Update to 7.8.2 (2376)
Thanks to @alabiaga and @marcelpinto for help with improvements for Android 12. https://github.com/DrKLO/Telegram/pull/1633 https://github.com/DrKLO/Telegram/pull/1636 https://github.com/DrKLO/Telegram/pull/1630
19
Dockerfile
|
@ -1,11 +1,11 @@
|
|||
FROM gradle:6.7.1-jdk8
|
||||
FROM gradle:6.7.1-jdk11
|
||||
|
||||
ENV ANDROID_SDK_URL https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
|
||||
ENV ANDROID_API_LEVEL android-30
|
||||
ENV ANDROID_BUILD_TOOLS_VERSION 30.0.3
|
||||
ENV ANDROID_SDK_URL https://dl.google.com/android/repository/commandlinetools-linux-7302050_latest.zip
|
||||
ENV ANDROID_API_LEVEL android-31
|
||||
ENV ANDROID_BUILD_TOOLS_VERSION 31.0.0
|
||||
ENV ANDROID_HOME /usr/local/android-sdk-linux
|
||||
ENV ANDROID_NDK_VERSION 21.4.7075529
|
||||
ENV ANDROID_VERSION 30
|
||||
ENV ANDROID_VERSION 31
|
||||
ENV ANDROID_NDK_HOME ${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/
|
||||
ENV PATH ${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
|
||||
|
||||
|
@ -15,12 +15,15 @@ RUN mkdir "$ANDROID_HOME" .android && \
|
|||
unzip sdk.zip && \
|
||||
rm sdk.zip
|
||||
|
||||
RUN yes | ${ANDROID_HOME}/tools/bin/sdkmanager --licenses
|
||||
RUN $ANDROID_HOME/tools/bin/sdkmanager --update
|
||||
RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
|
||||
RUN yes | ${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME --licenses
|
||||
RUN $ANDROID_HOME/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME --update
|
||||
RUN $ANDROID_HOME/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME "build-tools;30.0.3" \
|
||||
"build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
|
||||
"platforms;android-${ANDROID_VERSION}" \
|
||||
"platform-tools" \
|
||||
"ndk;$ANDROID_NDK_VERSION"
|
||||
RUN cp $ANDROID_HOME/build-tools/30.0.3/dx $ANDROID_HOME/build-tools/31.0.0/dx
|
||||
RUN cp $ANDROID_HOME/build-tools/30.0.3/lib/dx.jar $ANDROID_HOME/build-tools/31.0.0/lib/dx.jar
|
||||
ENV PATH ${ANDROID_NDK_HOME}:$PATH
|
||||
ENV PATH ${ANDROID_NDK_HOME}/prebuilt/linux-x86_64/bin/:$PATH
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.3'
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion '31.0.0'
|
||||
ndkVersion "21.4.7075529"
|
||||
|
||||
defaultConfig.applicationId = "org.telegram.messenger"
|
||||
|
@ -299,7 +299,7 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
defaultConfig.versionCode = 2372
|
||||
defaultConfig.versionCode = 2376
|
||||
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.all { output ->
|
||||
|
@ -318,7 +318,7 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
versionName "7.8.1"
|
||||
versionName "7.8.2"
|
||||
|
||||
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']
|
||||
|
||||
|
|
|
@ -482,7 +482,7 @@ void Handshake::processHandshakeResponse(TLObject *message, int64_t messageId) {
|
|||
uint32_t paddedDataSize = 192;
|
||||
uint32_t encryptedDataSize = keySize + paddedDataSize + SHA256_DIGEST_LENGTH;
|
||||
uint32_t additionalSize = innerDataSize < paddedDataSize ? paddedDataSize - innerDataSize : 0;
|
||||
NativeByteBuffer *innerDataBuffer = BuffersStorage::getInstance().getFreeBuffer(encryptedDataSize + paddedDataSize + ivSize + SHA256_DIGEST_LENGTH);
|
||||
NativeByteBuffer *innerDataBuffer = BuffersStorage::getInstance().getFreeBuffer(encryptedDataSize + paddedDataSize + ivSize + SHA256_DIGEST_LENGTH + 256);
|
||||
|
||||
innerDataBuffer->position(encryptedDataSize);
|
||||
innerData->serializeToStream(innerDataBuffer);
|
||||
|
@ -518,12 +518,13 @@ void Handshake::processHandshakeResponse(TLObject *message, int64_t messageId) {
|
|||
}
|
||||
|
||||
bool ok = false;
|
||||
size_t resLen = BN_bn2bin(rsaKey->n, innerDataBuffer->bytes() + encryptedDataSize);
|
||||
uint32_t offset = encryptedDataSize + paddedDataSize + ivSize + SHA256_DIGEST_LENGTH;
|
||||
size_t resLen = BN_bn2bin(rsaKey->n, innerDataBuffer->bytes() + offset);
|
||||
const auto shift = (256 - resLen);
|
||||
|
||||
for (auto i = 0; i != 256; ++i) {
|
||||
const auto a = innerDataBuffer->bytes()[i];
|
||||
const auto b = (i < shift) ? 0 : innerDataBuffer->bytes()[encryptedDataSize + i - shift];
|
||||
const auto b = (i < shift) ? 0 : innerDataBuffer->bytes()[offset + i - shift];
|
||||
if (a > b) {
|
||||
break;
|
||||
} else if (a < b) {
|
||||
|
@ -544,9 +545,9 @@ void Handshake::processHandshakeResponse(TLObject *message, int64_t messageId) {
|
|||
BN_mod_exp(r, a, rsaKey->e, rsaKey->n, bnContext);
|
||||
uint32_t size = BN_num_bytes(r);
|
||||
auto rsaEncryptedData = new ByteArray(size >= 256 ? size : 256);
|
||||
size_t resLen = BN_bn2bin(r, rsaEncryptedData->bytes);
|
||||
if (256 - resLen > 0) {
|
||||
memset(rsaEncryptedData->bytes + resLen, 0, 256 - resLen);
|
||||
BN_bn2bin(r, rsaEncryptedData->bytes + (size < 256 ? (256 - size) : 0));
|
||||
if (256 - size > 0) {
|
||||
memset(rsaEncryptedData->bytes, 0, 256 - size);
|
||||
}
|
||||
BN_free(a);
|
||||
BN_free(r);
|
||||
|
|
|
@ -911,6 +911,8 @@ add_library(tgcalls STATIC
|
|||
voip/tgcalls/VideoCaptureInterface.cpp
|
||||
voip/tgcalls/VideoCaptureInterfaceImpl.cpp
|
||||
voip/tgcalls/AudioDeviceHelper.cpp
|
||||
voip/tgcalls/SctpDataChannelProviderInterfaceImpl.cpp
|
||||
voip/tgcalls/TurnCustomizerImpl.cpp
|
||||
voip/tgcalls/reference/InstanceImplReference.cpp
|
||||
voip/tgcalls/legacy/InstanceImplLegacy.cpp
|
||||
voip/tgcalls/group/GroupNetworkManager.cpp
|
||||
|
|
|
@ -45,7 +45,7 @@ int FormatPriority(const VideoFormat &format, const std::vector<std::string> &pr
|
|||
}
|
||||
return result;
|
||||
}();
|
||||
|
||||
|
||||
for (int i = 0; i < preferredCodecs.size(); i++) {
|
||||
for (const auto &name : kSupported) {
|
||||
if (absl::EqualsIgnoreCase(format.name, preferredCodecs[i]) && absl::EqualsIgnoreCase(format.name, name)) {
|
||||
|
@ -114,12 +114,6 @@ std::vector<VideoFormat>::const_iterator FindEqualFormat(
|
|||
});
|
||||
}
|
||||
|
||||
bool ContainsEqualFormat(
|
||||
const std::vector<VideoFormat> &list,
|
||||
const VideoFormat &format) {
|
||||
return FindEqualFormat(list, format) != list.end();
|
||||
}
|
||||
|
||||
void AddDefaultFeedbackParams(cricket::VideoCodec *codec) {
|
||||
// Don't add any feedback params for RED and ULPFEC.
|
||||
if (codec->name == cricket::kRedCodecName || codec->name == cricket::kUlpfecCodecName)
|
||||
|
|
|
@ -285,7 +285,6 @@ void EncryptedConnection::appendAdditionalMessages(rtc::CopyOnWriteBuffer &buffe
|
|||
}
|
||||
|
||||
const auto now = rtc::TimeMillis();
|
||||
auto someWereNotAdded = false;
|
||||
for (auto &resending : _myNotYetAckedMessages) {
|
||||
const auto sent = resending.lastSent;
|
||||
const auto when = sent
|
||||
|
@ -471,6 +470,7 @@ auto EncryptedConnection::processPacket(
|
|||
}
|
||||
const auto success = reader.ReadUInt32(¤tSeq);
|
||||
assert(success);
|
||||
(void)success;
|
||||
currentCounter = CounterFromSeq(currentSeq);
|
||||
|
||||
additionalMessage = true;
|
||||
|
|
|
@ -72,6 +72,7 @@ void Serialize(rtc::ByteBufferWriter &to, const cricket::Candidate &from) {
|
|||
std::string serialized;
|
||||
const auto success = iceCandidate.ToString(&serialized);
|
||||
assert(success);
|
||||
(void)success;
|
||||
Serialize(to, serialized);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "api/jsep_ice_candidate.h"
|
||||
#include "rtc_base/network_monitor_factory.h"
|
||||
|
||||
#include "TurnCustomizerImpl.h"
|
||||
#include "platform/PlatformInterface.h"
|
||||
|
||||
extern "C" {
|
||||
|
@ -61,24 +62,6 @@ private:
|
|||
std::string _value;
|
||||
};
|
||||
|
||||
class TurnCustomizerImpl : public webrtc::TurnCustomizer {
|
||||
public:
|
||||
TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
virtual ~TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
void MaybeModifyOutgoingStunMessage(cricket::PortInterface* port,
|
||||
cricket::StunMessage* message) override {
|
||||
message->AddAttribute(std::make_unique<cricket::StunByteStringAttribute>(cricket::STUN_ATTR_SOFTWARE, "Telegram "));
|
||||
}
|
||||
|
||||
bool AllowChannelData(cricket::PortInterface* port, const void *data, size_t size, bool payload) override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
NetworkManager::NetworkManager(
|
||||
rtc::Thread *thread,
|
||||
EncryptionKey encryptionKey,
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
#include "SctpDataChannelProviderInterfaceImpl.h"
|
||||
|
||||
#include "p2p/base/dtls_transport.h"
|
||||
|
||||
namespace tgcalls {
|
||||
|
||||
SctpDataChannelProviderInterfaceImpl::SctpDataChannelProviderInterfaceImpl(
|
||||
cricket::DtlsTransport *transportChannel,
|
||||
bool isOutgoing,
|
||||
std::function<void(bool)> onStateChanged,
|
||||
std::function<void()> onTerminated,
|
||||
std::function<void(std::string const &)> onMessageReceived,
|
||||
std::shared_ptr<Threads> threads
|
||||
) :
|
||||
_threads(std::move(threads)),
|
||||
_onStateChanged(onStateChanged),
|
||||
_onTerminated(onTerminated),
|
||||
_onMessageReceived(onMessageReceived) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_sctpTransportFactory.reset(new cricket::SctpTransportFactory(_threads->getNetworkThread()));
|
||||
|
||||
_sctpTransport = _sctpTransportFactory->CreateSctpTransport(transportChannel);
|
||||
_sctpTransport->SignalReadyToSendData.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpReadyToSendData);
|
||||
_sctpTransport->SignalDataReceived.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpDataReceived);
|
||||
_sctpTransport->SignalClosedAbruptly.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpClosedAbruptly);
|
||||
|
||||
webrtc::InternalDataChannelInit dataChannelInit;
|
||||
dataChannelInit.id = 0;
|
||||
dataChannelInit.open_handshake_role = isOutgoing ? webrtc::InternalDataChannelInit::kOpener : webrtc::InternalDataChannelInit::kAcker;
|
||||
_dataChannel = webrtc::SctpDataChannel::Create(
|
||||
this,
|
||||
"data",
|
||||
dataChannelInit,
|
||||
_threads->getNetworkThread(),
|
||||
_threads->getNetworkThread()
|
||||
);
|
||||
|
||||
_dataChannel->RegisterObserver(this);
|
||||
}
|
||||
|
||||
|
||||
SctpDataChannelProviderInterfaceImpl::~SctpDataChannelProviderInterfaceImpl() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->UnregisterObserver();
|
||||
_dataChannel->Close();
|
||||
_dataChannel = nullptr;
|
||||
|
||||
_sctpTransport = nullptr;
|
||||
_sctpTransportFactory.reset();
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::sendDataChannelMessage(std::string const &message) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (_isDataChannelOpen) {
|
||||
RTC_LOG(LS_INFO) << "Outgoing DataChannel message: " << message;
|
||||
|
||||
webrtc::DataBuffer buffer(message);
|
||||
_dataChannel->Send(buffer);
|
||||
} else {
|
||||
RTC_LOG(LS_INFO) << "Could not send an outgoing DataChannel message: the channel is not open";
|
||||
}
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::OnStateChange() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
auto state = _dataChannel->state();
|
||||
bool isDataChannelOpen = state == webrtc::DataChannelInterface::DataState::kOpen;
|
||||
if (_isDataChannelOpen != isDataChannelOpen) {
|
||||
_isDataChannelOpen = isDataChannelOpen;
|
||||
_onStateChanged(_isDataChannelOpen);
|
||||
}
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::OnMessage(const webrtc::DataBuffer& buffer) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (!buffer.binary) {
|
||||
std::string messageText(buffer.data.data(), buffer.data.data() + buffer.data.size());
|
||||
RTC_LOG(LS_INFO) << "Incoming DataChannel message: " << messageText;
|
||||
|
||||
_onMessageReceived(messageText);
|
||||
}
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::updateIsConnected(bool isConnected) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (isConnected) {
|
||||
if (!_isSctpTransportStarted) {
|
||||
_isSctpTransportStarted = true;
|
||||
_sctpTransport->Start(5000, 5000, 262144);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::sctpReadyToSendData() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->OnTransportReady(true);
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::sctpClosedAbruptly() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (_onTerminated) {
|
||||
_onTerminated();
|
||||
}
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::sctpDataReceived(const cricket::ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->OnDataReceived(params, buffer);
|
||||
}
|
||||
|
||||
bool SctpDataChannelProviderInterfaceImpl::SendData(int sid, const webrtc::SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, cricket::SendDataResult* result) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return _sctpTransport->SendData(sid, params, payload);
|
||||
}
|
||||
|
||||
bool SctpDataChannelProviderInterfaceImpl::ConnectDataChannel(webrtc::SctpDataChannel *data_channel) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::DisconnectDataChannel(webrtc::SctpDataChannel* data_channel) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::AddSctpDataStream(int sid) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_sctpTransport->OpenStream(sid);
|
||||
}
|
||||
|
||||
void SctpDataChannelProviderInterfaceImpl::RemoveSctpDataStream(int sid) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_threads->getNetworkThread()->Invoke<void>(RTC_FROM_HERE, [this, sid]() {
|
||||
_sctpTransport->ResetStream(sid);
|
||||
});
|
||||
}
|
||||
|
||||
bool SctpDataChannelProviderInterfaceImpl::ReadyToSendData() const {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return _sctpTransport->ReadyToSendData();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef TGCALLS_SCTP_DATA_CHANNEL_PROVIDER_IMPL_H
|
||||
#define TGCALLS_SCTP_DATA_CHANNEL_PROVIDER_IMPL_H
|
||||
|
||||
#include "media/sctp/sctp_transport_factory.h"
|
||||
#include "api/turn_customizer.h"
|
||||
#include "api/data_channel_interface.h"
|
||||
#include "pc/sctp_data_channel.h"
|
||||
#include "pc/sctp_transport.h"
|
||||
|
||||
#include "StaticThreads.h"
|
||||
|
||||
namespace cricket {
|
||||
class DtlsTransport;
|
||||
} // namespace cricket
|
||||
|
||||
namespace tgcalls {
|
||||
|
||||
class SctpDataChannelProviderInterfaceImpl : public sigslot::has_slots<>, public webrtc::SctpDataChannelProviderInterface, public webrtc::DataChannelObserver {
|
||||
public:
|
||||
SctpDataChannelProviderInterfaceImpl(
|
||||
cricket::DtlsTransport *transportChannel,
|
||||
bool isOutgoing,
|
||||
std::function<void(bool)> onStateChanged,
|
||||
std::function<void()> onTerminated,
|
||||
std::function<void(std::string const &)> onMessageReceived,
|
||||
std::shared_ptr<Threads> threads
|
||||
);
|
||||
virtual ~SctpDataChannelProviderInterfaceImpl();
|
||||
|
||||
void updateIsConnected(bool isConnected);
|
||||
void sendDataChannelMessage(std::string const &message);
|
||||
|
||||
virtual void OnStateChange() override;
|
||||
virtual void OnMessage(const webrtc::DataBuffer& buffer) override;
|
||||
virtual bool SendData(int sid, const webrtc::SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, cricket::SendDataResult* result = nullptr) override;
|
||||
virtual bool ConnectDataChannel(webrtc::SctpDataChannel *data_channel) override;
|
||||
virtual void DisconnectDataChannel(webrtc::SctpDataChannel* data_channel) override;
|
||||
virtual void AddSctpDataStream(int sid) override;
|
||||
virtual void RemoveSctpDataStream(int sid) override;
|
||||
virtual bool ReadyToSendData() const override;
|
||||
|
||||
private:
|
||||
void sctpReadyToSendData();
|
||||
void sctpClosedAbruptly();
|
||||
void sctpDataReceived(const cricket::ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Threads> _threads;
|
||||
std::function<void(bool)> _onStateChanged;
|
||||
std::function<void()> _onTerminated;
|
||||
std::function<void(std::string const &)> _onMessageReceived;
|
||||
|
||||
std::unique_ptr<cricket::SctpTransportFactory> _sctpTransportFactory;
|
||||
std::unique_ptr<cricket::SctpTransportInternal> _sctpTransport;
|
||||
rtc::scoped_refptr<webrtc::SctpDataChannel> _dataChannel;
|
||||
|
||||
bool _isSctpTransportStarted = false;
|
||||
bool _isDataChannelOpen = false;
|
||||
|
||||
};
|
||||
|
||||
} // namespace tgcalls
|
||||
|
||||
#endif
|
|
@ -64,7 +64,6 @@ public:
|
|||
network_->DisallowAllInvokes();
|
||||
media_ = create("tgc-media" + suffix);
|
||||
worker_ = create("tgc-work" + suffix);
|
||||
process_ = create("tgc-process" + suffix);
|
||||
worker_->DisallowAllInvokes();
|
||||
worker_->AllowInvokesToThread(network_.get());
|
||||
}
|
||||
|
@ -78,9 +77,6 @@ public:
|
|||
rtc::Thread *getWorkerThread() override {
|
||||
return worker_.get();
|
||||
}
|
||||
rtc::Thread *getProcessThread() override {
|
||||
return process_.get();
|
||||
}
|
||||
rtc::scoped_refptr<webrtc::SharedModuleThread> getSharedModuleThread() override {
|
||||
// This function must be called from a single thread because of SharedModuleThread implementation
|
||||
// So we don't care about making it thread safe
|
||||
|
@ -96,7 +92,6 @@ private:
|
|||
Thread network_;
|
||||
Thread media_;
|
||||
Thread worker_;
|
||||
Thread process_;
|
||||
rtc::scoped_refptr<webrtc::SharedModuleThread> shared_module_thread_;
|
||||
|
||||
static Thread create(const std::string &name) {
|
||||
|
@ -146,10 +141,6 @@ rtc::Thread *getWorkerThread() {
|
|||
return getThreads()->getWorkerThread();
|
||||
}
|
||||
|
||||
rtc::Thread *getProcessThread() {
|
||||
return getThreads()->getProcessThread();
|
||||
}
|
||||
|
||||
std::shared_ptr<Threads> &getThreads() {
|
||||
static std::shared_ptr<Threads> threads = std::make_shared<ThreadsImpl>(0);
|
||||
return threads;
|
||||
|
|
|
@ -20,7 +20,6 @@ public:
|
|||
virtual rtc::Thread *getNetworkThread() = 0;
|
||||
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
|
||||
|
@ -32,7 +31,6 @@ namespace StaticThreads {
|
|||
rtc::Thread *getNetworkThread();
|
||||
rtc::Thread *getMediaThread();
|
||||
rtc::Thread *getWorkerThread();
|
||||
rtc::Thread *getProcessThread();
|
||||
rtc::scoped_refptr<webrtc::SharedModuleThread> getSharedMoudleThread();
|
||||
std::shared_ptr<Threads> &getThreads();
|
||||
}
|
||||
|
|
21
TMessagesProj/jni/voip/tgcalls/TurnCustomizerImpl.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "TurnCustomizerImpl.h"
|
||||
|
||||
#include "api/transport/stun.h"
|
||||
|
||||
namespace tgcalls {
|
||||
|
||||
TurnCustomizerImpl::TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
TurnCustomizerImpl::~TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
void TurnCustomizerImpl::MaybeModifyOutgoingStunMessage(cricket::PortInterface* port, cricket::StunMessage* message) {
|
||||
message->AddAttribute(std::make_unique<cricket::StunByteStringAttribute>(cricket::STUN_ATTR_SOFTWARE, "Telegram "));
|
||||
}
|
||||
|
||||
bool TurnCustomizerImpl::AllowChannelData(cricket::PortInterface* port, const void *data, size_t size, bool payload) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
19
TMessagesProj/jni/voip/tgcalls/TurnCustomizerImpl.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef TGCALLS_TURN_CUSTOMIZER_H
|
||||
#define TGCALLS_TURN_CUSTOMIZER_H
|
||||
|
||||
#include "api/turn_customizer.h"
|
||||
|
||||
namespace tgcalls {
|
||||
|
||||
class TurnCustomizerImpl : public webrtc::TurnCustomizer {
|
||||
public:
|
||||
TurnCustomizerImpl();
|
||||
virtual ~TurnCustomizerImpl();
|
||||
|
||||
void MaybeModifyOutgoingStunMessage(cricket::PortInterface* port, cricket::StunMessage* message) override;
|
||||
bool AllowChannelData(cricket::PortInterface* port, const void *data, size_t size, bool payload) override;
|
||||
};
|
||||
|
||||
} // namespace tgcalls
|
||||
|
||||
#endif
|
|
@ -520,11 +520,14 @@ class AudioSinkImpl: public webrtc::AudioSinkInterface {
|
|||
public:
|
||||
struct Update {
|
||||
float level = 0.0f;
|
||||
std::shared_ptr<webrtc::AudioBuffer> buffer;
|
||||
std::shared_ptr<CombinedVad> vad;
|
||||
bool hasSpeech = false;
|
||||
|
||||
Update(float level_, webrtc::AudioBuffer *buffer_, std::shared_ptr<CombinedVad> vad_) :
|
||||
level(level_), buffer(std::shared_ptr<webrtc::AudioBuffer>(buffer_)), vad(vad_) {
|
||||
Update(float level_, bool hasSpech_) :
|
||||
level(level_), hasSpeech(hasSpech_) {
|
||||
}
|
||||
|
||||
Update(const Update &other) :
|
||||
level(other.level), hasSpeech(other.hasSpeech) {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -550,7 +553,7 @@ public:
|
|||
frame.ntp_time_ms = 0;
|
||||
_onAudioFrame(_channel_id.actualSsrc, frame);
|
||||
}
|
||||
if (_update && audio.channels == 1) {
|
||||
if (_update && audio.channels == 1) {
|
||||
const int16_t *samples = (const int16_t *)audio.data;
|
||||
int numberOfSamplesInFrame = (int)audio.samples_per_channel;
|
||||
|
||||
|
@ -573,17 +576,7 @@ public:
|
|||
float level = ((float)(_peak)) / 8000.0f;
|
||||
_peak = 0;
|
||||
_peakCount = 0;
|
||||
|
||||
webrtc::AudioBuffer *buffer;
|
||||
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);
|
||||
} else {
|
||||
buffer = nullptr;
|
||||
}
|
||||
|
||||
_update(Update(level, buffer, _vad));
|
||||
_update(Update(level, level >= 1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2929,12 +2922,6 @@ public:
|
|||
}
|
||||
|
||||
void setIsMuted(bool isMuted) {
|
||||
if (_videoContentType == VideoContentType::Screencast) {
|
||||
if (isMuted) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_isMuted == isMuted) {
|
||||
return;
|
||||
}
|
||||
|
@ -3011,23 +2998,23 @@ public:
|
|||
const auto weak = std::weak_ptr<GroupInstanceCustomInternal>(shared_from_this());
|
||||
|
||||
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 = voice;
|
||||
strong->_audioLevels[ssrc] = mappedUpdate;
|
||||
});
|
||||
});
|
||||
};
|
||||
}*/
|
||||
if (ssrc.actualSsrc != ssrc.networkSsrc) {
|
||||
if (_audioLevelsUpdated) {
|
||||
onAudioSinkUpdate = [weak, ssrc = ssrc, threads = _threads](AudioSinkImpl::Update update) {
|
||||
threads->getMediaThread()->PostTask(RTC_FROM_HERE, [weak, ssrc, update]() {
|
||||
auto strong = weak.lock();
|
||||
if (!strong) {
|
||||
return;
|
||||
}
|
||||
InternalGroupLevelValue updated;
|
||||
updated.value.level = update.level;
|
||||
updated.value.voice = update.hasSpeech;
|
||||
updated.timestamp = rtc::TimeMillis();
|
||||
strong->_audioLevels.insert(std::make_pair(ChannelId(ssrc), std::move(updated)));
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<IncomingAudioChannel> channel(new IncomingAudioChannel(
|
||||
_channelManager.get(),
|
||||
|
|
|
@ -17,194 +17,12 @@
|
|||
#include "modules/rtp_rtcp/source/rtp_utility.h"
|
||||
#include "modules/rtp_rtcp/source/byte_io.h"
|
||||
#include "platform/PlatformInterface.h"
|
||||
|
||||
#include "TurnCustomizerImpl.h"
|
||||
#include "SctpDataChannelProviderInterfaceImpl.h"
|
||||
#include "StaticThreads.h"
|
||||
|
||||
namespace tgcalls {
|
||||
|
||||
class TurnCustomizerImpl : public webrtc::TurnCustomizer {
|
||||
public:
|
||||
TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
virtual ~TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
void MaybeModifyOutgoingStunMessage(cricket::PortInterface* port,
|
||||
cricket::StunMessage* message) override {
|
||||
message->AddAttribute(std::make_unique<cricket::StunByteStringAttribute>(cricket::STUN_ATTR_SOFTWARE, "Telegram "));
|
||||
}
|
||||
|
||||
bool AllowChannelData(cricket::PortInterface* port, const void *data, size_t size, bool payload) override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class SctpDataChannelProviderInterfaceImpl : public sigslot::has_slots<>, public webrtc::SctpDataChannelProviderInterface, public webrtc::DataChannelObserver {
|
||||
public:
|
||||
SctpDataChannelProviderInterfaceImpl(
|
||||
cricket::DtlsTransport *transportChannel,
|
||||
std::function<void(bool)> onStateChanged,
|
||||
std::function<void()> onTerminated,
|
||||
std::function<void(std::string const &)> onMessageReceived,
|
||||
std::shared_ptr<Threads> threads
|
||||
) :
|
||||
_threads(std::move(threads)),
|
||||
_onStateChanged(onStateChanged),
|
||||
_onTerminated(onTerminated),
|
||||
_onMessageReceived(onMessageReceived) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_sctpTransportFactory.reset(new cricket::SctpTransportFactory(_threads->getNetworkThread()));
|
||||
|
||||
_sctpTransport = _sctpTransportFactory->CreateSctpTransport(transportChannel);
|
||||
_sctpTransport->SignalReadyToSendData.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpReadyToSendData);
|
||||
_sctpTransport->SignalDataReceived.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpDataReceived);
|
||||
_sctpTransport->SignalClosedAbruptly.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpClosedAbruptly);
|
||||
|
||||
webrtc::InternalDataChannelInit dataChannelInit;
|
||||
dataChannelInit.id = 0;
|
||||
_dataChannel = webrtc::SctpDataChannel::Create(
|
||||
this,
|
||||
"data",
|
||||
dataChannelInit,
|
||||
_threads->getNetworkThread(),
|
||||
_threads->getNetworkThread()
|
||||
);
|
||||
|
||||
_dataChannel->RegisterObserver(this);
|
||||
}
|
||||
|
||||
virtual ~SctpDataChannelProviderInterfaceImpl() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->UnregisterObserver();
|
||||
_dataChannel->Close();
|
||||
_dataChannel = nullptr;
|
||||
|
||||
_sctpTransport = nullptr;
|
||||
_sctpTransportFactory.reset();
|
||||
}
|
||||
|
||||
void sendDataChannelMessage(std::string const &message) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (_isDataChannelOpen) {
|
||||
RTC_LOG(LS_INFO) << "Outgoing DataChannel message: " << message;
|
||||
|
||||
webrtc::DataBuffer buffer(message);
|
||||
_dataChannel->Send(buffer);
|
||||
} else {
|
||||
RTC_LOG(LS_INFO) << "Could not send an outgoing DataChannel message: the channel is not open";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnStateChange() override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
auto state = _dataChannel->state();
|
||||
bool isDataChannelOpen = state == webrtc::DataChannelInterface::DataState::kOpen;
|
||||
if (_isDataChannelOpen != isDataChannelOpen) {
|
||||
_isDataChannelOpen = isDataChannelOpen;
|
||||
_onStateChanged(_isDataChannelOpen);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnMessage(const webrtc::DataBuffer& buffer) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (!buffer.binary) {
|
||||
std::string messageText(buffer.data.data(), buffer.data.data() + buffer.data.size());
|
||||
RTC_LOG(LS_INFO) << "Incoming DataChannel message: " << messageText;
|
||||
|
||||
_onMessageReceived(messageText);
|
||||
}
|
||||
}
|
||||
|
||||
void updateIsConnected(bool isConnected) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (isConnected) {
|
||||
if (!_isSctpTransportStarted) {
|
||||
_isSctpTransportStarted = true;
|
||||
_sctpTransport->Start(5000, 5000, 262144);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sctpReadyToSendData() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->OnTransportReady(true);
|
||||
}
|
||||
|
||||
void sctpClosedAbruptly() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (_onTerminated) {
|
||||
_onTerminated();
|
||||
}
|
||||
}
|
||||
|
||||
void sctpDataReceived(const cricket::ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->OnDataReceived(params, buffer);
|
||||
}
|
||||
|
||||
virtual bool SendData(int sid, const webrtc::SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, cricket::SendDataResult* result) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return _sctpTransport->SendData(sid, params, payload);
|
||||
}
|
||||
|
||||
virtual bool ConnectDataChannel(webrtc::SctpDataChannel *data_channel) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void DisconnectDataChannel(webrtc::SctpDataChannel* data_channel) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
virtual void AddSctpDataStream(int sid) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_sctpTransport->OpenStream(sid);
|
||||
}
|
||||
|
||||
virtual void RemoveSctpDataStream(int sid) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_threads->getNetworkThread()->Invoke<void>(RTC_FROM_HERE, [this, sid]() {
|
||||
_sctpTransport->ResetStream(sid);
|
||||
});
|
||||
}
|
||||
|
||||
virtual bool ReadyToSendData() const override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return _sctpTransport->ReadyToSendData();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Threads> _threads;
|
||||
std::function<void(bool)> _onStateChanged;
|
||||
std::function<void()> _onTerminated;
|
||||
std::function<void(std::string const &)> _onMessageReceived;
|
||||
|
||||
std::unique_ptr<cricket::SctpTransportFactory> _sctpTransportFactory;
|
||||
std::unique_ptr<cricket::SctpTransportInternal> _sctpTransport;
|
||||
rtc::scoped_refptr<webrtc::SctpDataChannel> _dataChannel;
|
||||
|
||||
bool _isSctpTransportStarted = false;
|
||||
bool _isDataChannelOpen = false;
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
kRtcpExpectedVersion = 2,
|
||||
kRtcpMinHeaderLength = 4,
|
||||
|
@ -589,6 +407,7 @@ void GroupNetworkManager::restartDataChannel() {
|
|||
const auto weak = std::weak_ptr<GroupNetworkManager>(shared_from_this());
|
||||
_dataChannelInterface.reset(new SctpDataChannelProviderInterfaceImpl(
|
||||
_dtlsTransport.get(),
|
||||
true,
|
||||
[weak, threads = _threads](bool state) {
|
||||
assert(threads->getNetworkThread()->IsCurrent());
|
||||
const auto strong = weak.lock();
|
||||
|
|
|
@ -13,184 +13,12 @@
|
|||
#include "p2p/base/dtls_transport_factory.h"
|
||||
#include "pc/dtls_srtp_transport.h"
|
||||
#include "pc/dtls_transport.h"
|
||||
|
||||
#include "TurnCustomizerImpl.h"
|
||||
#include "SctpDataChannelProviderInterfaceImpl.h"
|
||||
#include "StaticThreads.h"
|
||||
|
||||
namespace tgcalls {
|
||||
|
||||
class TurnCustomizerImpl : public webrtc::TurnCustomizer {
|
||||
public:
|
||||
TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
virtual ~TurnCustomizerImpl() {
|
||||
}
|
||||
|
||||
void MaybeModifyOutgoingStunMessage(cricket::PortInterface* port,
|
||||
cricket::StunMessage* message) override {
|
||||
message->AddAttribute(std::make_unique<cricket::StunByteStringAttribute>(cricket::STUN_ATTR_SOFTWARE, "Telegram "));
|
||||
}
|
||||
|
||||
bool AllowChannelData(cricket::PortInterface* port, const void *data, size_t size, bool payload) override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class SctpDataChannelProviderInterfaceImpl : public sigslot::has_slots<>, public webrtc::SctpDataChannelProviderInterface, public webrtc::DataChannelObserver {
|
||||
public:
|
||||
SctpDataChannelProviderInterfaceImpl(
|
||||
cricket::DtlsTransport *transportChannel,
|
||||
bool isOutgoing,
|
||||
std::function<void(bool)> onStateChanged,
|
||||
std::function<void(std::string const &)> onMessageReceived,
|
||||
std::shared_ptr<Threads> threads
|
||||
) :
|
||||
_threads(std::move(threads)),
|
||||
_onStateChanged(onStateChanged),
|
||||
_onMessageReceived(onMessageReceived) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_sctpTransportFactory.reset(new cricket::SctpTransportFactory(_threads->getNetworkThread()));
|
||||
|
||||
_sctpTransport = _sctpTransportFactory->CreateSctpTransport(transportChannel);
|
||||
_sctpTransport->SignalReadyToSendData.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpReadyToSendData);
|
||||
_sctpTransport->SignalDataReceived.connect(this, &SctpDataChannelProviderInterfaceImpl::sctpDataReceived);
|
||||
|
||||
webrtc::InternalDataChannelInit dataChannelInit;
|
||||
dataChannelInit.id = 0;
|
||||
dataChannelInit.open_handshake_role = isOutgoing ? webrtc::InternalDataChannelInit::kOpener : webrtc::InternalDataChannelInit::kAcker;
|
||||
_dataChannel = webrtc::SctpDataChannel::Create(
|
||||
this,
|
||||
"data",
|
||||
dataChannelInit,
|
||||
_threads->getNetworkThread(),
|
||||
_threads->getNetworkThread()
|
||||
);
|
||||
|
||||
_dataChannel->RegisterObserver(this);
|
||||
}
|
||||
|
||||
virtual ~SctpDataChannelProviderInterfaceImpl() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->UnregisterObserver();
|
||||
_dataChannel->Close();
|
||||
_dataChannel = nullptr;
|
||||
|
||||
_sctpTransport = nullptr;
|
||||
_sctpTransportFactory.reset();
|
||||
}
|
||||
|
||||
void sendDataChannelMessage(std::string const &message) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (_isDataChannelOpen) {
|
||||
RTC_LOG(LS_INFO) << "Outgoing DataChannel message: " << message;
|
||||
|
||||
webrtc::DataBuffer buffer(message);
|
||||
_dataChannel->Send(buffer);
|
||||
} else {
|
||||
RTC_LOG(LS_INFO) << "Could not send an outgoing DataChannel message: the channel is not open";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnStateChange() override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
auto state = _dataChannel->state();
|
||||
bool isDataChannelOpen = state == webrtc::DataChannelInterface::DataState::kOpen;
|
||||
if (_isDataChannelOpen != isDataChannelOpen) {
|
||||
_isDataChannelOpen = isDataChannelOpen;
|
||||
_onStateChanged(_isDataChannelOpen);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnMessage(const webrtc::DataBuffer& buffer) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (!buffer.binary) {
|
||||
std::string messageText(buffer.data.data(), buffer.data.data() + buffer.data.size());
|
||||
RTC_LOG(LS_INFO) << "Incoming DataChannel message: " << messageText;
|
||||
|
||||
_onMessageReceived(messageText);
|
||||
}
|
||||
}
|
||||
|
||||
void updateIsConnected(bool isConnected) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
if (isConnected) {
|
||||
if (!_isSctpTransportStarted) {
|
||||
_isSctpTransportStarted = true;
|
||||
_sctpTransport->Start(5000, 5000, 262144);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sctpReadyToSendData() {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->OnTransportReady(true);
|
||||
}
|
||||
|
||||
void sctpDataReceived(const cricket::ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer) {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_dataChannel->OnDataReceived(params, buffer);
|
||||
}
|
||||
|
||||
virtual bool SendData(const cricket::SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, cricket::SendDataResult* result) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return _sctpTransport->SendData(params, payload);
|
||||
}
|
||||
|
||||
virtual bool ConnectDataChannel(webrtc::SctpDataChannel *data_channel) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void DisconnectDataChannel(webrtc::SctpDataChannel* data_channel) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
virtual void AddSctpDataStream(int sid) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_sctpTransport->OpenStream(sid);
|
||||
}
|
||||
|
||||
virtual void RemoveSctpDataStream(int sid) override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
_threads->getNetworkThread()->Invoke<void>(RTC_FROM_HERE, [this, sid]() {
|
||||
_sctpTransport->ResetStream(sid);
|
||||
});
|
||||
}
|
||||
|
||||
virtual bool ReadyToSendData() const override {
|
||||
assert(_threads->getNetworkThread()->IsCurrent());
|
||||
|
||||
return _sctpTransport->ReadyToSendData();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Threads> _threads;
|
||||
std::function<void(bool)> _onStateChanged;
|
||||
std::function<void(std::string const &)> _onMessageReceived;
|
||||
|
||||
std::unique_ptr<cricket::SctpTransportFactory> _sctpTransportFactory;
|
||||
std::unique_ptr<cricket::SctpTransportInternal> _sctpTransport;
|
||||
rtc::scoped_refptr<webrtc::SctpDataChannel> _dataChannel;
|
||||
|
||||
bool _isSctpTransportStarted = false;
|
||||
bool _isDataChannelOpen = false;
|
||||
|
||||
};
|
||||
|
||||
webrtc::CryptoOptions NativeNetworkingImpl::getDefaulCryptoOptions() {
|
||||
auto options = webrtc::CryptoOptions();
|
||||
options.srtp.enable_aes128_sha1_80_crypto_cipher = true;
|
||||
|
@ -355,6 +183,14 @@ void NativeNetworkingImpl::start() {
|
|||
}
|
||||
strong->_dataChannelStateUpdated(state);
|
||||
},
|
||||
[weak, threads = _threads]() {
|
||||
assert(threads->getNetworkThread()->IsCurrent());
|
||||
const auto strong = weak.lock();
|
||||
if (!strong) {
|
||||
return;
|
||||
}
|
||||
//strong->restartDataChannel();
|
||||
},
|
||||
[weak, threads = _threads](std::string const &message) {
|
||||
assert(threads->getNetworkThread()->IsCurrent());
|
||||
const auto strong = weak.lock();
|
||||
|
|
|
@ -423,7 +423,7 @@
|
|||
android:name=".voip.CallNotificationSoundProvider"
|
||||
android:exported="true"/>
|
||||
|
||||
<receiver android:name=".ChatsWidgetProvider">
|
||||
<receiver android:name=".ChatsWidgetProvider" android:exported="false">
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/chats_widget_info" />
|
||||
<intent-filter>
|
||||
|
@ -435,7 +435,7 @@
|
|||
android:permission="android.permission.BIND_REMOTEVIEWS"
|
||||
android:exported="false" />
|
||||
|
||||
<receiver android:name=".ContactsWidgetProvider">
|
||||
<receiver android:name=".ContactsWidgetProvider" android:exported="false">
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/contacts_widget_info" />
|
||||
<intent-filter>
|
||||
|
|
|
@ -1747,6 +1747,9 @@ public class AndroidUtilities {
|
|||
}
|
||||
|
||||
public static void runOnUIThread(Runnable runnable, long delay) {
|
||||
if (ApplicationLoader.applicationHandler == null) {
|
||||
return;
|
||||
}
|
||||
if (delay == 0) {
|
||||
ApplicationLoader.applicationHandler.post(runnable);
|
||||
} else {
|
||||
|
@ -1755,6 +1758,9 @@ public class AndroidUtilities {
|
|||
}
|
||||
|
||||
public static void cancelRunOnUIThread(Runnable runnable) {
|
||||
if (ApplicationLoader.applicationHandler == null) {
|
||||
return;
|
||||
}
|
||||
ApplicationLoader.applicationHandler.removeCallbacks(runnable);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,12 @@ public class BuildVars {
|
|||
|
||||
public static boolean DEBUG_VERSION = false;
|
||||
public static boolean DEBUG_PRIVATE_VERSION = false;
|
||||
public static boolean LOGS_ENABLED = true;
|
||||
public static boolean LOGS_ENABLED = false;
|
||||
public static boolean USE_CLOUD_STRINGS = true;
|
||||
public static boolean CHECK_UPDATES = true;
|
||||
public static boolean NO_SCOPED_STORAGE = true/* || Build.VERSION.SDK_INT <= 28*/;
|
||||
public static int BUILD_VERSION = 2372;
|
||||
public static String BUILD_VERSION_STRING = "7.8.0";
|
||||
public static int BUILD_VERSION = 2376;
|
||||
public static String BUILD_VERSION_STRING = "7.8.2";
|
||||
public static int APP_ID = 4;
|
||||
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
||||
public static String APPCENTER_HASH = "a5b5c4f5-51da-dedc-9918-d9766a22ca7c";
|
||||
|
|
|
@ -28,13 +28,13 @@ public class ChatsWidgetProvider extends AppWidgetProvider {
|
|||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
for (int i = 0; i < appWidgetIds.length; i++) {
|
||||
int appWidgetId = appWidgetIds[i];
|
||||
updateWidget(context, appWidgetManager, appWidgetId, false);
|
||||
updateWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
|
||||
updateWidget(context, appWidgetManager, appWidgetId, true);
|
||||
updateWidget(context, appWidgetManager, appWidgetId);
|
||||
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ public class ChatsWidgetProvider extends AppWidgetProvider {
|
|||
return n - 1;
|
||||
}
|
||||
|
||||
public static void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, boolean edit) {
|
||||
public static void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
ApplicationLoader.postInitApplication();
|
||||
Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
|
||||
int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
|
||||
|
@ -80,6 +80,11 @@ public class ChatsWidgetProvider extends AppWidgetProvider {
|
|||
int id;
|
||||
if (!deleted) {
|
||||
int accountId = preferences.getInt("account" + appWidgetId, -1);
|
||||
if (accountId == -1) {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("account" + appWidgetId, UserConfig.selectedAccount);
|
||||
editor.putInt("type" + appWidgetId, EditWidgetActivity.TYPE_CHATS).commit();
|
||||
}
|
||||
ArrayList<Long> selectedDialogs = new ArrayList<>();
|
||||
if (accountId >= 0) {
|
||||
AccountInstance.getInstance(accountId).getMessagesStorage().getWidgetDialogIds(appWidgetId, EditWidgetActivity.TYPE_CHATS, selectedDialogs, null, null, false);
|
||||
|
@ -109,8 +114,6 @@ public class ChatsWidgetProvider extends AppWidgetProvider {
|
|||
|
||||
rv.setPendingIntentTemplate(R.id.list_view, contentIntent);
|
||||
appWidgetManager.updateAppWidget(appWidgetId, rv);
|
||||
if (edit) {
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
|
||||
}
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -327,9 +327,11 @@ class ChatsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
|
|||
rv.setTextViewText(R.id.shortcut_widget_item_badge, String.format("%d", dialog.unread_count));
|
||||
rv.setViewVisibility(R.id.shortcut_widget_item_badge, View.VISIBLE);
|
||||
if (accountInstance.getMessagesController().isDialogMuted(dialog.id)) {
|
||||
rv.setInt(R.id.shortcut_widget_item_badge, "setBackgroundResource", R.drawable.widget_counter_muted);
|
||||
rv.setBoolean(R.id.shortcut_widget_item_badge, "setEnabled", false);
|
||||
rv.setInt(R.id.shortcut_widget_item_badge, "setBackgroundResource", R.drawable.widget_badge_muted_background);
|
||||
} else {
|
||||
rv.setInt(R.id.shortcut_widget_item_badge, "setBackgroundResource", R.drawable.widget_counter);
|
||||
rv.setBoolean(R.id.shortcut_widget_item_badge, "setEnabled", true);
|
||||
rv.setInt(R.id.shortcut_widget_item_badge, "setBackgroundResource", R.drawable.widget_badge_background);
|
||||
}
|
||||
} else {
|
||||
rv.setViewVisibility(R.id.shortcut_widget_item_badge, View.GONE);
|
||||
|
|
|
@ -28,7 +28,7 @@ public class ContactsWidgetProvider extends AppWidgetProvider {
|
|||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
for (int i = 0; i < appWidgetIds.length; i++) {
|
||||
int appWidgetId = appWidgetIds[i];
|
||||
updateWidget(context, appWidgetManager, appWidgetId, false);
|
||||
updateWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class ContactsWidgetProvider extends AppWidgetProvider {
|
|||
|
||||
@Override
|
||||
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
|
||||
updateWidget(context, appWidgetManager, appWidgetId, true);
|
||||
updateWidget(context, appWidgetManager, appWidgetId);
|
||||
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ public class ContactsWidgetProvider extends AppWidgetProvider {
|
|||
return n - 1;
|
||||
}
|
||||
|
||||
public static void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, boolean edit) {
|
||||
public static void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
ApplicationLoader.postInitApplication();
|
||||
Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
|
||||
int maxHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
|
||||
|
@ -80,6 +80,11 @@ public class ContactsWidgetProvider extends AppWidgetProvider {
|
|||
int id;
|
||||
if (!deleted) {
|
||||
int accountId = preferences.getInt("account" + appWidgetId, -1);
|
||||
if (accountId == -1) {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("account" + appWidgetId, UserConfig.selectedAccount);
|
||||
editor.putInt("type" + appWidgetId, EditWidgetActivity.TYPE_CHATS).commit();
|
||||
}
|
||||
ArrayList<Long> selectedDialogs = new ArrayList<>();
|
||||
if (accountId >= 0) {
|
||||
AccountInstance.getInstance(accountId).getMessagesStorage().getWidgetDialogIds(appWidgetId, EditWidgetActivity.TYPE_CONTACTS, selectedDialogs, null, null, false);
|
||||
|
@ -111,8 +116,6 @@ public class ContactsWidgetProvider extends AppWidgetProvider {
|
|||
rv.setPendingIntentTemplate(R.id.list_view, contentIntent);
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, rv);
|
||||
if (edit) {
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
|
||||
}
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -899,7 +899,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyToMessage, AbstractMap<Integer, TLRPC.User> users, AbstractMap<Integer, TLRPC.Chat> chats, SparseArray<TLRPC.User> sUsers, SparseArray<TLRPC.Chat> sChats, boolean generateLayout, boolean checkMediaExists, long eid) {
|
||||
Theme.createCommonChatResources(null);
|
||||
Theme.createCommonChatResources();
|
||||
|
||||
currentAccount = accountNum;
|
||||
messageOwner = message;
|
||||
|
@ -2363,7 +2363,7 @@ public class MessageObject {
|
|||
}
|
||||
wantedBotKeyboardWidth = 0;
|
||||
if (messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup || messageOwner.reactions != null && !messageOwner.reactions.results.isEmpty()) {
|
||||
Theme.createCommonChatResources(null);
|
||||
Theme.createCommonChatResources();
|
||||
if (botButtonsLayout == null) {
|
||||
botButtonsLayout = new StringBuilder();
|
||||
} else {
|
||||
|
|
|
@ -2474,12 +2474,12 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
}
|
||||
if (chatsWidgets != null) {
|
||||
for (int a = 0, N = chatsWidgets.size(); a < N; a++) {
|
||||
ChatsWidgetProvider.updateWidget(ApplicationLoader.applicationContext, appWidgetManager, chatsWidgets.get(a), true);
|
||||
ChatsWidgetProvider.updateWidget(ApplicationLoader.applicationContext, appWidgetManager, chatsWidgets.get(a));
|
||||
}
|
||||
}
|
||||
if (contactsWidgets != null) {
|
||||
for (int a = 0, N = contactsWidgets.size(); a < N; a++) {
|
||||
ContactsWidgetProvider.updateWidget(ApplicationLoader.applicationContext, appWidgetManager, contactsWidgets.get(a), true);
|
||||
ContactsWidgetProvider.updateWidget(ApplicationLoader.applicationContext, appWidgetManager, contactsWidgets.get(a));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ import androidx.core.app.NotificationManagerCompat;
|
|||
import androidx.core.app.Person;
|
||||
import androidx.core.app.RemoteInput;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.core.content.LocusIdCompat;
|
||||
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
|
@ -2749,11 +2750,22 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
try {
|
||||
String id = "ndid_" + did;
|
||||
|
||||
Intent shortcutIntent = new Intent(ApplicationLoader.applicationContext, OpenChatReceiver.class);
|
||||
shortcutIntent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE);
|
||||
if (did > 0) {
|
||||
shortcutIntent.putExtra("userId", did);
|
||||
} else {
|
||||
shortcutIntent.putExtra("chatId", -did);
|
||||
}
|
||||
|
||||
ShortcutInfoCompat.Builder shortcutBuilder = new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, id)
|
||||
.setShortLabel(chat != null ? name : UserObject.getFirstName(user))
|
||||
.setLongLabel(name)
|
||||
.setIntent(new Intent(Intent.ACTION_DEFAULT))
|
||||
.setLongLived(true);
|
||||
.setIntent(shortcutIntent)
|
||||
.setLongLived(true)
|
||||
.setLocusId(new LocusIdCompat(id));
|
||||
|
||||
Bitmap avatar = null;
|
||||
if (person != null) {
|
||||
|
@ -2763,11 +2775,9 @@ public class NotificationsController extends BaseController {
|
|||
avatar = person.getIcon().getBitmap();
|
||||
}
|
||||
}
|
||||
ArrayList<ShortcutInfoCompat> arrayList = new ArrayList<>(1);
|
||||
arrayList.add(shortcutBuilder.build());
|
||||
ShortcutManagerCompat.addDynamicShortcuts(ApplicationLoader.applicationContext, arrayList);
|
||||
builder.setShortcutId(id);
|
||||
NotificationCompat.BubbleMetadata.Builder bubbleBuilder = new NotificationCompat.BubbleMetadata.Builder();
|
||||
ShortcutInfoCompat shortcut = shortcutBuilder.build();
|
||||
ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, shortcut);
|
||||
builder.setShortcutInfo(shortcut);
|
||||
Intent intent = new Intent(ApplicationLoader.applicationContext, BubbleActivity.class);
|
||||
intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE);
|
||||
if (did > 0) {
|
||||
|
@ -2776,19 +2786,21 @@ public class NotificationsController extends BaseController {
|
|||
intent.putExtra("chatId", -did);
|
||||
}
|
||||
intent.putExtra("currentAccount", currentAccount);
|
||||
bubbleBuilder.setIntent(PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
IconCompat icon;
|
||||
if (avatar != null) {
|
||||
icon = IconCompat.createWithAdaptiveBitmap(avatar);
|
||||
} else if (user != null) {
|
||||
icon = IconCompat.createWithResource(ApplicationLoader.applicationContext, user.bot ? R.drawable.book_bot : R.drawable.book_user);
|
||||
} else {
|
||||
icon = IconCompat.createWithResource(ApplicationLoader.applicationContext, R.drawable.book_group);
|
||||
}
|
||||
NotificationCompat.BubbleMetadata.Builder bubbleBuilder =
|
||||
new NotificationCompat.BubbleMetadata.Builder(
|
||||
PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT),
|
||||
icon);
|
||||
bubbleBuilder.setSuppressNotification(opened_dialog_id == did);
|
||||
bubbleBuilder.setAutoExpandBubble(false);
|
||||
bubbleBuilder.setDesiredHeight(AndroidUtilities.dp(640));
|
||||
if (avatar != null) {
|
||||
bubbleBuilder.setIcon(IconCompat.createWithAdaptiveBitmap(avatar));
|
||||
} else {
|
||||
if (user != null) {
|
||||
bubbleBuilder.setIcon(IconCompat.createWithResource(ApplicationLoader.applicationContext, user.bot ? R.drawable.book_bot : R.drawable.book_user));
|
||||
} else {
|
||||
bubbleBuilder.setIcon(IconCompat.createWithResource(ApplicationLoader.applicationContext, R.drawable.book_group));
|
||||
}
|
||||
}
|
||||
builder.setBubbleMetadata(bubbleBuilder.build());
|
||||
return id;
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -284,15 +284,22 @@ public class SharedConfig {
|
|||
}
|
||||
if (pendingAppUpdate != null) {
|
||||
long updateTime = 0;
|
||||
int updateVerstion;
|
||||
int updateVersion = 0;
|
||||
String updateVersionString = null;
|
||||
try {
|
||||
PackageInfo packageInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0);
|
||||
updateVerstion = packageInfo.versionCode;
|
||||
updateVersion = packageInfo.versionCode;
|
||||
updateVersionString = packageInfo.versionName;
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
updateVerstion = BuildVars.BUILD_VERSION;
|
||||
}
|
||||
if (pendingAppUpdateBuildVersion != updateVerstion) {
|
||||
if (updateVersion == 0) {
|
||||
updateVersion = BuildVars.BUILD_VERSION;
|
||||
}
|
||||
if (updateVersionString == null) {
|
||||
updateVersionString = BuildVars.BUILD_VERSION_STRING;
|
||||
}
|
||||
if (pendingAppUpdateBuildVersion != updateVersion || pendingAppUpdate.version == null || updateVersionString.compareTo(pendingAppUpdate.version) >= 0) {
|
||||
pendingAppUpdate = null;
|
||||
AndroidUtilities.runOnUIThread(SharedConfig::saveConfig);
|
||||
}
|
||||
|
@ -428,16 +435,29 @@ public class SharedConfig {
|
|||
return pendingAppUpdateBuildVersion == currentVersion;
|
||||
}
|
||||
|
||||
public static void setNewAppVersionAvailable(TLRPC.TL_help_appUpdate update) {
|
||||
pendingAppUpdate = update;
|
||||
public static boolean setNewAppVersionAvailable(TLRPC.TL_help_appUpdate update) {
|
||||
String updateVersionString = null;
|
||||
int versionCode = 0;
|
||||
try {
|
||||
PackageInfo packageInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0);
|
||||
pendingAppUpdateBuildVersion = packageInfo.versionCode;
|
||||
versionCode = packageInfo.versionCode;
|
||||
updateVersionString = packageInfo.versionName;
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
pendingAppUpdateBuildVersion = BuildVars.BUILD_VERSION;
|
||||
}
|
||||
if (versionCode == 0) {
|
||||
versionCode = BuildVars.BUILD_VERSION;
|
||||
}
|
||||
if (updateVersionString == null) {
|
||||
updateVersionString = BuildVars.BUILD_VERSION_STRING;
|
||||
}
|
||||
if (update.version == null || updateVersionString.compareTo(update.version) >= 0) {
|
||||
return false;
|
||||
}
|
||||
pendingAppUpdate = update;
|
||||
pendingAppUpdateBuildVersion = versionCode;
|
||||
saveConfig();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean checkPasscode(String passcode) {
|
||||
|
|
|
@ -65,16 +65,6 @@ public class UserConfig extends BaseController {
|
|||
public volatile byte[] savedSaltedPassword;
|
||||
public volatile long savedPasswordTime;
|
||||
|
||||
public String tonEncryptedData;
|
||||
public String tonPublicKey;
|
||||
public int tonPasscodeType = -1;
|
||||
public byte[] tonPasscodeSalt;
|
||||
public long tonPasscodeRetryInMs;
|
||||
public long tonLastUptimeMillis;
|
||||
public int tonBadPasscodeTries;
|
||||
public String tonKeyName;
|
||||
public boolean tonCreationFinished;
|
||||
|
||||
private static volatile UserConfig[] Instance = new UserConfig[UserConfig.MAX_ACCOUNT_COUNT];
|
||||
public static UserConfig getInstance(int num) {
|
||||
UserConfig localInstance = Instance[num];
|
||||
|
@ -146,21 +136,6 @@ public class UserConfig extends BaseController {
|
|||
editor.putInt("sharingMyLocationUntil", sharingMyLocationUntil);
|
||||
editor.putInt("lastMyLocationShareTime", lastMyLocationShareTime);
|
||||
editor.putBoolean("filtersLoaded", filtersLoaded);
|
||||
if (tonEncryptedData != null) {
|
||||
editor.putString("tonEncryptedData", tonEncryptedData);
|
||||
editor.putString("tonPublicKey", tonPublicKey);
|
||||
editor.putString("tonKeyName", tonKeyName);
|
||||
editor.putBoolean("tonCreationFinished", tonCreationFinished);
|
||||
if (tonPasscodeSalt != null) {
|
||||
editor.putInt("tonPasscodeType", tonPasscodeType);
|
||||
editor.putString("tonPasscodeSalt", Base64.encodeToString(tonPasscodeSalt, Base64.DEFAULT));
|
||||
editor.putLong("tonPasscodeRetryInMs", tonPasscodeRetryInMs);
|
||||
editor.putLong("tonLastUptimeMillis", tonLastUptimeMillis);
|
||||
editor.putInt("tonBadPasscodeTries", tonBadPasscodeTries);
|
||||
}
|
||||
} else {
|
||||
editor.remove("tonEncryptedData").remove("tonPublicKey").remove("tonKeyName").remove("tonPasscodeType").remove("tonPasscodeSalt").remove("tonPasscodeRetryInMs").remove("tonBadPasscodeTries").remove("tonLastUptimeMillis").remove("tonCreationFinished");
|
||||
}
|
||||
|
||||
editor.putInt("6migrateOffsetId", migrateOffsetId);
|
||||
if (migrateOffsetId != -1) {
|
||||
|
@ -282,25 +257,9 @@ public class UserConfig extends BaseController {
|
|||
notificationsSignUpSettingsLoaded = preferences.getBoolean("notificationsSignUpSettingsLoaded", false);
|
||||
autoDownloadConfigLoadTime = preferences.getLong("autoDownloadConfigLoadTime", 0);
|
||||
hasValidDialogLoadIds = preferences.contains("2dialogsLoadOffsetId") || preferences.getBoolean("hasValidDialogLoadIds", false);
|
||||
tonEncryptedData = preferences.getString("tonEncryptedData", null);
|
||||
tonPublicKey = preferences.getString("tonPublicKey", null);
|
||||
tonKeyName = preferences.getString("tonKeyName", "walletKey" + currentAccount);
|
||||
tonCreationFinished = preferences.getBoolean("tonCreationFinished", true);
|
||||
sharingMyLocationUntil = preferences.getInt("sharingMyLocationUntil", 0);
|
||||
lastMyLocationShareTime = preferences.getInt("lastMyLocationShareTime", 0);
|
||||
filtersLoaded = preferences.getBoolean("filtersLoaded", false);
|
||||
String salt = preferences.getString("tonPasscodeSalt", null);
|
||||
if (salt != null) {
|
||||
try {
|
||||
tonPasscodeSalt = Base64.decode(salt, Base64.DEFAULT);
|
||||
tonPasscodeType = preferences.getInt("tonPasscodeType", -1);
|
||||
tonPasscodeRetryInMs = preferences.getLong("tonPasscodeRetryInMs", 0);
|
||||
tonLastUptimeMillis = preferences.getLong("tonLastUptimeMillis", 0);
|
||||
tonBadPasscodeTries = preferences.getInt("tonBadPasscodeTries", 0);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String terms = preferences.getString("terms", null);
|
||||
|
@ -388,21 +347,8 @@ public class UserConfig extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public void clearTonConfig() {
|
||||
tonEncryptedData = null;
|
||||
tonKeyName = null;
|
||||
tonPublicKey = null;
|
||||
tonPasscodeType = -1;
|
||||
tonPasscodeSalt = null;
|
||||
tonCreationFinished = false;
|
||||
tonPasscodeRetryInMs = 0;
|
||||
tonLastUptimeMillis = 0;
|
||||
tonBadPasscodeTries = 0;
|
||||
}
|
||||
|
||||
public void clearConfig() {
|
||||
getPreferences().edit().clear().commit();
|
||||
clearTonConfig();
|
||||
|
||||
sharingMyLocationUntil = 0;
|
||||
lastMyLocationShareTime = 0;
|
||||
|
|
|
@ -644,9 +644,11 @@ public class ActionBarLayout extends FrameLayout {
|
|||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (!checkTransitionAnimation() && !inActionMode && !animationInProgress) {
|
||||
if (fragmentsStack.size() > 1) {
|
||||
if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && !startedTracking && !maybeStartTracking) {
|
||||
if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
BaseFragment currentFragment = fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
if (!currentFragment.isSwipeBackEnabled(ev)) {
|
||||
maybeStartTracking = false;
|
||||
startedTracking = false;
|
||||
return false;
|
||||
}
|
||||
startedTrackingPointerId = ev.getPointerId(0);
|
||||
|
|
|
@ -358,7 +358,11 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
||||
params.copyFrom(window.getAttributes());
|
||||
params.width = Math.min(maxWidth, calculatedWidth) + backgroundPaddings.left + backgroundPaddings.right;
|
||||
window.setAttributes(params);
|
||||
try {
|
||||
window.setAttributes(params);
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7369,7 +7369,7 @@ public class Theme {
|
|||
}
|
||||
}
|
||||
|
||||
public static void createCommonChatResources(Context context) {
|
||||
public static void createCommonChatResources() {
|
||||
synchronized (sync) {
|
||||
if (chat_msgTextPaint == null) {
|
||||
chat_msgTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
@ -7466,7 +7466,7 @@ public class Theme {
|
|||
}
|
||||
|
||||
public static void createChatResources(Context context, boolean fontsOnly) {
|
||||
createCommonChatResources(context);
|
||||
createCommonChatResources();
|
||||
|
||||
if (!fontsOnly && chat_msgInDrawable == null) {
|
||||
|
||||
|
@ -8687,6 +8687,7 @@ public class Theme {
|
|||
Drawable drawable = wallpaper;
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
wallpaperLoadTask = null;
|
||||
createCommonChatResources();
|
||||
applyChatServiceMessageColor(null, null, drawable);
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewWallpapper);
|
||||
});
|
||||
|
|
|
@ -8028,10 +8028,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
if (firstVisibleBlockNum >= 0) {
|
||||
int restore = Integer.MIN_VALUE;
|
||||
int oldAlpha = -1;
|
||||
int oldLinkAlpha = -1;
|
||||
if (alpha != 1.0f) {
|
||||
if (drawOnlyText) {
|
||||
oldAlpha = Theme.chat_msgTextPaint.getAlpha();
|
||||
oldLinkAlpha = Color.alpha(Theme.chat_msgTextPaint.linkColor);
|
||||
Theme.chat_msgTextPaint.setAlpha((int) (oldAlpha * alpha));
|
||||
Theme.chat_msgTextPaint.linkColor = ColorUtils.setAlphaComponent(Theme.chat_msgTextPaint.linkColor, (int) (oldLinkAlpha * alpha));
|
||||
} else {
|
||||
if (currentBackgroundDrawable != null) {
|
||||
int top = currentBackgroundDrawable.getBounds().top;
|
||||
|
@ -8083,6 +8086,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
}
|
||||
if (oldAlpha >= 0) {
|
||||
Theme.chat_msgTextPaint.setAlpha(oldAlpha);
|
||||
Theme.chat_msgTextPaint.linkColor = ColorUtils.setAlphaComponent(Theme.chat_msgTextPaint.linkColor, oldLinkAlpha);
|
||||
}
|
||||
|
||||
if (restore != Integer.MIN_VALUE) {
|
||||
|
@ -9817,6 +9821,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
return;
|
||||
}
|
||||
Theme.MessageDrawable drawable = a == 0 ? currentBackgroundDrawable : currentBackgroundSelectedDrawable;
|
||||
if (drawable == null) {
|
||||
continue;
|
||||
}
|
||||
int h = parentHeight;
|
||||
if (h == 0) {
|
||||
h = AndroidUtilities.displaySize.y;
|
||||
|
|
|
@ -3102,8 +3102,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
}
|
||||
if (!SharedConfig.smoothKeyboard) {
|
||||
setBottomClip(paddingBottom);
|
||||
} else if (!inPreviewMode) {
|
||||
} else if (!inPreviewMode && chatActivityEnterView.getEmojiPadding() == 0) {
|
||||
setBottomClip(AndroidUtilities.dp(48));
|
||||
} else {
|
||||
setBottomClip(0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
@ -6936,13 +6938,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
searchUpButton.setOnClickListener(view -> {
|
||||
getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, threadMessageId, searchingUserMessages, searchingChatMessages);
|
||||
showMessagesSearchListView(false);
|
||||
//if (!SharedConfig.searchMessagesAsListUsed && SharedConfig.searchMessagesAsListHintShows < 3 && !searchAsListHintShown && Math.random() <= 0.25) {
|
||||
if (!searchAsListHintShown) {
|
||||
if (!SharedConfig.searchMessagesAsListUsed && SharedConfig.searchMessagesAsListHintShows < 3 && !searchAsListHintShown && Math.random() <= 0.25) {
|
||||
showSearchAsListHint();
|
||||
// searchAsListHintShown = true;
|
||||
searchAsListHintShown = true;
|
||||
SharedConfig.increaseSearchAsListHintShows();
|
||||
}
|
||||
// SharedConfig.increaseSearchAsListHintShows();
|
||||
// }
|
||||
});
|
||||
searchUpButton.setContentDescription(LocaleController.getString("AccDescrSearchNext", R.string.AccDescrSearchNext));
|
||||
|
||||
|
@ -6997,9 +6997,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
searchCalendarButton.setContentDescription(LocaleController.getString("JumpToDate", R.string.JumpToDate));
|
||||
|
||||
searchCountText = new SearchCounterView(context);
|
||||
// searchCountText.setTextColor(Theme.getColor(Theme.key_chat_searchPanelText));
|
||||
// searchCountText.setTextSize(15);
|
||||
// searchCountText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
searchCountText.setGravity(Gravity.LEFT);
|
||||
searchContainer.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 0, 108, 0));
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public class ChatsWidgetConfigActivity extends ExternalActionActivity {
|
|||
args.putBoolean("onlySelect", true);
|
||||
args.putInt("dialogsType", 10);
|
||||
args.putBoolean("allowSwitchAccount", true);
|
||||
EditWidgetActivity fragment = new EditWidgetActivity(EditWidgetActivity.TYPE_CHATS, creatingAppWidgetId, false);
|
||||
EditWidgetActivity fragment = new EditWidgetActivity(EditWidgetActivity.TYPE_CHATS, creatingAppWidgetId);
|
||||
fragment.setDelegate(dialogs -> {
|
||||
Intent resultValue = new Intent();
|
||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, creatingAppWidgetId);
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
|
@ -31,6 +32,7 @@ import java.util.ArrayList;
|
|||
|
||||
public class BotCommandsMenuView extends View {
|
||||
|
||||
final RectF rectTmp = new RectF();
|
||||
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
final TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
final MenuDrawable backDrawable = new MenuDrawable() {
|
||||
|
@ -74,7 +76,7 @@ public class BotCommandsMenuView extends View {
|
|||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int size = MeasureSpec.getSize(widthMeasureSpec) + MeasureSpec.getSize(heightMeasureSpec) << 16;
|
||||
if (lastSize != size) {
|
||||
if (lastSize != size || menuText == null) {
|
||||
backDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
|
||||
textPaint.setTextSize(AndroidUtilities.dp(15));
|
||||
lastSize = size;
|
||||
|
@ -93,49 +95,49 @@ public class BotCommandsMenuView extends View {
|
|||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
boolean update = false;
|
||||
if (expanded && expandProgress != 1f) {
|
||||
expandProgress += 16f / 150f;
|
||||
if (expandProgress > 1) {
|
||||
expandProgress = 1f;
|
||||
} else {
|
||||
invalidate();
|
||||
if (menuText != null) {
|
||||
boolean update = false;
|
||||
if (expanded && expandProgress != 1f) {
|
||||
expandProgress += 16f / 150f;
|
||||
if (expandProgress > 1) {
|
||||
expandProgress = 1f;
|
||||
} else {
|
||||
invalidate();
|
||||
}
|
||||
update = true;
|
||||
} else if (!expanded && expandProgress != 0) {
|
||||
expandProgress -= 16f / 150f;
|
||||
if (expandProgress < 0) {
|
||||
expandProgress = 0;
|
||||
} else {
|
||||
invalidate();
|
||||
}
|
||||
update = true;
|
||||
}
|
||||
update = true;
|
||||
} else if (!expanded && expandProgress != 0) {
|
||||
expandProgress -= 16f / 150f;
|
||||
if (expandProgress < 0) {
|
||||
expandProgress = 0;
|
||||
} else {
|
||||
invalidate();
|
||||
|
||||
float expandProgress = CubicBezierInterpolator.DEFAULT.getInterpolation(this.expandProgress);
|
||||
if (update && expandProgress > 0) {
|
||||
textPaint.setAlpha((int) (255 * expandProgress));
|
||||
}
|
||||
update = true;
|
||||
}
|
||||
|
||||
float expandProgress = CubicBezierInterpolator.DEFAULT.getInterpolation(this.expandProgress);
|
||||
if (update && expandProgress > 0) {
|
||||
textPaint.setAlpha((int) (255 * expandProgress));
|
||||
}
|
||||
AndroidUtilities.rectTmp.set(0, 0, AndroidUtilities.dp(40) + (menuText.getWidth() + AndroidUtilities.dp(4)) * expandProgress, getMeasuredHeight());
|
||||
canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16), AndroidUtilities.dp(16), paint);
|
||||
backgroundDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom);
|
||||
backgroundDrawable.draw(canvas);
|
||||
canvas.save();
|
||||
canvas.translate(AndroidUtilities.dp(8), AndroidUtilities.dp(4));
|
||||
backDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
|
||||
|
||||
|
||||
if (expandProgress > 0) {
|
||||
rectTmp.set(0, 0, AndroidUtilities.dp(40) + (menuText.getWidth() + AndroidUtilities.dp(4)) * expandProgress, getMeasuredHeight());
|
||||
canvas.drawRoundRect(rectTmp, AndroidUtilities.dp(16), AndroidUtilities.dp(16), paint);
|
||||
backgroundDrawable.setBounds((int) rectTmp.left, (int) rectTmp.top, (int) rectTmp.right, (int) rectTmp.bottom);
|
||||
backgroundDrawable.draw(canvas);
|
||||
canvas.save();
|
||||
canvas.translate(AndroidUtilities.dp(34), (getMeasuredHeight() - menuText.getHeight()) / 2f);
|
||||
menuText.draw(canvas);
|
||||
canvas.translate(AndroidUtilities.dp(8), AndroidUtilities.dp(4));
|
||||
backDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
if (update) {
|
||||
onTranslationChanged((menuText.getWidth() + AndroidUtilities.dp(4)) * expandProgress);
|
||||
if (expandProgress > 0) {
|
||||
canvas.save();
|
||||
canvas.translate(AndroidUtilities.dp(34), (getMeasuredHeight() - menuText.getHeight()) / 2f);
|
||||
menuText.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
if (update) {
|
||||
onTranslationChanged((menuText.getWidth() + AndroidUtilities.dp(4)) * expandProgress);
|
||||
}
|
||||
}
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
|
|
@ -144,8 +144,6 @@ import java.util.Locale;
|
|||
|
||||
public class ChatActivityEnterView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate {
|
||||
|
||||
boolean textTransitionIsRunning;
|
||||
|
||||
public interface ChatActivityEnterViewDelegate {
|
||||
void onMessageSend(CharSequence message, boolean notify, int scheduleDate);
|
||||
|
||||
|
@ -243,6 +241,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
|
|||
|
||||
private Runnable moveToSendStateRunnable;
|
||||
boolean messageTransitionIsRunning;
|
||||
boolean textTransitionIsRunning;
|
||||
|
||||
private BotCommandsMenuView botCommandsMenuButton;
|
||||
public BotCommandsMenuContainer botCommandsMenuContainer;
|
||||
|
@ -4121,7 +4120,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
|
|||
}
|
||||
}
|
||||
if (processSendingText(message, notify, scheduleDate)) {
|
||||
if (delegate.hasForwardingMessages()) {
|
||||
if (delegate.hasForwardingMessages() || (scheduleDate != 0 && !isInScheduleMode()) || isInScheduleMode()) {
|
||||
messageEditText.setText("");
|
||||
if (delegate != null) {
|
||||
delegate.onMessageSend(message, notify, scheduleDate);
|
||||
|
|
|
@ -2874,7 +2874,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
|
|||
|
||||
@Override
|
||||
public boolean onSheetKeyDown(int keyCode, KeyEvent event) {
|
||||
if (cameraOpened && (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
|
||||
if (cameraOpened && (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)) {
|
||||
shutterButton.getDelegate().shutterReleased();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -209,6 +209,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
|
|||
float pinchScale;
|
||||
|
||||
boolean isInPinchToZoomTouchMode;
|
||||
boolean maybePinchToZoomTouchMode;
|
||||
|
||||
private int pointerId1, pointerId2;
|
||||
|
||||
|
@ -2497,7 +2498,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
|
|||
}
|
||||
|
||||
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN || ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
|
||||
if (!isInPinchToZoomTouchMode && ev.getPointerCount() == 2 && finishZoomTransition == null && recording) {
|
||||
if (maybePinchToZoomTouchMode && !isInPinchToZoomTouchMode && ev.getPointerCount() == 2 && finishZoomTransition == null && recording) {
|
||||
pinchStartDistance = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0));
|
||||
|
||||
pinchScale = 1f;
|
||||
|
@ -2508,7 +2509,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
|
|||
}
|
||||
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
AndroidUtilities.rectTmp.set(cameraContainer.getX(), cameraContainer.getY(), cameraContainer.getX() + cameraContainer.getMeasuredWidth(), cameraContainer.getY() + cameraContainer.getMeasuredHeight());
|
||||
return AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY());
|
||||
maybePinchToZoomTouchMode = AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY());
|
||||
}
|
||||
return true;
|
||||
} else if (ev.getActionMasked() == MotionEvent.ACTION_MOVE && isInPinchToZoomTouchMode) {
|
||||
|
@ -2536,7 +2537,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
|
|||
isInPinchToZoomTouchMode = false;
|
||||
finishZoom();
|
||||
}
|
||||
return isInPinchToZoomTouchMode;
|
||||
return true;
|
||||
}
|
||||
|
||||
ValueAnimator finishZoomTransition;
|
||||
|
|
|
@ -314,7 +314,7 @@ public class MotionBackgroundDrawable extends Drawable {
|
|||
if (Build.VERSION.SDK_INT < 28 && intensity < 0) {
|
||||
int w = right - left;
|
||||
int h = bottom - top;
|
||||
if (legacyBitmap == null || legacyBitmap.getWidth() != w || legacyBitmap.getHeight() != h) {
|
||||
if (w > 0 && h > 0 && (legacyBitmap == null || legacyBitmap.getWidth() != w || legacyBitmap.getHeight() != h)) {
|
||||
if (legacyBitmap != null) {
|
||||
legacyBitmap.recycle();
|
||||
}
|
||||
|
|
|
@ -1090,14 +1090,22 @@ public class PasscodeView extends FrameLayout {
|
|||
FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(ApplicationLoader.applicationContext);
|
||||
if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) {
|
||||
fingerprintView.setVisibility(VISIBLE);
|
||||
} else {
|
||||
fingerprintView.setVisibility(GONE);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
fingerprintView.setVisibility(GONE);
|
||||
}
|
||||
} else {
|
||||
fingerprintView.setVisibility(GONE);
|
||||
}
|
||||
if (SharedConfig.passcodeType == 1) {
|
||||
fingerprintImage.setVisibility(fingerprintView.getVisibility());
|
||||
}
|
||||
if (numberFrameLayouts.size() >= 11) {
|
||||
numberFrameLayouts.get(11).setVisibility(fingerprintView.getVisibility());
|
||||
}
|
||||
}
|
||||
|
||||
public void onShow(boolean fingerprint, boolean animated, int x, int y, Runnable onShow, Runnable onStart) {
|
||||
|
@ -1363,7 +1371,7 @@ public class PasscodeView extends FrameLayout {
|
|||
layoutParams = (LayoutParams) numbersFrameLayout.getLayoutParams();
|
||||
layoutParams.height = height;
|
||||
layoutParams.leftMargin = width / 2;
|
||||
layoutParams.topMargin = height - layoutParams.height;
|
||||
layoutParams.topMargin = height - layoutParams.height + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
|
||||
layoutParams.width = width / 2;
|
||||
numbersFrameLayout.setLayoutParams(layoutParams);
|
||||
} else {
|
||||
|
@ -1390,10 +1398,10 @@ public class PasscodeView extends FrameLayout {
|
|||
passwordFrameLayout.setLayoutParams(layoutParams);
|
||||
|
||||
layoutParams = (LayoutParams) numbersFrameLayout.getLayoutParams();
|
||||
layoutParams.height = height / 3 * 2 + AndroidUtilities.dp(20);
|
||||
layoutParams.height = height / 3 * 2;
|
||||
layoutParams.leftMargin = left;
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
layoutParams.topMargin = height - layoutParams.height + top;
|
||||
layoutParams.topMargin = height - layoutParams.height + top + AndroidUtilities.dp(20);
|
||||
} else {
|
||||
layoutParams.topMargin = height - layoutParams.height + top + (SharedConfig.passcodeType == 0 ? AndroidUtilities.dp(40) : 0);
|
||||
}
|
||||
|
|
|
@ -237,13 +237,13 @@ public class SearchCounterView extends View {
|
|||
boolean increment = countAnimationIncrement;
|
||||
if (countAnimationInLayout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4) + (increment ? AndroidUtilities.dp(13) : -AndroidUtilities.dp(13)) * (1f - countChangeProgress));
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(2) + (increment ? AndroidUtilities.dp(13) : -AndroidUtilities.dp(13)) * (1f - countChangeProgress));
|
||||
textPaint.setAlpha((int) (255 * countChangeProgress));
|
||||
countAnimationInLayout.draw(canvas);
|
||||
canvas.restore();
|
||||
} else if (countLayout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4) + (increment ? AndroidUtilities.dp(13) : -AndroidUtilities.dp(13)) * (1f - countChangeProgress));
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(2) + (increment ? AndroidUtilities.dp(13) : -AndroidUtilities.dp(13)) * (1f - countChangeProgress));
|
||||
textPaint.setAlpha((int) (255 * countChangeProgress));
|
||||
countLayout.draw(canvas);
|
||||
canvas.restore();
|
||||
|
@ -251,7 +251,7 @@ public class SearchCounterView extends View {
|
|||
|
||||
if (countOldLayout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4) + (increment ? -AndroidUtilities.dp(13) : AndroidUtilities.dp(13)) * (countChangeProgress));
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(2) + (increment ? -AndroidUtilities.dp(13) : AndroidUtilities.dp(13)) * (countChangeProgress));
|
||||
textPaint.setAlpha((int) (255 * (1f - countChangeProgress)));
|
||||
countOldLayout.draw(canvas);
|
||||
canvas.restore();
|
||||
|
@ -259,7 +259,7 @@ public class SearchCounterView extends View {
|
|||
|
||||
if (countAnimationStableLayout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(countLeft + dx * (1f - countChangeProgress), countTop + AndroidUtilities.dp(4));
|
||||
canvas.translate(countLeft + dx * (1f - countChangeProgress), countTop + AndroidUtilities.dp(2));
|
||||
textPaint.setAlpha(255);
|
||||
countAnimationStableLayout.draw(canvas);
|
||||
canvas.restore();
|
||||
|
@ -267,7 +267,7 @@ public class SearchCounterView extends View {
|
|||
|
||||
if (countAnimationStableLayout2 != null) {
|
||||
canvas.save();
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4));
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(2));
|
||||
textPaint.setAlpha(255);
|
||||
countAnimationStableLayout2.draw(canvas);
|
||||
canvas.restore();
|
||||
|
@ -299,7 +299,7 @@ public class SearchCounterView extends View {
|
|||
updateX(countWidth);
|
||||
if (countLayout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4));
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(2));
|
||||
countLayout.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
|
|
@ -254,18 +254,20 @@ public class GroupCallMiniTextureView extends FrameLayout implements GroupCallSt
|
|||
if (animateToFullscreen || showingInFullscreen) {
|
||||
size += (AndroidUtilities.dp(10) + AndroidUtilities.dp(39) * parentContainer.progressToFullscreenMode);
|
||||
} else {
|
||||
size += AndroidUtilities.dp(10) * (1.0f - parentContainer.progressToFullscreenMode);
|
||||
size += AndroidUtilities.dp(10) * Math.max(1.0f - parentContainer.progressToFullscreenMode, showingAsScrimView || animateToScrimView ? parentContainer.progressToScrimView : 0.0f);
|
||||
}
|
||||
|
||||
int x = (getMeasuredWidth() - size) / 2;
|
||||
float smallProgress;
|
||||
float smallProgress2;
|
||||
float scrimProgress = (showingAsScrimView || animateToScrimView ? parentContainer.progressToScrimView : 0);
|
||||
if (showingInFullscreen) {
|
||||
smallProgress = progressToFullscreen;
|
||||
smallProgress = smallProgress2 = progressToFullscreen;
|
||||
} else {
|
||||
smallProgress = animateToFullscreen ? parentContainer.progressToFullscreenMode : scrimProgress;
|
||||
smallProgress2 = showingAsScrimView || animateToScrimView ? parentContainer.progressToScrimView : parentContainer.progressToFullscreenMode;
|
||||
}
|
||||
int y = (int) ((getMeasuredHeight() - size) / 2 - AndroidUtilities.dp(11) - (AndroidUtilities.dp(17) + AndroidUtilities.dp(74) * parentContainer.progressToFullscreenMode) * smallProgress);
|
||||
int y = (int) ((getMeasuredHeight() - size) / 2 - AndroidUtilities.dp(28) - (AndroidUtilities.dp(17) + AndroidUtilities.dp(74) * (showingInFullscreen || animateToFullscreen ? parentContainer.progressToFullscreenMode : 0.0f)) * smallProgress + AndroidUtilities.dp(17) * smallProgress2);
|
||||
castingScreenDrawable.setBounds(x, y, x + size, y + size);
|
||||
castingScreenDrawable.draw(canvas);
|
||||
|
||||
|
@ -1102,8 +1104,14 @@ public class GroupCallMiniTextureView extends FrameLayout implements GroupCallSt
|
|||
}
|
||||
|
||||
boolean pausedInternal = false;
|
||||
if (participant.participant.video != null && participant.participant.video.paused) {
|
||||
pausedInternal = true;
|
||||
if (participant.presentation) {
|
||||
if (participant.participant.presentation != null && participant.participant.presentation.paused) {
|
||||
pausedInternal = true;
|
||||
}
|
||||
} else {
|
||||
if (participant.participant.video != null && participant.participant.video.paused) {
|
||||
pausedInternal = true;
|
||||
}
|
||||
}
|
||||
if (videoIsPaused != pausedInternal) {
|
||||
videoIsPaused = pausedInternal;
|
||||
|
|
|
@ -25,7 +25,7 @@ public class ContactsWidgetConfigActivity extends ExternalActionActivity {
|
|||
args.putBoolean("onlySelect", true);
|
||||
args.putInt("dialogsType", 10);
|
||||
args.putBoolean("allowSwitchAccount", true);
|
||||
EditWidgetActivity fragment = new EditWidgetActivity(EditWidgetActivity.TYPE_CONTACTS, creatingAppWidgetId, false);
|
||||
EditWidgetActivity fragment = new EditWidgetActivity(EditWidgetActivity.TYPE_CONTACTS, creatingAppWidgetId);
|
||||
fragment.setDelegate(dialogs -> {
|
||||
Intent resultValue = new Intent();
|
||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, creatingAppWidgetId);
|
||||
|
|
|
@ -104,7 +104,6 @@ public class EditWidgetActivity extends BaseFragment {
|
|||
|
||||
private int widgetType;
|
||||
private int currentWidgetId;
|
||||
private boolean isEdit;
|
||||
|
||||
private EditWidgetActivityDelegate delegate;
|
||||
|
||||
|
@ -733,18 +732,15 @@ public class EditWidgetActivity extends BaseFragment {
|
|||
}
|
||||
}
|
||||
|
||||
public EditWidgetActivity(int type, int widgetId, boolean edit) {
|
||||
public EditWidgetActivity(int type, int widgetId) {
|
||||
super();
|
||||
widgetType = type;
|
||||
currentWidgetId = widgetId;
|
||||
isEdit = edit;
|
||||
if (edit) {
|
||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
|
||||
getMessagesStorage().getWidgetDialogIds(currentWidgetId, widgetType, selectedDialogs, users, chats, true);
|
||||
getMessagesController().putUsers(users, true);
|
||||
getMessagesController().putChats(chats, true);
|
||||
}
|
||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
|
||||
getMessagesStorage().getWidgetDialogIds(currentWidgetId, widgetType, selectedDialogs, users, chats, true);
|
||||
getMessagesController().putUsers(users, true);
|
||||
getMessagesController().putChats(chats, true);
|
||||
updateRows();
|
||||
}
|
||||
|
||||
|
@ -810,14 +806,16 @@ public class EditWidgetActivity extends BaseFragment {
|
|||
getMessagesStorage().putWidgetDialogs(currentWidgetId, selectedDialogs);
|
||||
|
||||
SharedPreferences preferences = getParentActivity().getSharedPreferences("shortcut_widget", Activity.MODE_PRIVATE);
|
||||
preferences.edit().putInt("account" + currentWidgetId, currentAccount).commit();
|
||||
preferences.edit().putInt("type" + currentWidgetId, widgetType).commit();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("account" + currentWidgetId, currentAccount);
|
||||
editor.putInt("type" + currentWidgetId, widgetType);
|
||||
editor.commit();
|
||||
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getParentActivity());
|
||||
if (widgetType == TYPE_CHATS) {
|
||||
ChatsWidgetProvider.updateWidget(getParentActivity(), appWidgetManager, currentWidgetId, isEdit);
|
||||
ChatsWidgetProvider.updateWidget(getParentActivity(), appWidgetManager, currentWidgetId);
|
||||
} else {
|
||||
ContactsWidgetProvider.updateWidget(getParentActivity(), appWidgetManager, currentWidgetId, isEdit);
|
||||
ContactsWidgetProvider.updateWidget(getParentActivity(), appWidgetManager, currentWidgetId);
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.didSelectDialogs(selectedDialogs);
|
||||
|
|
|
@ -35,8 +35,10 @@ public class FeedWidgetConfigActivity extends ExternalActionActivity {
|
|||
AccountInstance.getInstance(fragment1.getCurrentAccount()).getMessagesStorage().putWidgetDialogs(creatingAppWidgetId, dids);
|
||||
|
||||
SharedPreferences preferences = FeedWidgetConfigActivity.this.getSharedPreferences("shortcut_widget", Activity.MODE_PRIVATE);
|
||||
preferences.edit().putInt("account" + creatingAppWidgetId, fragment1.getCurrentAccount()).commit();
|
||||
preferences.edit().putLong("dialogId" + creatingAppWidgetId, dids.get(0)).commit();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("account" + creatingAppWidgetId, fragment1.getCurrentAccount());
|
||||
editor.putLong("dialogId" + creatingAppWidgetId, dids.get(0));
|
||||
editor.commit();
|
||||
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(FeedWidgetConfigActivity.this);
|
||||
FeedWidgetProvider.updateWidget(FeedWidgetConfigActivity.this, appWidgetManager, creatingAppWidgetId);
|
||||
|
|
|
@ -308,7 +308,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
AndroidUtilities.isInMultiwindow = isInMultiWindowMode();
|
||||
}
|
||||
Theme.createCommonChatResources(this);
|
||||
Theme.createCommonChatResources();
|
||||
Theme.createDialogsResources(this);
|
||||
if (SharedConfig.passcodeHash.length() != 0 && SharedConfig.appLocked) {
|
||||
SharedConfig.lastPauseTime = (int) (SystemClock.elapsedRealtime() / 1000);
|
||||
|
@ -2273,7 +2273,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
fragment = new ActionIntroActivity(ActionIntroActivity.ACTION_TYPE_CHANGE_PHONE_NUMBER);
|
||||
closePrevious = true;
|
||||
} else if (open_settings == 6) {
|
||||
fragment = new EditWidgetActivity(open_widget_edit_type, open_widget_edit, true);
|
||||
fragment = new EditWidgetActivity(open_widget_edit_type, open_widget_edit);
|
||||
} else {
|
||||
fragment = null;
|
||||
}
|
||||
|
@ -3657,18 +3657,19 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
if (SharedConfig.pendingAppUpdate != null && SharedConfig.pendingAppUpdate.version.equals(res.version)) {
|
||||
return;
|
||||
}
|
||||
SharedConfig.setNewAppVersionAvailable(res);
|
||||
if (res.can_not_skip) {
|
||||
showUpdateActivity(accountNum, res, false);
|
||||
} else {
|
||||
drawerLayoutAdapter.notifyDataSetChanged();
|
||||
try {
|
||||
(new UpdateAppAlertDialog(LaunchActivity.this, res, accountNum)).show();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
if (SharedConfig.setNewAppVersionAvailable(res)) {
|
||||
if (res.can_not_skip) {
|
||||
showUpdateActivity(accountNum, res, false);
|
||||
} else {
|
||||
drawerLayoutAdapter.notifyDataSetChanged();
|
||||
try {
|
||||
(new UpdateAppAlertDialog(LaunchActivity.this, res, accountNum)).show();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.appUpdateAvailable);
|
||||
}
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.appUpdateAvailable);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -676,7 +676,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
|||
BulletinFactory.of(containerView).createSimpleBulletin(R.raw.voip_invite, bulletinMessage).show();
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
BottomSheet bottomSheet = builder.create();
|
||||
bottomSheet.show();
|
||||
bottomSheet.setItemColor(0,0xffffffff, 0xffffffff);
|
||||
bottomSheet.setItemColor(1,0xffffffff, 0xffffffff);
|
||||
bottomSheet.setBackgroundColor(0xff1C2229);
|
||||
bottomSheet.setTitleColor(0xff8A8A8A);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1480,6 +1480,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
@Override
|
||||
public View createView(Context context) {
|
||||
Theme.createProfileResources(context);
|
||||
Theme.createChatResources(context, false);
|
||||
|
||||
searchTransitionOffset = 0;
|
||||
searchTransitionProgress = 1f;
|
||||
|
|
|
@ -16,6 +16,7 @@ import android.graphics.Shader;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
|
@ -114,6 +115,9 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain
|
|||
enterView = chatActivity.getChatActivityEnterView();
|
||||
|
||||
ChatActivityEnterView chatActivityEnterView = chatActivity.getChatActivityEnterView();
|
||||
if (chatActivityEnterView == null || chatActivityEnterView.getEditField() == null || chatActivityEnterView.getEditField().getLayout() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
fromRadius = chatActivityEnterView.getRecordCicle().drawingCircleRadius;
|
||||
bitmapPaint.setFilterBitmap(true);
|
||||
|
@ -145,7 +149,18 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain
|
|||
emojiSize = AndroidUtilities.dp(24);
|
||||
}
|
||||
}
|
||||
if (editText.length() != text.length()) {
|
||||
boolean containsSpans = false;
|
||||
if (text instanceof Spannable) {
|
||||
Spannable spannable = (Spannable) text;
|
||||
Object[] objects = spannable.getSpans(0, text.length(), Object.class);
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
if (!(objects[i] instanceof Emoji.EmojiSpan)) {
|
||||
containsSpans = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (editText.length() != text.length() || containsSpans) {
|
||||
crossfade = true;
|
||||
String str = editText.toString();
|
||||
String trimmedStr = str.trim();
|
||||
|
@ -543,78 +558,78 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain
|
|||
}
|
||||
|
||||
canvas.save();
|
||||
{
|
||||
canvas.clipRect(drawableX + AndroidUtilities.dp(4), drawableTop + AndroidUtilities.dp(4), drawableRight - AndroidUtilities.dp(4), drawableBottom - AndroidUtilities.dp(4));
|
||||
|
||||
float scale = progressX + scaleFrom * (1f - progressX);
|
||||
float scale2;
|
||||
if (drawBitmaps) {
|
||||
scale2 = progressX + scaleY * (1f - progressX);
|
||||
canvas.clipRect(drawableX + AndroidUtilities.dp(4), drawableTop + AndroidUtilities.dp(4), drawableRight - AndroidUtilities.dp(4), drawableBottom - AndroidUtilities.dp(4));
|
||||
|
||||
float scale = progressX + scaleFrom * (1f - progressX);
|
||||
float scale2;
|
||||
if (drawBitmaps) {
|
||||
scale2 = progressX + scaleY * (1f - progressX);
|
||||
} else {
|
||||
scale2 = 1f;
|
||||
}
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(fromX * (1f - progressX) + (toX - toXOffset) * progressX, fromY * (1f - progress) + (toY + textLayoutBlock.textYOffset) * progress);
|
||||
canvas.scale(scale, scale * scale2, 0, 0);
|
||||
// canvas.translate(0, textLayoutBlock.textYOffset / 2);
|
||||
if (drawBitmaps) {
|
||||
if (crossfade) {
|
||||
bitmapPaint.setAlpha((int) (255 * (1f - alphaProgress)));
|
||||
}
|
||||
canvas.drawBitmap(textLayoutBitmap, 0, 0, bitmapPaint);
|
||||
} else {
|
||||
if (crossfade) {
|
||||
int oldAlpha = Theme.chat_msgTextPaint.getAlpha();
|
||||
Theme.chat_msgTextPaint.setAlpha((int) (oldAlpha * (1f - alphaProgress)));
|
||||
layout.draw(canvas);
|
||||
Theme.chat_msgTextPaint.setAlpha(oldAlpha);
|
||||
} else {
|
||||
scale2 = 1f;
|
||||
layout.draw(canvas);
|
||||
}
|
||||
|
||||
}
|
||||
canvas.restore();
|
||||
|
||||
if (rtlLayout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(fromX * (1f - progressX) + (toX - toXOffset) * progressX, fromY * (1f - progress) + (toY + textLayoutBlock.textYOffset) * progress);
|
||||
canvas.translate(fromX * (1f - progressX) + (toX - toXOffsetRtl) * progressX, fromY * (1f - progress) + (toY + textLayoutBlock.textYOffset) * progress);
|
||||
canvas.scale(scale, scale * scale2, 0, 0);
|
||||
// canvas.translate(0, textLayoutBlock.textYOffset / 2);
|
||||
if (drawBitmaps) {
|
||||
if (crossfade) {
|
||||
bitmapPaint.setAlpha((int) (255 * (1f - alphaProgress)));
|
||||
}
|
||||
canvas.drawBitmap(textLayoutBitmap, 0, 0, bitmapPaint);
|
||||
canvas.drawBitmap(textLayoutBitmapRtl, 0, 0, bitmapPaint);
|
||||
} else {
|
||||
if (crossfade) {
|
||||
int oldAlpha = Theme.chat_msgTextPaint.getAlpha();
|
||||
Theme.chat_msgTextPaint.setAlpha((int) (oldAlpha * (1f - alphaProgress)));
|
||||
layout.draw(canvas);
|
||||
rtlLayout.draw(canvas);
|
||||
Theme.chat_msgTextPaint.setAlpha(oldAlpha);
|
||||
} else {
|
||||
layout.draw(canvas);
|
||||
rtlLayout.draw(canvas);
|
||||
}
|
||||
|
||||
}
|
||||
canvas.restore();
|
||||
|
||||
if (rtlLayout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(fromX * (1f - progressX) + (toX - toXOffsetRtl) * progressX, fromY * (1f - progress) + (toY + textLayoutBlock.textYOffset) * progress);
|
||||
canvas.scale(scale, scale * scale2, 0, 0);
|
||||
if (drawBitmaps) {
|
||||
if (crossfade) {
|
||||
bitmapPaint.setAlpha((int) (255 * (1f - alphaProgress)));
|
||||
}
|
||||
canvas.drawBitmap(textLayoutBitmapRtl, 0, 0, bitmapPaint);
|
||||
} else {
|
||||
if (crossfade) {
|
||||
int oldAlpha = Theme.chat_msgTextPaint.getAlpha();
|
||||
Theme.chat_msgTextPaint.setAlpha((int) (oldAlpha * (1f - alphaProgress)));
|
||||
rtlLayout.draw(canvas);
|
||||
Theme.chat_msgTextPaint.setAlpha(oldAlpha);
|
||||
} else {
|
||||
rtlLayout.draw(canvas);
|
||||
}
|
||||
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
if (crossfade) {
|
||||
canvas.save();
|
||||
canvas.translate(messageView.getLeft() + listView.getX() - container.getX() + (fromX - toX) * (1f - progressX), messageViewY + (fromY - toY) * (1f - progress));
|
||||
canvas.scale(scale, scale * scale2, messageView.getTextX(), messageView.getTextY());
|
||||
canvas.translate(0, -crossfadeTextOffset);
|
||||
|
||||
if (drawBitmaps) {
|
||||
bitmapPaint.setAlpha((int) (255 * alphaProgress));
|
||||
canvas.drawBitmap(crossfadeTextBitmap, 0, 0, bitmapPaint);
|
||||
} else {
|
||||
messageView.drawMessageText(canvas, messageView.getMessageObject().textLayoutBlocks, true, alphaProgress, true);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (crossfade) {
|
||||
canvas.save();
|
||||
canvas.translate(messageView.getLeft() + listView.getX() - container.getX() + (fromX - toX) * (1f - progressX), messageViewY + (fromY - toY) * (1f - progress));
|
||||
canvas.scale(scale, scale * scale2, messageView.getTextX(), messageView.getTextY());
|
||||
canvas.translate(0, -crossfadeTextOffset);
|
||||
|
||||
if (crossfadeTextBitmap != null) {
|
||||
bitmapPaint.setAlpha((int) (255 * alphaProgress));
|
||||
canvas.drawBitmap(crossfadeTextBitmap, 0, 0, bitmapPaint);
|
||||
} else {
|
||||
messageView.drawMessageText(canvas, messageView.getMessageObject().textLayoutBlocks, true, alphaProgress, true);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
|
||||
canvas.restore();
|
||||
|
||||
if (clipBottomWithAlpha) {
|
||||
|
@ -631,8 +646,8 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain
|
|||
}
|
||||
if (enterView.getSendButton().getVisibility() == View.VISIBLE && sendProgress < 1f) {
|
||||
canvas.save();
|
||||
canvas.translate(enterView.getX() + enterView.getSendButton().getX() + ((View) enterView.getSendButton().getParent()).getX() + ((View) enterView.getSendButton().getParent().getParent()).getX() - container.getX() + AndroidUtilities.dp(52) * sendProgress, enterView.getY() + enterView.getSendButton().getY() + ((View) enterView.getSendButton().getParent()).getY() + ((View) enterView.getSendButton().getParent().getParent()).getY()- container.getY());
|
||||
// canvas.saveLayerAlpha(0, 0, enterView.getSendButton().getWidth(), enterView.getSendButton().getHeight(), (int) (enterView.getSendButton().getAlpha() * 255), Canvas.ALL_SAVE_FLAG);
|
||||
canvas.translate(enterView.getX() + enterView.getSendButton().getX() + ((View) enterView.getSendButton().getParent()).getX() + ((View) enterView.getSendButton().getParent().getParent()).getX() - container.getX() + AndroidUtilities.dp(52) * sendProgress, enterView.getY() + enterView.getSendButton().getY() + ((View) enterView.getSendButton().getParent()).getY() + ((View) enterView.getSendButton().getParent().getParent()).getY() - container.getY());
|
||||
// canvas.saveLayerAlpha(0, 0, enterView.getSendButton().getWidth(), enterView.getSendButton().getHeight(), (int) (enterView.getSendButton().getAlpha() * 255), Canvas.ALL_SAVE_FLAG);
|
||||
//canvas.scale(enterView.getSendButton().getScaleX(), enterView.getSendButton().getScaleY(), enterView.getSendButton().getWidth() / 2f, enterView.getSendButton().getHeight() / 2f);
|
||||
enterView.getSendButton().draw(canvas);
|
||||
canvas.restore();
|
||||
|
|
|
@ -29,7 +29,7 @@ public class VoIPPermissionActivity extends Activity {
|
|||
if (isVideoCall && checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(Manifest.permission.CAMERA);
|
||||
}
|
||||
if (permissions.isEmpty()) {
|
||||
if (!permissions.isEmpty()) {
|
||||
try {
|
||||
requestPermissions(permissions.toArray(new String[0]), isVideoCall ? 102 : 101);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="?attr/widgetBackgroundCornerRadius" />
|
||||
<solid android:color="?android:attr/colorBackground" />
|
||||
</shape>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?android:attr/colorAccent" />
|
||||
<corners
|
||||
android:topLeftRadius="12dp"
|
||||
android:topRightRadius="12dp"
|
||||
android:bottomLeftRadius="12dp"
|
||||
android:bottomRightRadius="12dp"/>
|
||||
</shape>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?android:attr/colorButtonNormal" />
|
||||
<corners
|
||||
android:topLeftRadius="12dp"
|
||||
android:topRightRadius="12dp"
|
||||
android:bottomLeftRadius="12dp"
|
||||
android:bottomRightRadius="12dp"/>
|
||||
</shape>
|
BIN
TMessagesProj/src/main/res/drawable/widget_avatar_1.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
TMessagesProj/src/main/res/drawable/widget_avatar_2.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
TMessagesProj/src/main/res/drawable/widget_avatar_3.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
TMessagesProj/src/main/res/drawable/widget_avatar_4.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
TMessagesProj/src/main/res/drawable/widget_avatar_5.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
TMessagesProj/src/main/res/drawable/widget_avatar_6.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
TMessagesProj/src/main/res/drawable/widget_avatar_7.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/widget_counter" />
|
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/widget_counter_muted" />
|
|
@ -1,121 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:minHeight="72dp"
|
||||
android:id="@+id/contacts_widget_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="86dp"
|
||||
android:weightSum="1"
|
||||
android:baselineAligned="false">
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="72dp"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="1">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:id="@+id/contacts_widget_item1"
|
||||
android:layout_height="86dp"
|
||||
android:background="@drawable/list_selector_ex"
|
||||
android:layout_weight="0.5">
|
||||
<include layout="@layout/contacts_widget_item_1" />
|
||||
|
||||
<ImageView android:id="@+id/contacts_widget_item_avatar1"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:gravity="start" />
|
||||
<include layout="@layout/contacts_widget_item_2" />
|
||||
|
||||
<TextView android:id="@+id/contacts_widget_item_text1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="12dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:textColor="@color/widget_name"/>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="1dp"
|
||||
android:background="@drawable/widgets_light_badgebg"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="27dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:id="@+id/contacts_widget_item_badge_bg1">
|
||||
|
||||
<TextView android:id="@+id/contacts_widget_item_badge1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="23dp"
|
||||
android:paddingLeft="7dp"
|
||||
android:paddingRight="7dp"
|
||||
android:paddingBottom="1dp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:minWidth="23dp"
|
||||
android:textSize="13dp"
|
||||
android:background="@drawable/widget_counter"
|
||||
android:textColor="@color/widget_badge" />
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:minHeight="72dp"
|
||||
android:id="@+id/contacts_widget_item2"
|
||||
android:background="@drawable/list_selector_ex"
|
||||
android:layout_height="86dp"
|
||||
android:layout_weight="0.5">
|
||||
|
||||
<ImageView android:id="@+id/contacts_widget_item_avatar2"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:gravity="start" />
|
||||
|
||||
<TextView android:id="@+id/contacts_widget_item_text2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="12dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:textColor="@color/widget_name"/>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="1dp"
|
||||
android:background="@drawable/widgets_light_badgebg"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="27dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:id="@+id/contacts_widget_item_badge_bg2">
|
||||
|
||||
<TextView android:id="@+id/contacts_widget_item_badge2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="23dp"
|
||||
android:paddingLeft="7dp"
|
||||
android:paddingRight="7dp"
|
||||
android:paddingBottom="1dp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:minWidth="23dp"
|
||||
android:textSize="13dp"
|
||||
android:background="@drawable/widget_counter"
|
||||
android:textColor="@color/widget_badge" />
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
55
TMessagesProj/src/main/res/layout/contacts_widget_item_1.xml
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="0dp"
|
||||
android:id="@+id/contacts_widget_item1"
|
||||
android:layout_height="86dp"
|
||||
android:background="@drawable/list_selector_ex"
|
||||
android:layout_weight="0.5"
|
||||
android:theme="@style/Theme.TMessages.AppWidget"
|
||||
tools:showIn="@layout/contacts_widget_item">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/contacts_widget_item_avatar1"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:src="?attr/widgetPreviewImage"
|
||||
android:gravity="start" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contacts_widget_item_text1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="12dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:text="?attr/widgetPreviewTitle"
|
||||
android:textColor="@color/widget_name" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="1dp"
|
||||
android:background="@drawable/widgets_light_badgebg"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="27dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:visibility="?attr/widgetPreviewDot"
|
||||
android:id="@+id/contacts_widget_item_badge_bg1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contacts_widget_item_badge1"
|
||||
style="@style/TMessages.AppWidget.Badge"
|
||||
android:layout_gravity="center"
|
||||
android:text="2" />
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
56
TMessagesProj/src/main/res/layout/contacts_widget_item_2.xml
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="0dp"
|
||||
android:minHeight="72dp"
|
||||
android:id="@+id/contacts_widget_item2"
|
||||
android:background="@drawable/list_selector_ex"
|
||||
android:layout_height="86dp"
|
||||
android:layout_weight="0.5"
|
||||
android:theme="@style/Theme.TMessages.AppWidget"
|
||||
tools:showIn="@layout/contacts_widget_item">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/contacts_widget_item_avatar2"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:src="?attr/widgetPreviewImage"
|
||||
android:gravity="start" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contacts_widget_item_text2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="12dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:text="?attr/widgetPreviewTitle"
|
||||
android:textColor="@color/widget_name" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="1dp"
|
||||
android:background="@drawable/widgets_light_badgebg"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="27dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:visibility="?attr/widgetPreviewDot"
|
||||
android:id="@+id/contacts_widget_item_badge_bg2">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contacts_widget_item_badge2"
|
||||
style="@style/TMessages.AppWidget.Badge"
|
||||
android:layout_gravity="center"
|
||||
android:text="1" />
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="176dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="262dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="348dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="176dp"
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<include
|
||||
layout="@layout/contacts_widget_item_1"
|
||||
android:theme="@style/Theme.TMessages.AppWidget.Preview4" />
|
||||
|
||||
<include
|
||||
layout="@layout/contacts_widget_item_2"
|
||||
android:theme="@style/Theme.TMessages.AppWidget.Preview5" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="1">
|
||||
|
||||
<include
|
||||
layout="@layout/contacts_widget_item_2"
|
||||
android:theme="@style/Theme.TMessages.AppWidget.Preview6" />
|
||||
|
||||
<include
|
||||
layout="@layout/contacts_widget_item_2"
|
||||
android:theme="@style/Theme.TMessages.AppWidget.Preview7" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,9 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:minHeight="72dp"
|
||||
android:id="@+id/shortcut_widget_item"
|
||||
android:layout_height="72dp">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:minHeight="72dp"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ImageView android:id="@+id/shortcut_widget_item_avatar"
|
||||
android:layout_width="54dp"
|
||||
|
@ -12,6 +13,7 @@
|
|||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:src="?attr/widgetPreviewImage"
|
||||
android:gravity="start" />
|
||||
|
||||
<RelativeLayout
|
||||
|
@ -33,6 +35,7 @@
|
|||
android:textColor="@color/widget_name"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:text="?attr/widgetPreviewTitle"
|
||||
android:layout_toStartOf="@+id/shortcut_widget_item_time"/>
|
||||
|
||||
<TextView android:id="@+id/shortcut_widget_item_time"
|
||||
|
@ -41,6 +44,7 @@
|
|||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="3dp"
|
||||
android:textSize="13dp"
|
||||
android:text="?attr/widgetPreviewTime"
|
||||
android:textColor="@color/widget_time" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
@ -65,22 +69,16 @@
|
|||
android:autoLink="none"
|
||||
android:textColorLink="@color/widget_text"
|
||||
android:layout_alignParentStart="true"
|
||||
android:text="?attr/widgetPreviewContent"
|
||||
android:layout_toStartOf="@+id/shortcut_widget_item_badge"/>
|
||||
|
||||
<TextView android:id="@+id/shortcut_widget_item_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="23dp"
|
||||
android:paddingLeft="7dp"
|
||||
android:paddingRight="7dp"
|
||||
android:paddingBottom="1dp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:gravity="center"
|
||||
android:minWidth="23dp"
|
||||
android:textSize="13dp"
|
||||
android:layout_marginStart="4dp"
|
||||
<TextView
|
||||
android:id="@+id/shortcut_widget_item_badge"
|
||||
style="@style/TMessages.AppWidget.Badge"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:background="@drawable/widget_counter"
|
||||
android:textColor="@color/widget_badge" />
|
||||
android:layout_marginStart="4dp"
|
||||
android:text="2"
|
||||
android:visibility="?attr/widgetPreviewDot" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="76dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="148dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="220dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="292dp"
|
||||
android:background="@drawable/widget_bg"
|
||||
android:padding="2dp">
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget">
|
||||
|
||||
<ListView android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/TMessages.AppWidget.Background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/Theme.TMessages.AppWidget"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<include
|
||||
layout="@layout/shortcut_widget_item"
|
||||
android:theme="@style/Theme.TMessages.AppWidget.Preview" />
|
||||
|
||||
<include
|
||||
layout="@layout/shortcut_widget_item"
|
||||
android:theme="@style/Theme.TMessages.AppWidget.Preview2" />
|
||||
|
||||
</LinearLayout>
|
32
TMessagesProj/src/main/res/values-v31/styles.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2021 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- APP WIDGET -->
|
||||
|
||||
<style name="Base.Theme.TMessages.AppWidget" parent="android:Theme.DeviceDefault.DayNight" />
|
||||
|
||||
<style name="TMessages.AppWidget.Background" parent="Base.TMessages.AppWidget.Background">
|
||||
<item name="android:clipToOutline">true</item>
|
||||
<item name="android:background">@drawable/widget_background</item>
|
||||
</style>
|
||||
|
||||
<style name="TMessages.AppWidget.Badge" parent="Base.TMessages.AppWidget.Badge">
|
||||
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
4
TMessagesProj/src/main/res/values-v31/values.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="app_widget_background_corner_radius">@android:dimen/system_app_widget_background_radius</dimen>
|
||||
</resources>
|
10
TMessagesProj/src/main/res/values/attrs.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="widgetBackgroundCornerRadius" format="dimension" />
|
||||
|
||||
<attr name="widgetPreviewTitle" format="string" />
|
||||
<attr name="widgetPreviewContent" format="string" />
|
||||
<attr name="widgetPreviewTime" format="string" />
|
||||
<attr name="widgetPreviewImage" format="reference" />
|
||||
<attr name="widgetPreviewDot" format="integer" />
|
||||
</resources>
|
|
@ -130,4 +130,94 @@
|
|||
<item name="android:windowFullscreen">false</item>
|
||||
</style>
|
||||
|
||||
<!--APP WIDGET-->
|
||||
|
||||
<style name="Base.Theme.TMessages.AppWidget" parent="Theme.TMessages"/>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget" parent="Base.Theme.TMessages.AppWidget">
|
||||
<item name="widgetBackgroundCornerRadius">@dimen/app_widget_background_corner_radius</item>
|
||||
|
||||
<item name="widgetPreviewTitle"/>
|
||||
<item name="widgetPreviewContent"/>
|
||||
<item name="widgetPreviewTime"/>
|
||||
<item name="widgetPreviewDot">0</item>
|
||||
<item name="widgetPreviewImage">@null</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget.Preview">
|
||||
<item name="widgetPreviewTitle">Local Weather</item>
|
||||
<item name="widgetPreviewContent">☀ 30°C Sunny,</item>
|
||||
<item name="widgetPreviewTime">13:00</item>
|
||||
<item name="widgetPreviewDot">0</item>
|
||||
<item name="widgetPreviewImage">@drawable/widget_avatar_5</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget.Preview2">
|
||||
<item name="widgetPreviewTitle">Rex</item>
|
||||
<item name="widgetPreviewContent">It\'s morning in Tokyo 😎</item>
|
||||
<item name="widgetPreviewTime">12:00</item>
|
||||
<item name="widgetPreviewDot">2</item>
|
||||
<item name="widgetPreviewImage">@drawable/widget_avatar_7</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget.Preview3">
|
||||
<item name="widgetPreviewTitle">Dolph Ingman</item>
|
||||
<item name="widgetPreviewContent">😅 Sticker</item>
|
||||
<item name="widgetPreviewTime">11:00</item>
|
||||
<item name="widgetPreviewDot">2</item>
|
||||
<item name="widgetPreviewImage">@drawable/widget_avatar_6</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget.Preview4">
|
||||
<item name="widgetPreviewTitle">Doge</item>
|
||||
<item name="widgetPreviewDot">0</item>
|
||||
<item name="widgetPreviewImage">@drawable/widget_avatar_1</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget.Preview5">
|
||||
<item name="widgetPreviewTitle">Donald</item>
|
||||
<item name="widgetPreviewDot">2</item>
|
||||
<item name="widgetPreviewImage">@drawable/widget_avatar_4</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget.Preview6">
|
||||
<item name="widgetPreviewTitle">Kate</item>
|
||||
<item name="widgetPreviewDot">2</item>
|
||||
<item name="widgetPreviewImage">@drawable/widget_avatar_2</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.TMessages.AppWidget.Preview7">
|
||||
<item name="widgetPreviewTitle">Nick</item>
|
||||
<item name="widgetPreviewDot">2</item>
|
||||
<item name="widgetPreviewImage">@drawable/widget_avatar_3</item>
|
||||
</style>
|
||||
|
||||
<!-- APP WIDGET STYLES-->
|
||||
|
||||
<style name="Base.TMessages.AppWidget.Background" parent="android:Widget">
|
||||
<item name="android:id">@android:id/background</item>
|
||||
<item name="android:padding">2dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TMessages.AppWidget.Background" parent="Base.TMessages.AppWidget.Background">
|
||||
<item name="android:background">@drawable/widget_bg</item>
|
||||
</style>
|
||||
|
||||
<style name="Base.TMessages.AppWidget.Badge" parent="android:Widget">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">23dp</item>
|
||||
<item name="android:paddingLeft">7dp</item>
|
||||
<item name="android:paddingRight">7dp</item>
|
||||
<item name="android:paddingBottom">1dp</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:minWidth">23dp</item>
|
||||
<item name="android:textSize">13dp</item>
|
||||
<item name="android:background">@drawable/widget_badge_background</item>
|
||||
</style>
|
||||
|
||||
<style name="TMessages.AppWidget.Badge" parent="Base.TMessages.AppWidget.Badge">
|
||||
<item name="android:textColor">@color/widget_badge</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
<resources>
|
||||
<bool name="isTablet">false</bool>
|
||||
<dimen name="custom_notification_corner_radius">2dip</dimen>
|
||||
<dimen name="app_widget_background_corner_radius">16dp</dimen>
|
||||
</resources>
|
|
@ -1,13 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="320dp"
|
||||
android:minHeight="78dp"
|
||||
android:minWidth="250dp"
|
||||
android:minHeight="110dp"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeHeight="40dp"
|
||||
android:targetCellWidth="4"
|
||||
android:targetCellHeight="2"
|
||||
android:updatePeriodMillis="3600000"
|
||||
android:initialLayout="@layout/shortcut_widget_layout_1"
|
||||
android:initialLayout="@layout/shortcut_widget_layout_2"
|
||||
android:autoAdvanceViewId="@id/list_view"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:widgetCategory="home_screen"
|
||||
android:description="@string/EditWidgetChatsInfo"
|
||||
android:previewImage="@drawable/chats_widget_preview"
|
||||
android:previewLayout="@layout/shortcut_widget_layout_preview"
|
||||
android:widgetFeatures="reconfigurable|configuration_optional"
|
||||
android:configure="org.telegram.ui.ChatsWidgetConfigActivity">
|
||||
</appwidget-provider>
|
|
@ -3,11 +3,18 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="110dp"
|
||||
android:minHeight="86dp"
|
||||
android:minResizeHeight="40dp"
|
||||
android:maxResizeHeight="110dp"
|
||||
android:targetCellWidth="2"
|
||||
android:targetCellHeight="2"
|
||||
android:updatePeriodMillis="3600000"
|
||||
android:initialLayout="@layout/contacts_widget_layout_2"
|
||||
android:autoAdvanceViewId="@id/list_view"
|
||||
android:resizeMode="vertical"
|
||||
android:widgetCategory="home_screen"
|
||||
android:description="@string/EditWidgetContactsInfo"
|
||||
android:previewImage="@drawable/contacts_widget_preview"
|
||||
android:previewLayout="@layout/contacts_widget_layout_preview"
|
||||
android:widgetFeatures="reconfigurable|configuration_optional"
|
||||
android:configure="org.telegram.ui.ContactsWidgetConfigActivity">
|
||||
</appwidget-provider>
|