Update to 8.7.1
|
@ -300,7 +300,7 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig.versionCode = 2622
|
defaultConfig.versionCode = 2629
|
||||||
|
|
||||||
applicationVariants.all { variant ->
|
applicationVariants.all { variant ->
|
||||||
variant.outputs.all { output ->
|
variant.outputs.all { output ->
|
||||||
|
@ -319,7 +319,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionName "8.7.0"
|
versionName "8.7.1"
|
||||||
|
|
||||||
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']
|
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ constexpr auto kServiceCauseResend = 2;
|
||||||
|
|
||||||
static constexpr uint8_t kAckId = uint8_t(-1);
|
static constexpr uint8_t kAckId = uint8_t(-1);
|
||||||
static constexpr uint8_t kEmptyId = uint8_t(-2);
|
static constexpr uint8_t kEmptyId = uint8_t(-2);
|
||||||
|
static constexpr uint8_t kCustomId = uint8_t(127);
|
||||||
|
|
||||||
void AppendSeq(rtc::CopyOnWriteBuffer &buffer, uint32_t seq) {
|
void AppendSeq(rtc::CopyOnWriteBuffer &buffer, uint32_t seq) {
|
||||||
const auto bytes = rtc::HostToNetwork32(seq);
|
const auto bytes = rtc::HostToNetwork32(seq);
|
||||||
|
@ -68,6 +69,22 @@ bool ConstTimeIsDifferent(const void *a, const void *b, size_t size) {
|
||||||
return different;
|
return different;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc::CopyOnWriteBuffer SerializeRawMessageWithSeq(
|
||||||
|
const rtc::CopyOnWriteBuffer &message,
|
||||||
|
uint32_t seq,
|
||||||
|
bool singleMessagePacket) {
|
||||||
|
rtc::ByteBufferWriter writer;
|
||||||
|
writer.WriteUInt32(seq);
|
||||||
|
writer.WriteUInt8(kCustomId);
|
||||||
|
writer.WriteUInt32((uint32_t)message.size());
|
||||||
|
writer.WriteBytes((const char *)message.data(), message.size());
|
||||||
|
|
||||||
|
auto result = rtc::CopyOnWriteBuffer();
|
||||||
|
result.AppendData(writer.Data(), writer.Length());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
EncryptedConnection::EncryptedConnection(
|
EncryptedConnection::EncryptedConnection(
|
||||||
|
@ -152,6 +169,25 @@ auto EncryptedConnection::prepareForSending(const Message &message)
|
||||||
}
|
}
|
||||||
const auto seq = *maybeSeq;
|
const auto seq = *maybeSeq;
|
||||||
auto serialized = SerializeMessageWithSeq(message, seq, singleMessagePacket);
|
auto serialized = SerializeMessageWithSeq(message, seq, singleMessagePacket);
|
||||||
|
|
||||||
|
return prepareForSendingMessageInternal(serialized, seq, messageRequiresAck);
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::optional<EncryptedConnection::EncryptedPacket> EncryptedConnection::prepareForSendingRawMessage(rtc::CopyOnWriteBuffer &message, bool messageRequiresAck) {
|
||||||
|
// If message requires ack, then we can't serialize it as a single
|
||||||
|
// message packet, because later it may be sent as a part of big packet.
|
||||||
|
const auto singleMessagePacket = !haveAdditionalMessages() && !messageRequiresAck;
|
||||||
|
const auto maybeSeq = computeNextSeq(messageRequiresAck, singleMessagePacket);
|
||||||
|
if (!maybeSeq) {
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
const auto seq = *maybeSeq;
|
||||||
|
auto serialized = SerializeRawMessageWithSeq(message, seq, singleMessagePacket);
|
||||||
|
|
||||||
|
return prepareForSendingMessageInternal(serialized, seq, messageRequiresAck);
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::optional<EncryptedConnection::EncryptedPacket> EncryptedConnection::prepareForSendingMessageInternal(rtc::CopyOnWriteBuffer &serialized, uint32_t seq, bool messageRequiresAck) {
|
||||||
if (!enoughSpaceInPacket(serialized, 0)) {
|
if (!enoughSpaceInPacket(serialized, 0)) {
|
||||||
return LogError("Too large packet: ", std::to_string(serialized.size()));
|
return LogError("Too large packet: ", std::to_string(serialized.size()));
|
||||||
}
|
}
|
||||||
|
@ -404,6 +440,41 @@ auto EncryptedConnection::handleIncomingPacket(const char *bytes, size_t size)
|
||||||
return processPacket(decryptionBuffer, incomingSeq);
|
return processPacket(decryptionBuffer, incomingSeq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::optional<EncryptedConnection::DecryptedRawPacket> EncryptedConnection::handleIncomingRawPacket(const char *bytes, size_t size) {
|
||||||
|
if (size < 21 || size > kMaxIncomingPacketSize) {
|
||||||
|
return LogError("Bad incoming packet size: ", std::to_string(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto x = (_key.isOutgoing ? 8 : 0) + (_type == Type::Signaling ? 128 : 0);
|
||||||
|
const auto key = _key.value->data();
|
||||||
|
const auto msgKey = reinterpret_cast<const uint8_t*>(bytes);
|
||||||
|
const auto encryptedData = msgKey + 16;
|
||||||
|
const auto dataSize = size - 16;
|
||||||
|
|
||||||
|
auto aesKeyIv = PrepareAesKeyIv(key, msgKey, x);
|
||||||
|
|
||||||
|
auto decryptionBuffer = rtc::Buffer(dataSize);
|
||||||
|
AesProcessCtr(
|
||||||
|
MemorySpan{ encryptedData, dataSize },
|
||||||
|
decryptionBuffer.data(),
|
||||||
|
std::move(aesKeyIv));
|
||||||
|
|
||||||
|
const auto msgKeyLarge = ConcatSHA256(
|
||||||
|
MemorySpan{ key + 88 + x, 32 },
|
||||||
|
MemorySpan{ decryptionBuffer.data(), decryptionBuffer.size() });
|
||||||
|
if (ConstTimeIsDifferent(msgKeyLarge.data() + 8, msgKey, 16)) {
|
||||||
|
return LogError("Bad incoming data hash.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto incomingSeq = ReadSeq(decryptionBuffer.data());
|
||||||
|
const auto incomingCounter = CounterFromSeq(incomingSeq);
|
||||||
|
if (!registerIncomingCounter(incomingCounter)) {
|
||||||
|
// We've received that packet already.
|
||||||
|
return LogError("Already handled packet received.", std::to_string(incomingCounter));
|
||||||
|
}
|
||||||
|
return processRawPacket(decryptionBuffer, incomingSeq);
|
||||||
|
}
|
||||||
|
|
||||||
auto EncryptedConnection::processPacket(
|
auto EncryptedConnection::processPacket(
|
||||||
const rtc::Buffer &fullBuffer,
|
const rtc::Buffer &fullBuffer,
|
||||||
uint32_t packetSeq)
|
uint32_t packetSeq)
|
||||||
|
@ -490,6 +561,98 @@ auto EncryptedConnection::processPacket(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto EncryptedConnection::processRawPacket(
|
||||||
|
const rtc::Buffer &fullBuffer,
|
||||||
|
uint32_t packetSeq)
|
||||||
|
-> absl::optional<DecryptedRawPacket> {
|
||||||
|
assert(fullBuffer.size() >= 5);
|
||||||
|
|
||||||
|
auto additionalMessage = false;
|
||||||
|
auto firstMessageRequiringAck = true;
|
||||||
|
auto newRequiringAckReceived = false;
|
||||||
|
|
||||||
|
auto currentSeq = packetSeq;
|
||||||
|
auto currentCounter = CounterFromSeq(currentSeq);
|
||||||
|
rtc::ByteBufferReader reader(
|
||||||
|
reinterpret_cast<const char*>(fullBuffer.data() + 4), // Skip seq.
|
||||||
|
fullBuffer.size() - 4);
|
||||||
|
|
||||||
|
auto result = absl::optional<DecryptedRawPacket>();
|
||||||
|
while (true) {
|
||||||
|
const auto type = uint8_t(*reader.Data());
|
||||||
|
const auto singleMessagePacket = ((currentSeq & kSingleMessagePacketSeqBit) != 0);
|
||||||
|
if (singleMessagePacket && additionalMessage) {
|
||||||
|
return LogError("Single message packet bit in not first message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == kEmptyId) {
|
||||||
|
if (additionalMessage) {
|
||||||
|
return LogError("Empty message should be only the first one in the packet.");
|
||||||
|
}
|
||||||
|
RTC_LOG(LS_INFO) << logHeader()
|
||||||
|
<< "Got RECV:empty" << "#" << currentCounter;
|
||||||
|
reader.Consume(1);
|
||||||
|
} else if (type == kAckId) {
|
||||||
|
if (!additionalMessage) {
|
||||||
|
return LogError("Ack message must not be the first one in the packet.");
|
||||||
|
}
|
||||||
|
ackMyMessage(currentSeq);
|
||||||
|
reader.Consume(1);
|
||||||
|
} else if (type == kCustomId) {
|
||||||
|
reader.Consume(1);
|
||||||
|
|
||||||
|
if (auto message = DeserializeRawMessage(reader, singleMessagePacket)) {
|
||||||
|
const auto messageRequiresAck = ((currentSeq & kMessageRequiresAckSeqBit) != 0);
|
||||||
|
const auto skipMessage = messageRequiresAck
|
||||||
|
? !registerSentAck(currentCounter, firstMessageRequiringAck)
|
||||||
|
: (additionalMessage && !registerIncomingCounter(currentCounter));
|
||||||
|
if (messageRequiresAck) {
|
||||||
|
firstMessageRequiringAck = false;
|
||||||
|
if (!skipMessage) {
|
||||||
|
newRequiringAckReceived = true;
|
||||||
|
}
|
||||||
|
sendAckPostponed(currentSeq);
|
||||||
|
RTC_LOG(LS_INFO) << logHeader()
|
||||||
|
<< (skipMessage ? "Repeated RECV:type" : "Got RECV:type") << type << "#" << currentCounter;
|
||||||
|
}
|
||||||
|
if (!skipMessage) {
|
||||||
|
appendReceivedRawMessage(result, std::move(*message), currentSeq);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return LogError("Could not parse message from packet, type: ", std::to_string(type));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return LogError("Could not parse message from packet, type: ", std::to_string(type));
|
||||||
|
}
|
||||||
|
if (!reader.Length()) {
|
||||||
|
break;
|
||||||
|
} else if (singleMessagePacket) {
|
||||||
|
return LogError("Single message didn't fill the entire packet.");
|
||||||
|
} else if (reader.Length() < 5) {
|
||||||
|
return LogError("Bad remaining data size: ", std::to_string(reader.Length()));
|
||||||
|
}
|
||||||
|
const auto success = reader.ReadUInt32(¤tSeq);
|
||||||
|
assert(success);
|
||||||
|
(void)success;
|
||||||
|
currentCounter = CounterFromSeq(currentSeq);
|
||||||
|
|
||||||
|
additionalMessage = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_acksToSendSeqs.empty()) {
|
||||||
|
if (newRequiringAckReceived) {
|
||||||
|
_requestSendService(0, 0);
|
||||||
|
} else if (!_sendAcksTimerActive) {
|
||||||
|
_sendAcksTimerActive = true;
|
||||||
|
_requestSendService(
|
||||||
|
_delayIntervals.maxDelayBeforeAckResend,
|
||||||
|
kServiceCauseAcks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void EncryptedConnection::appendReceivedMessage(
|
void EncryptedConnection::appendReceivedMessage(
|
||||||
absl::optional<DecryptedPacket> &to,
|
absl::optional<DecryptedPacket> &to,
|
||||||
Message &&message,
|
Message &&message,
|
||||||
|
@ -505,6 +668,21 @@ void EncryptedConnection::appendReceivedMessage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EncryptedConnection::appendReceivedRawMessage(
|
||||||
|
absl::optional<DecryptedRawPacket> &to,
|
||||||
|
rtc::CopyOnWriteBuffer &&message,
|
||||||
|
uint32_t incomingSeq) {
|
||||||
|
auto decrypted = DecryptedRawMessage{
|
||||||
|
std::move(message),
|
||||||
|
CounterFromSeq(incomingSeq)
|
||||||
|
};
|
||||||
|
if (to) {
|
||||||
|
to->additional.push_back(std::move(decrypted));
|
||||||
|
} else {
|
||||||
|
to = DecryptedRawPacket{ std::move(decrypted) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char *EncryptedConnection::logHeader() const {
|
const char *EncryptedConnection::logHeader() const {
|
||||||
return (_type == Type::Signaling) ? "(signaling) " : "(transport) ";
|
return (_type == Type::Signaling) ? "(signaling) " : "(transport) ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,19 @@ public:
|
||||||
uint32_t counter = 0;
|
uint32_t counter = 0;
|
||||||
};
|
};
|
||||||
absl::optional<EncryptedPacket> prepareForSending(const Message &message);
|
absl::optional<EncryptedPacket> prepareForSending(const Message &message);
|
||||||
|
absl::optional<EncryptedPacket> prepareForSendingRawMessage(rtc::CopyOnWriteBuffer &serialized, bool messageRequiresAck);
|
||||||
absl::optional<EncryptedPacket> prepareForSendingService(int cause);
|
absl::optional<EncryptedPacket> prepareForSendingService(int cause);
|
||||||
|
|
||||||
struct DecryptedPacket {
|
struct DecryptedPacket {
|
||||||
DecryptedMessage main;
|
DecryptedMessage main;
|
||||||
std::vector<DecryptedMessage> additional;
|
std::vector<DecryptedMessage> additional;
|
||||||
};
|
};
|
||||||
|
struct DecryptedRawPacket {
|
||||||
|
DecryptedRawMessage main;
|
||||||
|
std::vector<DecryptedRawMessage> additional;
|
||||||
|
};
|
||||||
absl::optional<DecryptedPacket> handleIncomingPacket(const char *bytes, size_t size);
|
absl::optional<DecryptedPacket> handleIncomingPacket(const char *bytes, size_t size);
|
||||||
|
absl::optional<DecryptedRawPacket> handleIncomingRawPacket(const char *bytes, size_t size);
|
||||||
|
|
||||||
absl::optional<rtc::CopyOnWriteBuffer> encryptRawPacket(rtc::CopyOnWriteBuffer const &buffer);
|
absl::optional<rtc::CopyOnWriteBuffer> encryptRawPacket(rtc::CopyOnWriteBuffer const &buffer);
|
||||||
absl::optional<rtc::CopyOnWriteBuffer> decryptRawPacket(rtc::CopyOnWriteBuffer const &buffer);
|
absl::optional<rtc::CopyOnWriteBuffer> decryptRawPacket(rtc::CopyOnWriteBuffer const &buffer);
|
||||||
|
@ -57,6 +63,7 @@ private:
|
||||||
EncryptedPacket encryptPrepared(const rtc::CopyOnWriteBuffer &buffer);
|
EncryptedPacket encryptPrepared(const rtc::CopyOnWriteBuffer &buffer);
|
||||||
bool registerIncomingCounter(uint32_t incomingCounter);
|
bool registerIncomingCounter(uint32_t incomingCounter);
|
||||||
absl::optional<DecryptedPacket> processPacket(const rtc::Buffer &fullBuffer, uint32_t packetSeq);
|
absl::optional<DecryptedPacket> processPacket(const rtc::Buffer &fullBuffer, uint32_t packetSeq);
|
||||||
|
absl::optional<DecryptedRawPacket> processRawPacket(const rtc::Buffer &fullBuffer, uint32_t packetSeq);
|
||||||
bool registerSentAck(uint32_t counter, bool firstInPacket);
|
bool registerSentAck(uint32_t counter, bool firstInPacket);
|
||||||
void ackMyMessage(uint32_t counter);
|
void ackMyMessage(uint32_t counter);
|
||||||
void sendAckPostponed(uint32_t incomingSeq);
|
void sendAckPostponed(uint32_t incomingSeq);
|
||||||
|
@ -66,6 +73,11 @@ private:
|
||||||
absl::optional<DecryptedPacket> &to,
|
absl::optional<DecryptedPacket> &to,
|
||||||
Message &&message,
|
Message &&message,
|
||||||
uint32_t incomingSeq);
|
uint32_t incomingSeq);
|
||||||
|
void appendReceivedRawMessage(
|
||||||
|
absl::optional<DecryptedRawPacket> &to,
|
||||||
|
rtc::CopyOnWriteBuffer &&message,
|
||||||
|
uint32_t incomingSeq);
|
||||||
|
absl::optional<EncryptedPacket> prepareForSendingMessageInternal(rtc::CopyOnWriteBuffer &serialized, uint32_t seq, bool messageRequiresAck);
|
||||||
|
|
||||||
const char *logHeader() const;
|
const char *logHeader() const;
|
||||||
|
|
||||||
|
|
|
@ -215,6 +215,7 @@ template <typename Implementation>
|
||||||
bool Register();
|
bool Register();
|
||||||
|
|
||||||
struct Descriptor {
|
struct Descriptor {
|
||||||
|
std::string version;
|
||||||
Config config;
|
Config config;
|
||||||
PersistentState persistentState;
|
PersistentState persistentState;
|
||||||
std::vector<Endpoint> endpoints;
|
std::vector<Endpoint> endpoints;
|
||||||
|
|
|
@ -378,4 +378,29 @@ absl::optional<Message> DeserializeMessage(
|
||||||
: absl::nullopt;
|
: absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::optional<rtc::CopyOnWriteBuffer> DeserializeRawMessage(
|
||||||
|
rtc::ByteBufferReader &reader,
|
||||||
|
bool singleMessagePacket) {
|
||||||
|
if (!reader.Length()) {
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t length = 0;
|
||||||
|
if (!reader.ReadUInt32(&length)) {
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < 0 || length > 1024 * 1024) {
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::CopyOnWriteBuffer result;
|
||||||
|
result.SetSize(length);
|
||||||
|
if (!reader.ReadBytes((char *)result.MutableData(), result.size())) {
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace tgcalls
|
} // namespace tgcalls
|
||||||
|
|
|
@ -18,13 +18,14 @@ enum class AudioState;
|
||||||
struct PeerIceParameters {
|
struct PeerIceParameters {
|
||||||
std::string ufrag;
|
std::string ufrag;
|
||||||
std::string pwd;
|
std::string pwd;
|
||||||
|
bool supportsRenomination = false;
|
||||||
|
|
||||||
PeerIceParameters() = default;
|
PeerIceParameters() = default;
|
||||||
PeerIceParameters(const PeerIceParameters &other) = default;
|
|
||||||
|
|
||||||
PeerIceParameters(std::string ufrag_, std::string pwd_) :
|
PeerIceParameters(std::string ufrag_, std::string pwd_, bool supportsRenomination_) :
|
||||||
ufrag(ufrag_),
|
ufrag(ufrag_),
|
||||||
pwd(pwd_) {
|
pwd(pwd_),
|
||||||
|
supportsRenomination(supportsRenomination_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -127,12 +128,21 @@ rtc::CopyOnWriteBuffer SerializeMessageWithSeq(
|
||||||
absl::optional<Message> DeserializeMessage(
|
absl::optional<Message> DeserializeMessage(
|
||||||
rtc::ByteBufferReader &reader,
|
rtc::ByteBufferReader &reader,
|
||||||
bool singleMessagePacket);
|
bool singleMessagePacket);
|
||||||
|
absl::optional<rtc::CopyOnWriteBuffer> DeserializeRawMessage(
|
||||||
|
rtc::ByteBufferReader &reader,
|
||||||
|
bool singleMessagePacket);
|
||||||
|
|
||||||
struct DecryptedMessage {
|
struct DecryptedMessage {
|
||||||
Message message;
|
Message message;
|
||||||
uint32_t counter = 0;
|
uint32_t counter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DecryptedRawMessage {
|
||||||
|
rtc::CopyOnWriteBuffer message;
|
||||||
|
uint32_t counter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace tgcalls
|
} // namespace tgcalls
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -88,7 +88,7 @@ _isOutgoing(encryptionKey.isOutgoing),
|
||||||
_stateUpdated(std::move(stateUpdated)),
|
_stateUpdated(std::move(stateUpdated)),
|
||||||
_transportMessageReceived(std::move(transportMessageReceived)),
|
_transportMessageReceived(std::move(transportMessageReceived)),
|
||||||
_sendSignalingMessage(std::move(sendSignalingMessage)),
|
_sendSignalingMessage(std::move(sendSignalingMessage)),
|
||||||
_localIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH)) {
|
_localIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), false) {
|
||||||
assert(_thread->IsCurrent());
|
assert(_thread->IsCurrent());
|
||||||
|
|
||||||
_networkMonitorFactory = PlatformInterface::SharedInstance()->createNetworkMonitorFactory();
|
_networkMonitorFactory = PlatformInterface::SharedInstance()->createNetworkMonitorFactory();
|
||||||
|
@ -207,7 +207,7 @@ void NetworkManager::receiveSignalingMessage(DecryptedMessage &&message) {
|
||||||
assert(list != nullptr);
|
assert(list != nullptr);
|
||||||
|
|
||||||
if (!_remoteIceParameters.has_value()) {
|
if (!_remoteIceParameters.has_value()) {
|
||||||
PeerIceParameters parameters(list->iceParameters.ufrag, list->iceParameters.pwd);
|
PeerIceParameters parameters(list->iceParameters.ufrag, list->iceParameters.pwd, false);
|
||||||
_remoteIceParameters = parameters;
|
_remoteIceParameters = parameters;
|
||||||
|
|
||||||
cricket::IceParameters remoteIceParameters(
|
cricket::IceParameters remoteIceParameters(
|
||||||
|
|
|
@ -61,16 +61,20 @@ public:
|
||||||
explicit ThreadsImpl(size_t i) {
|
explicit ThreadsImpl(size_t i) {
|
||||||
auto suffix = i == 0 ? "" : "#" + std::to_string(i);
|
auto suffix = i == 0 ? "" : "#" + std::to_string(i);
|
||||||
media_ = create("tgc-media" + suffix);
|
media_ = create("tgc-media" + suffix);
|
||||||
//worker_ = create("tgc-work" + suffix);
|
worker_ = create("tgc-work" + suffix);
|
||||||
worker_ = create_network("tgc-work" + suffix);
|
network_ = create_network("tgc-net" + suffix);
|
||||||
//network_ = create_network("tgc-net" + suffix);
|
|
||||||
|
media_->AllowInvokesToThread(worker_.get());
|
||||||
|
media_->AllowInvokesToThread(network_.get());
|
||||||
|
worker_->AllowInvokesToThread(network_.get());
|
||||||
|
|
||||||
//network_->DisallowAllInvokes();
|
//network_->DisallowAllInvokes();
|
||||||
//worker_->DisallowAllInvokes();
|
//worker_->DisallowAllInvokes();
|
||||||
//worker_->AllowInvokesToThread(network_.get());
|
//worker_->AllowInvokesToThread(network_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc::Thread *getNetworkThread() override {
|
rtc::Thread *getNetworkThread() override {
|
||||||
return worker_.get();
|
return network_.get();
|
||||||
}
|
}
|
||||||
rtc::Thread *getMediaThread() override {
|
rtc::Thread *getMediaThread() override {
|
||||||
return media_.get();
|
return media_.get();
|
||||||
|
@ -90,7 +94,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//Thread network_;
|
Thread network_;
|
||||||
Thread media_;
|
Thread media_;
|
||||||
Thread worker_;
|
Thread worker_;
|
||||||
rtc::scoped_refptr<webrtc::SharedModuleThread> shared_module_thread_;
|
rtc::scoped_refptr<webrtc::SharedModuleThread> shared_module_thread_;
|
||||||
|
|
|
@ -318,7 +318,7 @@ _dataChannelMessageReceived(dataChannelMessageReceived),
|
||||||
_audioActivityUpdated(audioActivityUpdated) {
|
_audioActivityUpdated(audioActivityUpdated) {
|
||||||
assert(_threads->getNetworkThread()->IsCurrent());
|
assert(_threads->getNetworkThread()->IsCurrent());
|
||||||
|
|
||||||
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH));
|
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), false);
|
||||||
|
|
||||||
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
||||||
|
|
||||||
|
@ -452,7 +452,7 @@ void GroupNetworkManager::stop() {
|
||||||
_transportChannel.reset();
|
_transportChannel.reset();
|
||||||
_portAllocator.reset();
|
_portAllocator.reset();
|
||||||
|
|
||||||
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH));
|
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), false);
|
||||||
|
|
||||||
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,23 @@
|
||||||
namespace tgcalls {
|
namespace tgcalls {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
enum class SignalingProtocolVersion {
|
||||||
|
V1,
|
||||||
|
V2
|
||||||
|
};
|
||||||
|
|
||||||
|
SignalingProtocolVersion signalingProtocolVersion(std::string const &version) {
|
||||||
|
if (version == "4.0.1") {
|
||||||
|
return SignalingProtocolVersion::V1;
|
||||||
|
} else if (version == "4.0.2") {
|
||||||
|
return SignalingProtocolVersion::V2;
|
||||||
|
} else {
|
||||||
|
RTC_LOG(LS_ERROR) << "signalingProtocolVersion: unknown version " << version;
|
||||||
|
|
||||||
|
return SignalingProtocolVersion::V2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(VideoCaptureInterface *videoCapture) {
|
static VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(VideoCaptureInterface *videoCapture) {
|
||||||
return videoCapture
|
return videoCapture
|
||||||
? static_cast<VideoCaptureInterfaceImpl*>(videoCapture)->object()->getSyncAssumingSameThread()
|
? static_cast<VideoCaptureInterfaceImpl*>(videoCapture)->object()->getSyncAssumingSameThread()
|
||||||
|
@ -777,6 +794,7 @@ struct NetworkBitrateLogRecord {
|
||||||
class InstanceV2ImplInternal : public std::enable_shared_from_this<InstanceV2ImplInternal> {
|
class InstanceV2ImplInternal : public std::enable_shared_from_this<InstanceV2ImplInternal> {
|
||||||
public:
|
public:
|
||||||
InstanceV2ImplInternal(Descriptor &&descriptor, std::shared_ptr<Threads> threads) :
|
InstanceV2ImplInternal(Descriptor &&descriptor, std::shared_ptr<Threads> threads) :
|
||||||
|
_signalingProtocolVersion(signalingProtocolVersion(descriptor.version)),
|
||||||
_threads(threads),
|
_threads(threads),
|
||||||
_rtcServers(descriptor.rtcServers),
|
_rtcServers(descriptor.rtcServers),
|
||||||
_proxy(std::move(descriptor.proxy)),
|
_proxy(std::move(descriptor.proxy)),
|
||||||
|
@ -927,7 +945,7 @@ public:
|
||||||
_threads->getNetworkThread()
|
_threads->getNetworkThread()
|
||||||
);
|
);
|
||||||
|
|
||||||
webrtc::Call::Config callConfig(_eventLog.get());
|
webrtc::Call::Config callConfig(_eventLog.get(), _threads->getNetworkThread());
|
||||||
callConfig.task_queue_factory = _taskQueueFactory.get();
|
callConfig.task_queue_factory = _taskQueueFactory.get();
|
||||||
callConfig.trials = &_fieldTrials;
|
callConfig.trials = &_fieldTrials;
|
||||||
callConfig.audio_state = _channelManager->media_engine()->voice().GetAudioState();
|
callConfig.audio_state = _channelManager->media_engine()->voice().GetAudioState();
|
||||||
|
@ -1033,28 +1051,87 @@ public:
|
||||||
|
|
||||||
void sendSignalingMessage(signaling::Message const &message) {
|
void sendSignalingMessage(signaling::Message const &message) {
|
||||||
auto data = message.serialize();
|
auto data = message.serialize();
|
||||||
|
sendRawSignalingMessage(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendRawSignalingMessage(std::vector<uint8_t> const &data) {
|
||||||
RTC_LOG(LS_INFO) << "sendSignalingMessage: " << std::string(data.begin(), data.end());
|
RTC_LOG(LS_INFO) << "sendSignalingMessage: " << std::string(data.begin(), data.end());
|
||||||
|
|
||||||
if (_signalingEncryption) {
|
if (_signalingEncryptedConnection) {
|
||||||
if (const auto encryptedData = _signalingEncryption->encryptOutgoing(data)) {
|
switch (_signalingProtocolVersion) {
|
||||||
_signalingDataEmitted(std::vector<uint8_t>(encryptedData->data(), encryptedData->data() + encryptedData->size()));
|
case SignalingProtocolVersion::V1: {
|
||||||
|
if (const auto message = _signalingEncryptedConnection->encryptRawPacket(rtc::CopyOnWriteBuffer(data.data(), data.size()))) {
|
||||||
|
_signalingDataEmitted(std::vector<uint8_t>(message.value().data(), message.value().data() + message.value().size()));
|
||||||
} else {
|
} else {
|
||||||
RTC_LOG(LS_ERROR) << "sendSignalingMessage: failed to encrypt payload";
|
RTC_LOG(LS_ERROR) << "Could not encrypt signaling message";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SignalingProtocolVersion::V2: {
|
||||||
|
rtc::CopyOnWriteBuffer message;
|
||||||
|
message.AppendData(data.data(), data.size());
|
||||||
|
|
||||||
|
commitSendSignalingMessage(_signalingEncryptedConnection->prepareForSendingRawMessage(message, true));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
RTC_DCHECK_NOTREACHED();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_signalingDataEmitted(data);
|
RTC_LOG(LS_ERROR) << "sendSignalingMessage encryption not available";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void commitSendSignalingMessage(absl::optional<EncryptedConnection::EncryptedPacket> packet) {
|
||||||
|
if (!packet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_signalingDataEmitted(packet.value().bytes);
|
||||||
|
}
|
||||||
|
|
||||||
void beginSignaling() {
|
void beginSignaling() {
|
||||||
_signalingEncryption.reset(new SignalingEncryption(_encryptionKey));
|
const auto weak = std::weak_ptr<InstanceV2ImplInternal>(shared_from_this());
|
||||||
|
|
||||||
|
_signalingEncryptedConnection = std::make_unique<EncryptedConnection>(
|
||||||
|
EncryptedConnection::Type::Signaling,
|
||||||
|
_encryptionKey,
|
||||||
|
[weak, threads = _threads](int delayMs, int cause) {
|
||||||
|
if (delayMs == 0) {
|
||||||
|
threads->getMediaThread()->PostTask(RTC_FROM_HERE, [weak, cause]() {
|
||||||
|
const auto strong = weak.lock();
|
||||||
|
if (!strong) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong->sendPendingSignalingServiceData(cause);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
threads->getMediaThread()->PostDelayedTask(RTC_FROM_HERE, [weak, cause]() {
|
||||||
|
const auto strong = weak.lock();
|
||||||
|
if (!strong) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong->sendPendingSignalingServiceData(cause);
|
||||||
|
}, delayMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (_encryptionKey.isOutgoing) {
|
if (_encryptionKey.isOutgoing) {
|
||||||
sendInitialSetup();
|
sendInitialSetup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendPendingSignalingServiceData(int cause) {
|
||||||
|
commitSendSignalingMessage(_signalingEncryptedConnection->prepareForSendingService(cause));
|
||||||
|
}
|
||||||
|
|
||||||
void createNegotiatedChannels() {
|
void createNegotiatedChannels() {
|
||||||
const auto coordinatedState = _contentNegotiationContext->coordinatedState();
|
const auto coordinatedState = _contentNegotiationContext->coordinatedState();
|
||||||
if (!coordinatedState) {
|
if (!coordinatedState) {
|
||||||
|
@ -1295,8 +1372,9 @@ public:
|
||||||
auto localIceParams = networking->getLocalIceParameters();
|
auto localIceParams = networking->getLocalIceParameters();
|
||||||
std::string ufrag = localIceParams.ufrag;
|
std::string ufrag = localIceParams.ufrag;
|
||||||
std::string pwd = localIceParams.pwd;
|
std::string pwd = localIceParams.pwd;
|
||||||
|
bool supportsRenomination = localIceParams.supportsRenomination;
|
||||||
|
|
||||||
threads->getMediaThread()->PostTask(RTC_FROM_HERE, [weak, ufrag, pwd, hash, fingerprint, setup, localIceParams]() {
|
threads->getMediaThread()->PostTask(RTC_FROM_HERE, [weak, ufrag, pwd, supportsRenomination, hash, fingerprint, setup, localIceParams]() {
|
||||||
const auto strong = weak.lock();
|
const auto strong = weak.lock();
|
||||||
if (!strong) {
|
if (!strong) {
|
||||||
return;
|
return;
|
||||||
|
@ -1306,6 +1384,7 @@ public:
|
||||||
|
|
||||||
data.ufrag = ufrag;
|
data.ufrag = ufrag;
|
||||||
data.pwd = pwd;
|
data.pwd = pwd;
|
||||||
|
data.supportsRenomination = supportsRenomination;
|
||||||
|
|
||||||
signaling::DtlsFingerprint dtlsFingerprint;
|
signaling::DtlsFingerprint dtlsFingerprint;
|
||||||
dtlsFingerprint.hash = hash;
|
dtlsFingerprint.hash = hash;
|
||||||
|
@ -1335,21 +1414,41 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void receiveSignalingData(const std::vector<uint8_t> &data) {
|
void receiveSignalingData(const std::vector<uint8_t> &data) {
|
||||||
std::vector<uint8_t> decryptedData;
|
if (_signalingEncryptedConnection) {
|
||||||
|
switch (_signalingProtocolVersion) {
|
||||||
if (_signalingEncryption) {
|
case SignalingProtocolVersion::V1: {
|
||||||
const auto rawDecryptedData = _signalingEncryption->decryptIncoming(data);
|
if (const auto message = _signalingEncryptedConnection->decryptRawPacket(rtc::CopyOnWriteBuffer(data.data(), data.size()))) {
|
||||||
if (!rawDecryptedData) {
|
processSignalingMessage(message.value());
|
||||||
RTC_LOG(LS_ERROR) << "receiveSignalingData: could not decrypt payload";
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
decryptedData = std::vector<uint8_t>(rawDecryptedData->data(), rawDecryptedData->data() + rawDecryptedData->size());
|
|
||||||
} else {
|
} else {
|
||||||
decryptedData = data;
|
RTC_LOG(LS_ERROR) << "receiveSignalingData could not decrypt signaling data";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SignalingProtocolVersion::V2: {
|
||||||
|
if (const auto packet = _signalingEncryptedConnection->handleIncomingRawPacket((const char *)data.data(), data.size())) {
|
||||||
|
processSignalingMessage(packet.value().main.message);
|
||||||
|
|
||||||
|
for (const auto &additional : packet.value().additional) {
|
||||||
|
processSignalingMessage(additional.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
RTC_DCHECK_NOTREACHED();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RTC_LOG(LS_ERROR) << "receiveSignalingData encryption not available";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processSignalingMessage(rtc::CopyOnWriteBuffer const &data) {
|
||||||
|
std::vector<uint8_t> decryptedData = std::vector<uint8_t>(data.data(), data.data() + data.size());
|
||||||
processSignalingData(decryptedData);
|
processSignalingData(decryptedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1365,6 +1464,7 @@ public:
|
||||||
PeerIceParameters remoteIceParameters;
|
PeerIceParameters remoteIceParameters;
|
||||||
remoteIceParameters.ufrag = initialSetup->ufrag;
|
remoteIceParameters.ufrag = initialSetup->ufrag;
|
||||||
remoteIceParameters.pwd = initialSetup->pwd;
|
remoteIceParameters.pwd = initialSetup->pwd;
|
||||||
|
remoteIceParameters.supportsRenomination = initialSetup->supportsRenomination;
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLFingerprint> fingerprint;
|
std::unique_ptr<rtc::SSLFingerprint> fingerprint;
|
||||||
std::string sslSetup;
|
std::string sslSetup;
|
||||||
|
@ -1828,6 +1928,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SignalingProtocolVersion _signalingProtocolVersion;
|
||||||
std::shared_ptr<Threads> _threads;
|
std::shared_ptr<Threads> _threads;
|
||||||
std::vector<RtcServer> _rtcServers;
|
std::vector<RtcServer> _rtcServers;
|
||||||
std::unique_ptr<Proxy> _proxy;
|
std::unique_ptr<Proxy> _proxy;
|
||||||
|
@ -1843,7 +1944,7 @@ private:
|
||||||
std::function<rtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory*)> _createAudioDeviceModule;
|
std::function<rtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory*)> _createAudioDeviceModule;
|
||||||
FilePath _statsLogPath;
|
FilePath _statsLogPath;
|
||||||
|
|
||||||
std::unique_ptr<SignalingEncryption> _signalingEncryption;
|
std::unique_ptr<EncryptedConnection> _signalingEncryptedConnection;
|
||||||
|
|
||||||
int64_t _startTimestamp = 0;
|
int64_t _startTimestamp = 0;
|
||||||
|
|
||||||
|
@ -1993,6 +2094,7 @@ void InstanceV2Impl::setEchoCancellationStrength(int strength) {
|
||||||
std::vector<std::string> InstanceV2Impl::GetVersions() {
|
std::vector<std::string> InstanceV2Impl::GetVersions() {
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
result.push_back("4.0.1");
|
result.push_back("4.0.1");
|
||||||
|
result.push_back("4.0.2");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,21 +20,12 @@
|
||||||
#include "SctpDataChannelProviderInterfaceImpl.h"
|
#include "SctpDataChannelProviderInterfaceImpl.h"
|
||||||
#include "StaticThreads.h"
|
#include "StaticThreads.h"
|
||||||
#include "platform/PlatformInterface.h"
|
#include "platform/PlatformInterface.h"
|
||||||
|
#include "p2p/base/turn_port.h"
|
||||||
|
|
||||||
namespace tgcalls {
|
namespace tgcalls {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
NativeNetworkingImpl::ConnectionDescription::CandidateDescription connectionDescriptionFromCandidate(cricket::Candidate const &candidate) {
|
|
||||||
NativeNetworkingImpl::ConnectionDescription::CandidateDescription result;
|
|
||||||
|
|
||||||
result.type = candidate.type();
|
|
||||||
result.protocol = candidate.protocol();
|
|
||||||
result.address = candidate.address().ToString();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CryptStringImpl : public rtc::CryptStringImpl {
|
class CryptStringImpl : public rtc::CryptStringImpl {
|
||||||
public:
|
public:
|
||||||
CryptStringImpl(std::string const &value) :
|
CryptStringImpl(std::string const &value) :
|
||||||
|
@ -192,6 +183,16 @@ private:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NativeNetworkingImpl::ConnectionDescription::CandidateDescription NativeNetworkingImpl::connectionDescriptionFromCandidate(cricket::Candidate const &candidate) {
|
||||||
|
NativeNetworkingImpl::ConnectionDescription::CandidateDescription result;
|
||||||
|
|
||||||
|
result.type = candidate.type();
|
||||||
|
result.protocol = candidate.protocol();
|
||||||
|
result.address = candidate.address().ToString();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
webrtc::CryptoOptions NativeNetworkingImpl::getDefaulCryptoOptions() {
|
webrtc::CryptoOptions NativeNetworkingImpl::getDefaulCryptoOptions() {
|
||||||
auto options = webrtc::CryptoOptions();
|
auto options = webrtc::CryptoOptions();
|
||||||
options.srtp.enable_aes128_sha1_80_crypto_cipher = true;
|
options.srtp.enable_aes128_sha1_80_crypto_cipher = true;
|
||||||
|
@ -215,7 +216,7 @@ _dataChannelStateUpdated(configuration.dataChannelStateUpdated),
|
||||||
_dataChannelMessageReceived(configuration.dataChannelMessageReceived) {
|
_dataChannelMessageReceived(configuration.dataChannelMessageReceived) {
|
||||||
assert(_threads->getNetworkThread()->IsCurrent());
|
assert(_threads->getNetworkThread()->IsCurrent());
|
||||||
|
|
||||||
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH));
|
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), true);
|
||||||
|
|
||||||
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
||||||
|
|
||||||
|
@ -310,7 +311,7 @@ void NativeNetworkingImpl::resetDtlsSrtpTransport() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_portAllocator->SetConfiguration(stunServers, turnServers, 2, webrtc::NO_PRUNE, _turnCustomizer.get());
|
_portAllocator->SetConfiguration(stunServers, turnServers, 0, webrtc::NO_PRUNE, _turnCustomizer.get());
|
||||||
|
|
||||||
|
|
||||||
_transportChannel = cricket::P2PTransportChannel::Create("transport", 0, _portAllocator.get(), _asyncResolverFactory.get());
|
_transportChannel = cricket::P2PTransportChannel::Create("transport", 0, _portAllocator.get(), _asyncResolverFactory.get());
|
||||||
|
@ -324,7 +325,7 @@ void NativeNetworkingImpl::resetDtlsSrtpTransport() {
|
||||||
cricket::IceParameters localIceParameters(
|
cricket::IceParameters localIceParameters(
|
||||||
_localIceParameters.ufrag,
|
_localIceParameters.ufrag,
|
||||||
_localIceParameters.pwd,
|
_localIceParameters.pwd,
|
||||||
false
|
_localIceParameters.supportsRenomination
|
||||||
);
|
);
|
||||||
|
|
||||||
_transportChannel->SetIceParameters(localIceParameters);
|
_transportChannel->SetIceParameters(localIceParameters);
|
||||||
|
@ -334,7 +335,6 @@ void NativeNetworkingImpl::resetDtlsSrtpTransport() {
|
||||||
_transportChannel->SignalCandidateGathered.connect(this, &NativeNetworkingImpl::candidateGathered);
|
_transportChannel->SignalCandidateGathered.connect(this, &NativeNetworkingImpl::candidateGathered);
|
||||||
_transportChannel->SignalIceTransportStateChanged.connect(this, &NativeNetworkingImpl::transportStateChanged);
|
_transportChannel->SignalIceTransportStateChanged.connect(this, &NativeNetworkingImpl::transportStateChanged);
|
||||||
_transportChannel->SignalCandidatePairChanged.connect(this, &NativeNetworkingImpl::candidatePairChanged);
|
_transportChannel->SignalCandidatePairChanged.connect(this, &NativeNetworkingImpl::candidatePairChanged);
|
||||||
_transportChannel->SignalReadPacket.connect(this, &NativeNetworkingImpl::transportPacketReceived);
|
|
||||||
_transportChannel->SignalNetworkRouteChanged.connect(this, &NativeNetworkingImpl::transportRouteChanged);
|
_transportChannel->SignalNetworkRouteChanged.connect(this, &NativeNetworkingImpl::transportRouteChanged);
|
||||||
|
|
||||||
webrtc::CryptoOptions cryptoOptions = NativeNetworkingImpl::getDefaulCryptoOptions();
|
webrtc::CryptoOptions cryptoOptions = NativeNetworkingImpl::getDefaulCryptoOptions();
|
||||||
|
@ -384,7 +384,7 @@ void NativeNetworkingImpl::start() {
|
||||||
_threads
|
_threads
|
||||||
));
|
));
|
||||||
|
|
||||||
_lastNetworkActivityMs = rtc::TimeMillis();
|
_lastDisconnectedTimestamp = rtc::TimeMillis();
|
||||||
checkConnectionTimeout();
|
checkConnectionTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ void NativeNetworkingImpl::stop() {
|
||||||
_transportChannel.reset();
|
_transportChannel.reset();
|
||||||
_portAllocator.reset();
|
_portAllocator.reset();
|
||||||
|
|
||||||
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH));
|
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), true);
|
||||||
|
|
||||||
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
||||||
|
|
||||||
|
@ -429,7 +429,7 @@ void NativeNetworkingImpl::setRemoteParams(PeerIceParameters const &remoteIcePar
|
||||||
cricket::IceParameters parameters(
|
cricket::IceParameters parameters(
|
||||||
remoteIceParameters.ufrag,
|
remoteIceParameters.ufrag,
|
||||||
remoteIceParameters.pwd,
|
remoteIceParameters.pwd,
|
||||||
false
|
remoteIceParameters.supportsRenomination
|
||||||
);
|
);
|
||||||
|
|
||||||
_transportChannel->SetRemoteIceParameters(parameters);
|
_transportChannel->SetRemoteIceParameters(parameters);
|
||||||
|
@ -474,7 +474,9 @@ void NativeNetworkingImpl::checkConnectionTimeout() {
|
||||||
int64_t currentTimestamp = rtc::TimeMillis();
|
int64_t currentTimestamp = rtc::TimeMillis();
|
||||||
const int64_t maxTimeout = 20000;
|
const int64_t maxTimeout = 20000;
|
||||||
|
|
||||||
if (strong->_lastNetworkActivityMs + maxTimeout < currentTimestamp) {
|
if (!strong->_isConnected && strong->_lastDisconnectedTimestamp + maxTimeout < currentTimestamp) {
|
||||||
|
RTC_LOG(LS_INFO) << "NativeNetworkingImpl timeout " << (currentTimestamp - strong->_lastDisconnectedTimestamp) << " ms";
|
||||||
|
|
||||||
strong->_isFailed = true;
|
strong->_isFailed = true;
|
||||||
strong->notifyStateUpdated();
|
strong->notifyStateUpdated();
|
||||||
}
|
}
|
||||||
|
@ -527,13 +529,6 @@ void NativeNetworkingImpl::transportReadyToSend(cricket::IceTransportInternal *t
|
||||||
assert(_threads->getNetworkThread()->IsCurrent());
|
assert(_threads->getNetworkThread()->IsCurrent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeNetworkingImpl::transportPacketReceived(rtc::PacketTransportInternal *transport, const char *bytes, size_t size, const int64_t ×tamp, int unused) {
|
|
||||||
assert(_threads->getNetworkThread()->IsCurrent());
|
|
||||||
|
|
||||||
_lastNetworkActivityMs = rtc::TimeMillis();
|
|
||||||
_isFailed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeNetworkingImpl::transportRouteChanged(absl::optional<rtc::NetworkRoute> route) {
|
void NativeNetworkingImpl::transportRouteChanged(absl::optional<rtc::NetworkRoute> route) {
|
||||||
assert(_threads->getNetworkThread()->IsCurrent());
|
assert(_threads->getNetworkThread()->IsCurrent());
|
||||||
|
|
||||||
|
@ -606,6 +601,10 @@ void NativeNetworkingImpl::UpdateAggregateStates_n() {
|
||||||
if (_isConnected != isConnected) {
|
if (_isConnected != isConnected) {
|
||||||
_isConnected = isConnected;
|
_isConnected = isConnected;
|
||||||
|
|
||||||
|
if (!isConnected) {
|
||||||
|
_lastDisconnectedTimestamp = rtc::TimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
notifyStateUpdated();
|
notifyStateUpdated();
|
||||||
|
|
||||||
if (_dataChannelInterface) {
|
if (_dataChannelInterface) {
|
||||||
|
|
|
@ -143,6 +143,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
static webrtc::CryptoOptions getDefaulCryptoOptions();
|
static webrtc::CryptoOptions getDefaulCryptoOptions();
|
||||||
|
static ConnectionDescription::CandidateDescription connectionDescriptionFromCandidate(cricket::Candidate const &candidate);
|
||||||
|
|
||||||
NativeNetworkingImpl(Configuration &&configuration);
|
NativeNetworkingImpl(Configuration &&configuration);
|
||||||
~NativeNetworkingImpl();
|
~NativeNetworkingImpl();
|
||||||
|
@ -168,7 +169,6 @@ private:
|
||||||
void OnTransportReceivingState_n(rtc::PacketTransportInternal *transport);
|
void OnTransportReceivingState_n(rtc::PacketTransportInternal *transport);
|
||||||
void transportStateChanged(cricket::IceTransportInternal *transport);
|
void transportStateChanged(cricket::IceTransportInternal *transport);
|
||||||
void transportReadyToSend(cricket::IceTransportInternal *transport);
|
void transportReadyToSend(cricket::IceTransportInternal *transport);
|
||||||
void transportPacketReceived(rtc::PacketTransportInternal *transport, const char *bytes, size_t size, const int64_t ×tamp, int unused);
|
|
||||||
void transportRouteChanged(absl::optional<rtc::NetworkRoute> route);
|
void transportRouteChanged(absl::optional<rtc::NetworkRoute> route);
|
||||||
void candidatePairChanged(cricket::CandidatePairChangeEvent const &event);
|
void candidatePairChanged(cricket::CandidatePairChangeEvent const &event);
|
||||||
void DtlsReadyToSend(bool DtlsReadyToSend);
|
void DtlsReadyToSend(bool DtlsReadyToSend);
|
||||||
|
@ -214,7 +214,7 @@ private:
|
||||||
|
|
||||||
bool _isConnected = false;
|
bool _isConnected = false;
|
||||||
bool _isFailed = false;
|
bool _isFailed = false;
|
||||||
int64_t _lastNetworkActivityMs = 0;
|
int64_t _lastDisconnectedTimestamp = 0;
|
||||||
absl::optional<RouteDescription> _currentRouteDescription;
|
absl::optional<RouteDescription> _currentRouteDescription;
|
||||||
absl::optional<ConnectionDescription> _currentConnectionDescription;
|
absl::optional<ConnectionDescription> _currentConnectionDescription;
|
||||||
};
|
};
|
||||||
|
|
|
@ -366,6 +366,7 @@ std::vector<uint8_t> InitialSetupMessage_serialize(const InitialSetupMessage * c
|
||||||
object.insert(std::make_pair("@type", json11::Json("InitialSetup")));
|
object.insert(std::make_pair("@type", json11::Json("InitialSetup")));
|
||||||
object.insert(std::make_pair("ufrag", json11::Json(message->ufrag)));
|
object.insert(std::make_pair("ufrag", json11::Json(message->ufrag)));
|
||||||
object.insert(std::make_pair("pwd", json11::Json(message->pwd)));
|
object.insert(std::make_pair("pwd", json11::Json(message->pwd)));
|
||||||
|
object.insert(std::make_pair("renomination", json11::Json(message->supportsRenomination)));
|
||||||
|
|
||||||
json11::Json::array jsonFingerprints;
|
json11::Json::array jsonFingerprints;
|
||||||
for (const auto &fingerprint : message->fingerprints) {
|
for (const auto &fingerprint : message->fingerprints) {
|
||||||
|
@ -393,6 +394,11 @@ absl::optional<InitialSetupMessage> InitialSetupMessage_parse(json11::Json::obje
|
||||||
RTC_LOG(LS_ERROR) << "Signaling: pwd must be a string";
|
RTC_LOG(LS_ERROR) << "Signaling: pwd must be a string";
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
const auto renomination = object.find("renomination");
|
||||||
|
bool renominationValue = false;
|
||||||
|
if (renomination != object.end() && renomination->second.is_bool()) {
|
||||||
|
renominationValue = renomination->second.bool_value();
|
||||||
|
}
|
||||||
const auto fingerprints = object.find("fingerprints");
|
const auto fingerprints = object.find("fingerprints");
|
||||||
if (fingerprints == object.end() || !fingerprints->second.is_array()) {
|
if (fingerprints == object.end() || !fingerprints->second.is_array()) {
|
||||||
RTC_LOG(LS_ERROR) << "Signaling: fingerprints must be an array";
|
RTC_LOG(LS_ERROR) << "Signaling: fingerprints must be an array";
|
||||||
|
@ -431,6 +437,7 @@ absl::optional<InitialSetupMessage> InitialSetupMessage_parse(json11::Json::obje
|
||||||
InitialSetupMessage message;
|
InitialSetupMessage message;
|
||||||
message.ufrag = ufrag->second.string_value();
|
message.ufrag = ufrag->second.string_value();
|
||||||
message.pwd = pwd->second.string_value();
|
message.pwd = pwd->second.string_value();
|
||||||
|
message.supportsRenomination = renominationValue;
|
||||||
message.fingerprints = std::move(parsedFingerprints);
|
message.fingerprints = std::move(parsedFingerprints);
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
|
|
|
@ -138,6 +138,7 @@ struct MediaContent {
|
||||||
struct InitialSetupMessage {
|
struct InitialSetupMessage {
|
||||||
std::string ufrag;
|
std::string ufrag;
|
||||||
std::string pwd;
|
std::string pwd;
|
||||||
|
bool supportsRenomination = false;
|
||||||
std::vector<DtlsFingerprint> fingerprints;
|
std::vector<DtlsFingerprint> fingerprints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ public class BuildVars {
|
||||||
public static boolean USE_CLOUD_STRINGS = true;
|
public static boolean USE_CLOUD_STRINGS = true;
|
||||||
public static boolean CHECK_UPDATES = true;
|
public static boolean CHECK_UPDATES = true;
|
||||||
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
|
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
|
||||||
public static int BUILD_VERSION = 2622;
|
public static int BUILD_VERSION = 2629;
|
||||||
public static String BUILD_VERSION_STRING = "8.7.0";
|
public static String BUILD_VERSION_STRING = "8.7.1";
|
||||||
public static int APP_ID = 4;
|
public static int APP_ID = 4;
|
||||||
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
||||||
|
|
||||||
|
|
|
@ -1356,7 +1356,7 @@ public class DownloadController extends BaseController implements NotificationCe
|
||||||
for (int i = 0; i < messageObjects.size(); i++) {
|
for (int i = 0; i < messageObjects.size(); i++) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (int j = 0; j < recentDownloadingFiles.size(); j++) {
|
for (int j = 0; j < recentDownloadingFiles.size(); j++) {
|
||||||
if (messageObjects.get(i).getId() == recentDownloadingFiles.get(j).getId()) {
|
if (messageObjects.get(i).getId() == recentDownloadingFiles.get(j).getId() && recentDownloadingFiles.get(j).getDialogId() == messageObjects.get(i).getDialogId()) {
|
||||||
recentDownloadingFiles.remove(j);
|
recentDownloadingFiles.remove(j);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1364,7 +1364,7 @@ public class DownloadController extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
for (int j = 0; j < downloadingFiles.size(); j++) {
|
for (int j = 0; j < downloadingFiles.size(); j++) {
|
||||||
if (messageObjects.get(i).getId() == downloadingFiles.get(j).getId()) {
|
if (messageObjects.get(i).getId() == downloadingFiles.get(j).getId() && downloadingFiles.get(j).getDialogId() == messageObjects.get(i).getDialogId()) {
|
||||||
downloadingFiles.remove(j);
|
downloadingFiles.remove(j);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4912,6 +4912,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
info.mediaEntities,
|
info.mediaEntities,
|
||||||
info.isPhoto,
|
info.isPhoto,
|
||||||
info.cropState,
|
info.cropState,
|
||||||
|
info.roundVideo,
|
||||||
callback);
|
callback);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6417,7 +6417,7 @@ public class MessageObject {
|
||||||
for (int a = 0; a < getDocument().attributes.size(); a++) {
|
for (int a = 0; a < getDocument().attributes.size(); a++) {
|
||||||
TLRPC.DocumentAttribute attribute = getDocument().attributes.get(a);
|
TLRPC.DocumentAttribute attribute = getDocument().attributes.get(a);
|
||||||
if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
|
if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
|
||||||
if (attribute.duration < MessagesController.getInstance(currentAccount).ringtoneDurationMax * 2) {
|
if (attribute.duration < 60) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -835,7 +835,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
showFiltersTooltip = mainPreferences.getBoolean("showFiltersTooltip", false);
|
showFiltersTooltip = mainPreferences.getBoolean("showFiltersTooltip", false);
|
||||||
autoarchiveAvailable = mainPreferences.getBoolean("autoarchiveAvailable", false);
|
autoarchiveAvailable = mainPreferences.getBoolean("autoarchiveAvailable", false);
|
||||||
groupCallVideoMaxParticipants = mainPreferences.getInt("groipCallVideoMaxParticipants", 30);
|
groupCallVideoMaxParticipants = mainPreferences.getInt("groipCallVideoMaxParticipants", 30);
|
||||||
chatReadMarkSizeThreshold = mainPreferences.getInt("chatReadMarkSizeThreshold", 50);
|
chatReadMarkSizeThreshold = mainPreferences.getInt("chatReadMarkSizeThreshold", 100);
|
||||||
chatReadMarkExpirePeriod = mainPreferences.getInt("chatReadMarkExpirePeriod", 7 * 86400);
|
chatReadMarkExpirePeriod = mainPreferences.getInt("chatReadMarkExpirePeriod", 7 * 86400);
|
||||||
ringtoneDurationMax = mainPreferences.getInt("ringtoneDurationMax", 5);
|
ringtoneDurationMax = mainPreferences.getInt("ringtoneDurationMax", 5);
|
||||||
ringtoneSizeMax = mainPreferences.getInt("ringtoneSizeMax", 1024_00);
|
ringtoneSizeMax = mainPreferences.getInt("ringtoneSizeMax", 1024_00);
|
||||||
|
@ -10696,19 +10696,22 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
arr.add(obj);
|
arr.add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
|
||||||
for (int a = 0; a < messages.size(); a++) {
|
|
||||||
long key = messages.keyAt(a);
|
|
||||||
ArrayList<MessageObject> value = messages.valueAt(a);
|
|
||||||
updateInterfaceWithMessages(key, value, false);
|
|
||||||
}
|
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
|
||||||
});
|
|
||||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||||
if (!pushMessages.isEmpty()) {
|
if (!pushMessages.isEmpty()) {
|
||||||
AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, !(res instanceof TLRPC.TL_updates_differenceSlice), false, null));
|
AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, !(res instanceof TLRPC.TL_updates_differenceSlice), false, null));
|
||||||
}
|
}
|
||||||
getMessagesStorage().putMessages(res.new_messages, true, false, false, getDownloadController().getAutodownloadMask(), false);
|
getMessagesStorage().putMessages(res.new_messages, true, false, false, getDownloadController().getAutodownloadMask(), false);
|
||||||
|
|
||||||
|
for (int a = 0; a < messages.size(); a++) {
|
||||||
|
long dialogId = messages.keyAt(a);
|
||||||
|
ArrayList<MessageObject> arr = messages.valueAt(a);
|
||||||
|
getMediaDataController().loadReplyMessagesForMessages(arr, dialogId, false, () -> {
|
||||||
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
updateInterfaceWithMessages(dialogId, arr, false);
|
||||||
|
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
getSecretChatHelper().processPendingEncMessages();
|
getSecretChatHelper().processPendingEncMessages();
|
||||||
|
@ -13086,6 +13089,11 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
updatesOnMainThread = new ArrayList<>();
|
updatesOnMainThread = new ArrayList<>();
|
||||||
}
|
}
|
||||||
updatesOnMainThread.add(baseUpdate);
|
updatesOnMainThread.add(baseUpdate);
|
||||||
|
} else if (baseUpdate instanceof TLRPC.TL_updateBotMenuButton) {
|
||||||
|
if (updatesOnMainThread == null) {
|
||||||
|
updatesOnMainThread = new ArrayList<>();
|
||||||
|
}
|
||||||
|
updatesOnMainThread.add(baseUpdate);
|
||||||
} else if (baseUpdate instanceof TLRPC.TL_updateReadChannelDiscussionInbox) {
|
} else if (baseUpdate instanceof TLRPC.TL_updateReadChannelDiscussionInbox) {
|
||||||
if (updatesOnMainThread == null) {
|
if (updatesOnMainThread == null) {
|
||||||
updatesOnMainThread = new ArrayList<>();
|
updatesOnMainThread = new ArrayList<>();
|
||||||
|
@ -13721,6 +13729,9 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.webViewResultSent, resultSent.query_id);
|
getNotificationCenter().postNotificationName(NotificationCenter.webViewResultSent, resultSent.query_id);
|
||||||
} else if (baseUpdate instanceof TLRPC.TL_updateAttachMenuBots) {
|
} else if (baseUpdate instanceof TLRPC.TL_updateAttachMenuBots) {
|
||||||
getMediaDataController().loadAttachMenuBots(false, true);
|
getMediaDataController().loadAttachMenuBots(false, true);
|
||||||
|
} else if (baseUpdate instanceof TLRPC.TL_updateBotMenuButton) {
|
||||||
|
TLRPC.TL_updateBotMenuButton updateBotMenuButton = (TLRPC.TL_updateBotMenuButton) baseUpdate;
|
||||||
|
getNotificationCenter().postNotificationName(NotificationCenter.updateBotMenuButton, updateBotMenuButton.bot_id, updateBotMenuButton.button);
|
||||||
} else if (baseUpdate instanceof TLRPC.TL_updateReadChannelDiscussionInbox) {
|
} else if (baseUpdate instanceof TLRPC.TL_updateReadChannelDiscussionInbox) {
|
||||||
TLRPC.TL_updateReadChannelDiscussionInbox update = (TLRPC.TL_updateReadChannelDiscussionInbox) baseUpdate;
|
TLRPC.TL_updateReadChannelDiscussionInbox update = (TLRPC.TL_updateReadChannelDiscussionInbox) baseUpdate;
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.threadMessagesRead, -update.channel_id, update.top_msg_id, update.read_max_id, 0);
|
getNotificationCenter().postNotificationName(NotificationCenter.threadMessagesRead, -update.channel_id, update.top_msg_id, update.read_max_id, 0);
|
||||||
|
|
|
@ -189,6 +189,8 @@ public class NotificationCenter {
|
||||||
public static final int filterSettingsUpdated = totalEvents++;
|
public static final int filterSettingsUpdated = totalEvents++;
|
||||||
public static final int suggestedFiltersLoaded = totalEvents++;
|
public static final int suggestedFiltersLoaded = totalEvents++;
|
||||||
|
|
||||||
|
public static final int updateBotMenuButton = totalEvents++;
|
||||||
|
|
||||||
//global
|
//global
|
||||||
public static final int pushMessagesUpdated = totalEvents++;
|
public static final int pushMessagesUpdated = totalEvents++;
|
||||||
public static final int stopEncodingService = totalEvents++;
|
public static final int stopEncodingService = totalEvents++;
|
||||||
|
|
|
@ -3438,7 +3438,7 @@ public class NotificationsController extends BaseController {
|
||||||
MessageObject messageObject = pushMessages.get(0);
|
MessageObject messageObject = pushMessages.get(0);
|
||||||
boolean[] text = new boolean[1];
|
boolean[] text = new boolean[1];
|
||||||
String message = lastMessage = getStringForMessage(messageObject, false, text, null);
|
String message = lastMessage = getStringForMessage(messageObject, false, text, null);
|
||||||
silent = messageObject.messageOwner.silent ? 1 : 0;
|
silent = isSilentMessage(messageObject) ? 1 : 0;
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3469,7 +3469,7 @@ public class NotificationsController extends BaseController {
|
||||||
}
|
}
|
||||||
if (silent == 2) {
|
if (silent == 2) {
|
||||||
lastMessage = message;
|
lastMessage = message;
|
||||||
silent = messageObject.messageOwner.silent ? 1 : 0;
|
silent = isSilentMessage(messageObject) ? 1 : 0;
|
||||||
}
|
}
|
||||||
if (pushDialogs.size() == 1) {
|
if (pushDialogs.size() == 1) {
|
||||||
if (replace) {
|
if (replace) {
|
||||||
|
@ -3859,6 +3859,10 @@ public class NotificationsController extends BaseController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSilentMessage(MessageObject messageObject) {
|
||||||
|
return messageObject.messageOwner.silent || messageObject.isReactionPush;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private void setNotificationChannel(Notification mainNotification, NotificationCompat.Builder builder, boolean useSummaryNotification) {
|
private void setNotificationChannel(Notification mainNotification, NotificationCompat.Builder builder, boolean useSummaryNotification) {
|
||||||
if (useSummaryNotification) {
|
if (useSummaryNotification) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ public class SharedPrefsHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void cleanupAccount(int account) {
|
public static void cleanupAccount(int account) {
|
||||||
|
if (webViewBotsPrefs != null) {
|
||||||
SharedPreferences.Editor editor = webViewBotsPrefs.edit();
|
SharedPreferences.Editor editor = webViewBotsPrefs.edit();
|
||||||
for (String key : webViewBotsPrefs.getAll().keySet()) {
|
for (String key : webViewBotsPrefs.getAll().keySet()) {
|
||||||
if (key.startsWith("confirm_shown_" + account + "_")) {
|
if (key.startsWith("confirm_shown_" + account + "_")) {
|
||||||
|
@ -29,6 +30,7 @@ public class SharedPrefsHelper {
|
||||||
}
|
}
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static SharedPreferences getWebViewBotsPrefs() {
|
public static SharedPreferences getWebViewBotsPrefs() {
|
||||||
return webViewBotsPrefs;
|
return webViewBotsPrefs;
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class RingtoneDataStore {
|
||||||
public final ArrayList<CachedTone> userRingtones = new ArrayList<>();
|
public final ArrayList<CachedTone> userRingtones = new ArrayList<>();
|
||||||
private boolean loaded;
|
private boolean loaded;
|
||||||
|
|
||||||
public final static HashSet<String> ringtoneSupportedMimeType = new HashSet<>(Arrays.asList("audio/mpeg", "audio/ogg", "audio/m4a"));
|
public final static HashSet<String> ringtoneSupportedMimeType = new HashSet<>(Arrays.asList("audio/mpeg3", "audio/mpeg", "audio/ogg", "audio/m4a"));
|
||||||
|
|
||||||
public RingtoneDataStore(int currentAccount) {
|
public RingtoneDataStore(int currentAccount) {
|
||||||
this.currentAccount = currentAccount;
|
this.currentAccount = currentAccount;
|
||||||
|
@ -49,7 +49,9 @@ public class RingtoneDataStore {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
loadUserRingtones();
|
loadUserRingtones();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadUserRingtones() {
|
public void loadUserRingtones() {
|
||||||
|
@ -251,7 +253,7 @@ public class RingtoneDataStore {
|
||||||
File file = FileLoader.getPathToAttach(document);
|
File file = FileLoader.getPathToAttach(document);
|
||||||
if (file == null || !file.exists()) {
|
if (file == null || !file.exists()) {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
FileLoader.getInstance(currentAccount).loadFile(document, null, 0, 0);
|
FileLoader.getInstance(currentAccount).loadFile(document, document, 0, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,10 +50,11 @@ public class MediaCodecVideoConvertor {
|
||||||
ArrayList<VideoEditedInfo.MediaEntity> mediaEntities,
|
ArrayList<VideoEditedInfo.MediaEntity> mediaEntities,
|
||||||
boolean isPhoto,
|
boolean isPhoto,
|
||||||
MediaController.CropState cropState,
|
MediaController.CropState cropState,
|
||||||
|
boolean isRound,
|
||||||
MediaController.VideoConvertorListener callback) {
|
MediaController.VideoConvertorListener callback) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
return convertVideoInternal(videoPath, cacheFile, rotationValue, isSecret, originalWidth, originalHeight,
|
return convertVideoInternal(videoPath, cacheFile, rotationValue, isSecret, originalWidth, originalHeight,
|
||||||
resultWidth, resultHeight, framerate, bitrate, originalBitrate, startTime, endTime, avatarStartTime, duration, needCompress, false, savedFilterState, paintPath, mediaEntities, isPhoto, cropState);
|
resultWidth, resultHeight, framerate, bitrate, originalBitrate, startTime, endTime, avatarStartTime, duration, needCompress, false, savedFilterState, paintPath, mediaEntities, isPhoto, cropState, isRound);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastFrameTimestamp() {
|
public long getLastFrameTimestamp() {
|
||||||
|
@ -73,7 +74,8 @@ public class MediaCodecVideoConvertor {
|
||||||
String paintPath,
|
String paintPath,
|
||||||
ArrayList<VideoEditedInfo.MediaEntity> mediaEntities,
|
ArrayList<VideoEditedInfo.MediaEntity> mediaEntities,
|
||||||
boolean isPhoto,
|
boolean isPhoto,
|
||||||
MediaController.CropState cropState) {
|
MediaController.CropState cropState,
|
||||||
|
boolean isRound) {
|
||||||
|
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
boolean error = false;
|
boolean error = false;
|
||||||
|
@ -407,7 +409,9 @@ public class MediaCodecVideoConvertor {
|
||||||
|
|
||||||
decoder = MediaCodec.createDecoderByType(videoFormat.getString(MediaFormat.KEY_MIME));
|
decoder = MediaCodec.createDecoderByType(videoFormat.getString(MediaFormat.KEY_MIME));
|
||||||
outputSurface = new OutputSurface(savedFilterState, null, paintPath, mediaEntities, cropState, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, false);
|
outputSurface = new OutputSurface(savedFilterState, null, paintPath, mediaEntities, cropState, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, false);
|
||||||
|
if (!isRound && Math.max(resultHeight, resultHeight) / (float) Math.max(originalHeight, originalWidth) < 0.9f) {
|
||||||
outputSurface.changeFragmentShader(createFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, true), createFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, false));
|
outputSurface.changeFragmentShader(createFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, true), createFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, false));
|
||||||
|
}
|
||||||
decoder.configure(videoFormat, outputSurface.getSurface(), null, 0);
|
decoder.configure(videoFormat, outputSurface.getSurface(), null, 0);
|
||||||
decoder.start();
|
decoder.start();
|
||||||
|
|
||||||
|
@ -800,7 +804,7 @@ public class MediaCodecVideoConvertor {
|
||||||
originalWidth, originalHeight,
|
originalWidth, originalHeight,
|
||||||
resultWidth, resultHeight, framerate, bitrate, originalBitrate, startTime, endTime, avatarStartTime, duration,
|
resultWidth, resultHeight, framerate, bitrate, originalBitrate, startTime, endTime, avatarStartTime, duration,
|
||||||
needCompress, true, savedFilterState, paintPath, mediaEntities,
|
needCompress, true, savedFilterState, paintPath, mediaEntities,
|
||||||
isPhoto, cropState);
|
isPhoto, cropState, isRound);
|
||||||
}
|
}
|
||||||
|
|
||||||
long timeLeft = System.currentTimeMillis() - time;
|
long timeLeft = System.currentTimeMillis() - time;
|
||||||
|
|
|
@ -14,10 +14,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.util.Log;
|
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.R;
|
|
||||||
import org.telegram.ui.Adapters.FiltersView;
|
import org.telegram.ui.Adapters.FiltersView;
|
||||||
import org.telegram.ui.Components.RLottieDrawable;
|
import org.telegram.ui.Components.RLottieDrawable;
|
||||||
|
|
||||||
|
@ -94,15 +91,7 @@ public class ActionBarMenu extends LinearLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionBarMenuItem addItem(int id, int icon, CharSequence text, int backgroundColor, Drawable drawable, int width, CharSequence title, Theme.ResourcesProvider resourcesProvider) {
|
public ActionBarMenuItem addItem(int id, int icon, CharSequence text, int backgroundColor, Drawable drawable, int width, CharSequence title, Theme.ResourcesProvider resourcesProvider) {
|
||||||
ActionBarMenuItem menuItem = new ActionBarMenuItem(getContext(), this, backgroundColor, isActionMode ? parentActionBar.itemsActionModeColor : parentActionBar.itemsColor, text != null, resourcesProvider) {
|
ActionBarMenuItem menuItem = new ActionBarMenuItem(getContext(), this, backgroundColor, isActionMode ? parentActionBar.itemsActionModeColor : parentActionBar.itemsColor, text != null, resourcesProvider);
|
||||||
@Override
|
|
||||||
public void setVisibility(int visibility) {
|
|
||||||
super.setVisibility(visibility);
|
|
||||||
if (icon == R.drawable.ic_ab_other && (id == 0 || id == 14)) {
|
|
||||||
Log.d("kek", id + " " + (View.VISIBLE == visibility));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
menuItem.setTag(id);
|
menuItem.setTag(id);
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
menuItem.textView.setText(text);
|
menuItem.textView.setText(text);
|
||||||
|
|
|
@ -1914,9 +1914,9 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public View addColoredGap() {
|
public ActionBarPopupWindow.GapView addColoredGap() {
|
||||||
createPopupLayout();
|
createPopupLayout();
|
||||||
View gap = new ActionBarPopupWindow.GapView(getContext(), Theme.key_graySection);
|
ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), Theme.key_graySection);
|
||||||
gap.setTag(R.id.fit_width_tag, 1);
|
gap.setTag(R.id.fit_width_tag, 1);
|
||||||
popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8));
|
popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8));
|
||||||
return gap;
|
return gap;
|
||||||
|
|
|
@ -551,6 +551,10 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
public void setTopView(View topView) {
|
public void setTopView(View topView) {
|
||||||
this.topView = topView;
|
this.topView = topView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSwipeBackForegroundColor(int color) {
|
||||||
|
getSwipeBack().setForegroundColor(color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionBarPopupWindow() {
|
public ActionBarPopupWindow() {
|
||||||
|
@ -866,6 +870,7 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
|
|
||||||
Paint paint = new Paint();
|
Paint paint = new Paint();
|
||||||
String colorKey;
|
String colorKey;
|
||||||
|
int color = 0;
|
||||||
public GapView(Context context, String colorKey) {
|
public GapView(Context context, String colorKey) {
|
||||||
super(context);
|
super(context);
|
||||||
this.colorKey = colorKey;
|
this.colorKey = colorKey;
|
||||||
|
@ -873,8 +878,16 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
|
if (color == 0) {
|
||||||
paint.setColor(Theme.getColor(colorKey));
|
paint.setColor(Theme.getColor(colorKey));
|
||||||
|
} else {
|
||||||
|
paint.setColor(color);
|
||||||
|
}
|
||||||
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);
|
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setColor(int color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,7 +17,6 @@ import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Insets;
|
import android.graphics.Insets;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
@ -920,9 +919,6 @@ public class BottomSheet extends Dialog {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
Window window = getWindow();
|
Window window = getWindow();
|
||||||
/*if (Build.VERSION.SDK_INT >= 30) {
|
|
||||||
window.setDecorFitsSystemWindows(true);
|
|
||||||
}*/
|
|
||||||
window.setWindowAnimations(R.style.DialogNoAnimation);
|
window.setWindowAnimations(R.style.DialogNoAnimation);
|
||||||
setContentView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
setContentView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||||
|
|
||||||
|
|
|
@ -312,7 +312,9 @@ public class CalendarActivity extends BaseFragment {
|
||||||
@Override
|
@Override
|
||||||
public void run(boolean forAll) {
|
public void run(boolean forAll) {
|
||||||
finishFragment();
|
finishFragment();
|
||||||
|
if (parentLayout == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (parentLayout.fragmentsStack.size() >= 2) {
|
if (parentLayout.fragmentsStack.size() >= 2) {
|
||||||
BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2);
|
BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2);
|
||||||
if (fragment instanceof ChatActivity) {
|
if (fragment instanceof ChatActivity) {
|
||||||
|
|
|
@ -31,7 +31,6 @@ import android.text.Layout;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.StaticLayout;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
@ -39,9 +38,7 @@ import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -207,6 +204,7 @@ public class CameraScanActivity extends BaseFragment {
|
||||||
actionBarLayout[0] = null;
|
actionBarLayout[0] = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
bottomSheet.setUseLightStatusBar(false);
|
||||||
AndroidUtilities.setLightNavigationBar(bottomSheet.getWindow(), false);
|
AndroidUtilities.setLightNavigationBar(bottomSheet.getWindow(), false);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
bottomSheet.getWindow().setNavigationBarColor(0xff000000);
|
bottomSheet.getWindow().setNavigationBarColor(0xff000000);
|
||||||
|
@ -436,6 +434,7 @@ public class CameraScanActivity extends BaseFragment {
|
||||||
} else {
|
} else {
|
||||||
actionBar.setBackgroundDrawable(null);
|
actionBar.setBackgroundDrawable(null);
|
||||||
actionBar.setAddToContainer(false);
|
actionBar.setAddToContainer(false);
|
||||||
|
actionBar.setTitleColor(0xffffffff);
|
||||||
actionBar.setItemsColor(0xffffffff, false);
|
actionBar.setItemsColor(0xffffffff, false);
|
||||||
actionBar.setItemsBackgroundColor(0x22ffffff, false);
|
actionBar.setItemsBackgroundColor(0x22ffffff, false);
|
||||||
viewGroup.setBackgroundColor(Theme.getColor(Theme.key_wallet_blackBackground));
|
viewGroup.setBackgroundColor(Theme.getColor(Theme.key_wallet_blackBackground));
|
||||||
|
|
|
@ -1056,8 +1056,7 @@ public class DialogCell extends BaseCell {
|
||||||
checkMessage = false;
|
checkMessage = false;
|
||||||
messageString = formatArchivedDialogNames();
|
messageString = formatArchivedDialogNames();
|
||||||
} else if (message.messageOwner instanceof TLRPC.TL_messageService) {
|
} else if (message.messageOwner instanceof TLRPC.TL_messageService) {
|
||||||
if (ChatObject.isChannelAndNotMegaGroup(chat) && (message.messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear ||
|
if (ChatObject.isChannelAndNotMegaGroup(chat) && (message.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom)) {
|
||||||
message.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom)) {
|
|
||||||
messageString = "";
|
messageString = "";
|
||||||
showChecks = false;
|
showChecks = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2763,11 +2763,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void muteFor(int timeInSeconds) {
|
public void muteFor(int timeInSeconds) {
|
||||||
|
if (timeInSeconds == 0) {
|
||||||
|
if (getMessagesController().isDialogMuted(dialog_id)) {
|
||||||
|
ChatActivity.this.toggleMute(true);
|
||||||
|
}
|
||||||
|
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
||||||
|
BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_UNMUTE, timeInSeconds, getResourceProvider()).show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
getNotificationsController().muteUntil(dialog_id, timeInSeconds);
|
getNotificationsController().muteUntil(dialog_id, timeInSeconds);
|
||||||
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
||||||
BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show();
|
BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showCustomize() {
|
public void showCustomize() {
|
||||||
|
@ -4081,7 +4090,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(10), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground)));
|
greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(10), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground)));
|
||||||
emptyViewContainer.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 68, 0, 68, 0));
|
emptyViewContainer.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 68, 0, 68, 0));
|
||||||
} else if (currentEncryptedChat == null) {
|
} else if (currentEncryptedChat == null) {
|
||||||
if (!isThreadChat() && chatMode == 0 && (currentUser != null && currentUser.self || currentChat != null && currentChat.creator)) {
|
if (!isThreadChat() && chatMode == 0 && ((currentUser != null && currentUser.self) || (currentChat != null && currentChat.creator && !ChatObject.isChannelAndNotMegaGroup(currentChat)))) {
|
||||||
bigEmptyView = new ChatBigEmptyView(context, contentView, currentChat != null ? ChatBigEmptyView.EMPTY_VIEW_TYPE_GROUP : ChatBigEmptyView.EMPTY_VIEW_TYPE_SAVED, themeDelegate);
|
bigEmptyView = new ChatBigEmptyView(context, contentView, currentChat != null ? ChatBigEmptyView.EMPTY_VIEW_TYPE_GROUP : ChatBigEmptyView.EMPTY_VIEW_TYPE_SAVED, themeDelegate);
|
||||||
emptyViewContainer.addView(bigEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
|
emptyViewContainer.addView(bigEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
|
||||||
if (currentChat != null) {
|
if (currentChat != null) {
|
||||||
|
@ -14517,7 +14526,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
endReached[0] = cacheEndReached[0] = true;
|
endReached[0] = cacheEndReached[0] = true;
|
||||||
forwardEndReached[0] = forwardEndReached[0] = true;
|
forwardEndReached[0] = forwardEndReached[0] = true;
|
||||||
}
|
}
|
||||||
if (ChatObject.isChannel(currentChat) && !getMessagesController().dialogs_dict.containsKey(dialog_id) && load_type == 2 && loadIndex == 0) {
|
if (!isThreadChat() && ChatObject.isChannel(currentChat) && !getMessagesController().dialogs_dict.containsKey(dialog_id) && load_type == 2 && loadIndex == 0) {
|
||||||
forwardEndReached[0] = false;
|
forwardEndReached[0] = false;
|
||||||
hideForwardEndReached = true;
|
hideForwardEndReached = true;
|
||||||
}
|
}
|
||||||
|
@ -19652,7 +19661,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
}
|
}
|
||||||
if (pinnedText != null) {
|
if (pinnedText != null) {
|
||||||
if (pinnedText instanceof Spannable) {
|
if (pinnedText instanceof Spannable) {
|
||||||
MediaDataController.addTextStyleRuns(pinnedMessageObject, (Spannable) pinnedText);
|
MediaDataController.addTextStyleRuns(pinnedMessageObject, (Spannable) pinnedText, TextStyleSpan.FLAG_STYLE_SPOILER | TextStyleSpan.FLAG_STYLE_STRIKE);
|
||||||
}
|
}
|
||||||
messageTextView.setText(pinnedText);
|
messageTextView.setText(pinnedText);
|
||||||
}
|
}
|
||||||
|
@ -21668,7 +21677,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
} else {
|
} else {
|
||||||
isReactionsAvailable = !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty() || (chatInfo == null && !ChatObject.isChannel(currentChat)) || currentUser != null) && !availableReacts.isEmpty();
|
isReactionsAvailable = !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty() || (chatInfo == null && !ChatObject.isChannel(currentChat)) || currentUser != null) && !availableReacts.isEmpty();
|
||||||
}
|
}
|
||||||
boolean showMessageSeen = !isReactionsViewAvailable && !isInScheduleMode() && currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().chatReadMarkExpirePeriod) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count < getMessagesController().chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell);
|
boolean showMessageSeen = !isReactionsViewAvailable && !isInScheduleMode() && currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().chatReadMarkExpirePeriod) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count <= getMessagesController().chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell);
|
||||||
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (isReactionsViewAvailable || showMessageSeen) {
|
if (isReactionsViewAvailable || showMessageSeen) {
|
||||||
|
@ -21988,7 +21997,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
addGap = true;
|
addGap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.probablyRingtone()) {
|
if (message.probablyRingtone() && currentEncryptedChat == null) {
|
||||||
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate);
|
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate);
|
||||||
cell.setMinimumWidth(AndroidUtilities.dp(200));
|
cell.setMinimumWidth(AndroidUtilities.dp(200));
|
||||||
cell.setTextAndIcon(LocaleController.getString("SaveForNotifications", R.string.SaveForNotifications), R.drawable.msg_tone_add);
|
cell.setTextAndIcon(LocaleController.getString("SaveForNotifications", R.string.SaveForNotifications), R.drawable.msg_tone_add);
|
||||||
|
@ -22000,7 +22009,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (clicked || dialog_id == 0 || getUserConfig().clientUserId == dialog_id) {
|
if (clicked) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clicked = true;
|
clicked = true;
|
||||||
|
@ -23474,6 +23483,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
} else if (chatActivityEnterView != null && chatActivityEnterView.isPopupShowing()) {
|
} else if (chatActivityEnterView != null && chatActivityEnterView.isPopupShowing()) {
|
||||||
chatActivityEnterView.hidePopup(true);
|
chatActivityEnterView.hidePopup(true);
|
||||||
return false;
|
return false;
|
||||||
|
} else if (chatActivityEnterView != null && chatActivityEnterView.hasBotWebView() && chatActivityEnterView.botCommandsMenuIsShowing() && chatActivityEnterView.onBotWebViewBackPressed()) {
|
||||||
|
return false;
|
||||||
} else if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuIsShowing()) {
|
} else if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuIsShowing()) {
|
||||||
chatActivityEnterView.hideBotCommands();
|
chatActivityEnterView.hideBotCommands();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package org.telegram.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.telegram.messenger.LocaleController;
|
||||||
|
import org.telegram.messenger.R;
|
||||||
|
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||||
|
import org.telegram.ui.ActionBar.ActionBarMenuSubItem;
|
||||||
|
import org.telegram.ui.ActionBar.ActionBarPopupWindow;
|
||||||
|
import org.telegram.ui.Components.PopupSwipeBackLayout;
|
||||||
|
|
||||||
|
public class ChooseSpeedLayout {
|
||||||
|
|
||||||
|
ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout;
|
||||||
|
|
||||||
|
ActionBarMenuSubItem[] speedItems = new ActionBarMenuSubItem[5];
|
||||||
|
public ChooseSpeedLayout(Context context, PopupSwipeBackLayout swipeBackLayout, Callback callback) {
|
||||||
|
speedSwipeBackLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, 0, null);
|
||||||
|
speedSwipeBackLayout.setFitItems(true);
|
||||||
|
|
||||||
|
ActionBarMenuSubItem backItem = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_arrow_back, LocaleController.getString("Back", R.string.Back), false, null);
|
||||||
|
backItem.setOnClickListener(view -> {
|
||||||
|
swipeBackLayout.closeForeground();
|
||||||
|
});
|
||||||
|
backItem.setColors(0xfffafafa, 0xfffafafa);
|
||||||
|
|
||||||
|
ActionBarMenuSubItem item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_0_2, LocaleController.getString("SpeedVerySlow", R.string.SpeedVerySlow), false, null);
|
||||||
|
item.setColors(0xfffafafa, 0xfffafafa);
|
||||||
|
item.setOnClickListener((view) -> {
|
||||||
|
callback.onSpeedSelected(0.25f);
|
||||||
|
});
|
||||||
|
speedItems[0] = item;
|
||||||
|
|
||||||
|
item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_0_5, LocaleController.getString("SpeedSlow", R.string.SpeedSlow), false, null);
|
||||||
|
item.setColors(0xfffafafa, 0xfffafafa);
|
||||||
|
item.setOnClickListener((view) -> {
|
||||||
|
callback.onSpeedSelected(0.5f);
|
||||||
|
});
|
||||||
|
speedItems[1] = item;
|
||||||
|
|
||||||
|
item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_1, LocaleController.getString("SpeedNormal", R.string.SpeedNormal), false, null);
|
||||||
|
item.setColors(0xfffafafa, 0xfffafafa);
|
||||||
|
item.setOnClickListener((view) -> {
|
||||||
|
callback.onSpeedSelected(1f);
|
||||||
|
});
|
||||||
|
speedItems[2] = item;
|
||||||
|
|
||||||
|
item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_1_5, LocaleController.getString("SpeedFast", R.string.SpeedFast), false, null);
|
||||||
|
item.setColors(0xfffafafa, 0xfffafafa);
|
||||||
|
item.setOnClickListener((view) -> {
|
||||||
|
callback.onSpeedSelected(1.5f);
|
||||||
|
});
|
||||||
|
speedItems[3] = item;
|
||||||
|
|
||||||
|
item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_2, LocaleController.getString("SpeedVeryFast", R.string.SpeedVeryFast), false, null);
|
||||||
|
item.setColors(0xfffafafa, 0xfffafafa);
|
||||||
|
item.setOnClickListener((view) -> {
|
||||||
|
callback.onSpeedSelected(2f);
|
||||||
|
});
|
||||||
|
speedItems[4] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(float currentVideoSpeed) {
|
||||||
|
for (int a = 0; a < speedItems.length; a++) {
|
||||||
|
if (a == 0 && Math.abs(currentVideoSpeed - 0.25f) < 0.001f ||
|
||||||
|
a == 1 && Math.abs(currentVideoSpeed - 0.5f) < 0.001f ||
|
||||||
|
a == 2 && Math.abs(currentVideoSpeed - 1.0f) < 0.001f ||
|
||||||
|
a == 3 && Math.abs(currentVideoSpeed - 1.5f) < 0.001f ||
|
||||||
|
a == 4 && Math.abs(currentVideoSpeed - 2.0f) < 0.001f) {
|
||||||
|
speedItems[a].setColors(0xff6BB6F9, 0xff6BB6F9);
|
||||||
|
} else {
|
||||||
|
speedItems[a].setColors(0xfffafafa, 0xfffafafa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Callback {
|
||||||
|
void onSpeedSelected(float speed);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1441,9 +1441,13 @@ public class AlertsCreator {
|
||||||
if (second) {
|
if (second) {
|
||||||
if (UserObject.isUserSelf(user)) {
|
if (UserObject.isUserSelf(user)) {
|
||||||
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesSavedAlert", R.string.DeleteAllMessagesSavedAlert)));
|
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesSavedAlert", R.string.DeleteAllMessagesSavedAlert)));
|
||||||
|
} else {
|
||||||
|
if (chat != null && ChatObject.isChannelAndNotMegaGroup(chat)) {
|
||||||
|
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesChannelAlert", R.string.DeleteAllMessagesChannelAlert)));
|
||||||
} else {
|
} else {
|
||||||
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesAlert", R.string.DeleteAllMessagesAlert)));
|
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesAlert", R.string.DeleteAllMessagesAlert)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (clear) {
|
if (clear) {
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
|
@ -1512,7 +1516,7 @@ public class AlertsCreator {
|
||||||
if (clearingCache) {
|
if (clearingCache) {
|
||||||
actionText = LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache);
|
actionText = LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache);
|
||||||
} else {
|
} else {
|
||||||
actionText = LocaleController.getString("ClearHistory", R.string.ClearHistory);
|
actionText = LocaleController.getString("ClearForMe", R.string.ClearForMe);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (admin) {
|
if (admin) {
|
||||||
|
@ -1616,8 +1620,12 @@ public class AlertsCreator {
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithUser", R.string.AreYouSureClearHistoryWithUser, UserObject.getUserName(user))));
|
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithUser", R.string.AreYouSureClearHistoryWithUser, UserObject.getUserName(user))));
|
||||||
} else {
|
} else {
|
||||||
if (chat != null && canDeleteHistory) {
|
if (canDeleteHistory) {
|
||||||
|
if (ChatObject.isChannelAndNotMegaGroup(chat)) {
|
||||||
|
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithChannel", R.string.AreYouSureClearHistoryWithChannel, chat.title)));
|
||||||
|
} else {
|
||||||
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithChat", R.string.AreYouSureClearHistoryWithChat, chat.title)));
|
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithChat", R.string.AreYouSureClearHistoryWithChat, chat.title)));
|
||||||
|
}
|
||||||
} else if (chat.megagroup) {
|
} else if (chat.megagroup) {
|
||||||
messageTextView.setText(LocaleController.getString("AreYouSureClearHistoryGroup", R.string.AreYouSureClearHistoryGroup));
|
messageTextView.setText(LocaleController.getString("AreYouSureClearHistoryGroup", R.string.AreYouSureClearHistoryGroup));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1633,7 +1641,7 @@ public class AlertsCreator {
|
||||||
if (chat != null && canDeleteHistory && !TextUtils.isEmpty(chat.username)) {
|
if (chat != null && canDeleteHistory && !TextUtils.isEmpty(chat.username)) {
|
||||||
deleteForAll[0] = true;
|
deleteForAll[0] = true;
|
||||||
}
|
}
|
||||||
if ((user != null && user.id != selfUserId) || (chat != null && canDeleteHistory && TextUtils.isEmpty(chat.username))) {
|
if ((user != null && user.id != selfUserId) || (chat != null && canDeleteHistory && TextUtils.isEmpty(chat.username) && !ChatObject.isChannelAndNotMegaGroup(chat))) {
|
||||||
cell[0] = new CheckBoxCell(context, 1, resourcesProvider);
|
cell[0] = new CheckBoxCell(context, 1, resourcesProvider);
|
||||||
cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false));
|
cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false));
|
||||||
if (chat != null) {
|
if (chat != null) {
|
||||||
|
@ -1653,7 +1661,11 @@ public class AlertsCreator {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> {
|
String deleteText = LocaleController.getString("Delete", R.string.Delete);
|
||||||
|
if (chat != null && canDeleteHistory && !TextUtils.isEmpty(chat.username) && !ChatObject.isChannelAndNotMegaGroup(chat)) {
|
||||||
|
deleteText = LocaleController.getString("ClearForAll", R.string.ClearForAll);
|
||||||
|
}
|
||||||
|
builder.setPositiveButton(deleteText, (dialogInterface, i) -> {
|
||||||
onProcessRunnable.run(deleteForAll[0]);
|
onProcessRunnable.run(deleteForAll[0]);
|
||||||
});
|
});
|
||||||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||||
|
@ -2803,7 +2815,6 @@ public class AlertsCreator {
|
||||||
numberPicker.setMaxValue(values.length - 1);
|
numberPicker.setMaxValue(values.length - 1);
|
||||||
numberPicker.setTextColor(datePickerColors.textColor);
|
numberPicker.setTextColor(datePickerColors.textColor);
|
||||||
numberPicker.setValue(0);
|
numberPicker.setValue(0);
|
||||||
numberPicker.setWrapSelectorWheel(false);
|
|
||||||
numberPicker.setFormatter(index -> {
|
numberPicker.setFormatter(index -> {
|
||||||
if (values[index] == 0) {
|
if (values[index] == 0) {
|
||||||
return LocaleController.getString("AutoDeleteNever", R.string.AutoDeleteNever);
|
return LocaleController.getString("AutoDeleteNever", R.string.AutoDeleteNever);
|
||||||
|
@ -3048,18 +3059,59 @@ public class AlertsCreator {
|
||||||
BottomSheet.Builder builder = new BottomSheet.Builder(context, false);
|
BottomSheet.Builder builder = new BottomSheet.Builder(context, false);
|
||||||
builder.setApplyBottomPadding(false);
|
builder.setApplyBottomPadding(false);
|
||||||
|
|
||||||
final NumberPicker dayPicker = new NumberPicker(context);
|
int[] values = new int[]{
|
||||||
dayPicker.setTextColor(datePickerColors.textColor);
|
0,
|
||||||
dayPicker.setTextOffset(AndroidUtilities.dp(10));
|
60 * 24,
|
||||||
dayPicker.setItemCount(5);
|
2 * 60 * 24,
|
||||||
final NumberPicker hourPicker = new NumberPicker(context) {
|
3 * 60 * 24,
|
||||||
|
4 * 60 * 24,
|
||||||
|
5 * 60 * 24,
|
||||||
|
6 * 60 * 24,
|
||||||
|
7 * 60 * 24,
|
||||||
|
2 * 7 * 60 * 24,
|
||||||
|
3 * 7 * 60 * 24,
|
||||||
|
31 * 60 * 24,
|
||||||
|
2 * 31 * 60 * 24,
|
||||||
|
3 * 31 * 60 * 24,
|
||||||
|
4 * 31 * 60 * 24,
|
||||||
|
5 * 31 * 60 * 24,
|
||||||
|
6 * 31 * 60 * 24,
|
||||||
|
365 * 60 * 24
|
||||||
|
};
|
||||||
|
|
||||||
|
final NumberPicker numberPicker = new NumberPicker(context) {
|
||||||
@Override
|
@Override
|
||||||
protected CharSequence getContentDescription(int value) {
|
protected CharSequence getContentDescription(int index) {
|
||||||
return LocaleController.formatPluralString("Hours", value);
|
if (values[index] == 0) {
|
||||||
|
return LocaleController.getString("MuteNever", R.string.MuteNever);
|
||||||
|
} else if (values[index] < 7 * 60 * 24) {
|
||||||
|
return LocaleController.formatPluralString("Days", values[index] / (60 * 24));
|
||||||
|
} else if (values[index] < 31 * 60 * 24) {
|
||||||
|
return LocaleController.formatPluralString("Weeks", values[index] / (60 * 24));
|
||||||
|
} else if (values[index] < 365 * 60 * 24) {
|
||||||
|
return LocaleController.formatPluralString("Months", values[index] / (7 * 60 * 24));
|
||||||
|
} else {
|
||||||
|
return LocaleController.formatPluralString("Years", values[index] * 5 / 31 * 60 * 24);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
hourPicker.setItemCount(5);
|
numberPicker.setMinValue(0);
|
||||||
hourPicker.setTextColor(datePickerColors.textColor);
|
numberPicker.setMaxValue(values.length - 1);
|
||||||
|
numberPicker.setTextColor(datePickerColors.textColor);
|
||||||
|
numberPicker.setValue(0);
|
||||||
|
numberPicker.setFormatter(index -> {
|
||||||
|
if (values[index] == 0) {
|
||||||
|
return LocaleController.getString("MuteNever", R.string.MuteNever);
|
||||||
|
} else if (values[index] < 7 * 60 * 24) {
|
||||||
|
return LocaleController.formatPluralString("Days", values[index] / (60 * 24));
|
||||||
|
} else if (values[index] < 31 * 60 * 24) {
|
||||||
|
return LocaleController.formatPluralString("Weeks", values[index] / (7 * 60 * 24));
|
||||||
|
} else if (values[index] < 365 * 60 * 24) {
|
||||||
|
return LocaleController.formatPluralString("Months", values[index] / (31 * 60 * 24));
|
||||||
|
} else {
|
||||||
|
return LocaleController.formatPluralString("Years", values[index] / (365 * 60 * 24));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
LinearLayout container = new LinearLayout(context) {
|
LinearLayout container = new LinearLayout(context) {
|
||||||
|
|
||||||
|
@ -3074,10 +3126,8 @@ public class AlertsCreator {
|
||||||
} else {
|
} else {
|
||||||
count = 5;
|
count = 5;
|
||||||
}
|
}
|
||||||
dayPicker.setItemCount(count);
|
numberPicker.setItemCount(count);
|
||||||
hourPicker.setItemCount(count);
|
numberPicker.getLayoutParams().height = AndroidUtilities.dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count;
|
||||||
dayPicker.getLayoutParams().height = AndroidUtilities.dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count;
|
|
||||||
hourPicker.getLayoutParams().height = AndroidUtilities.dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count;
|
|
||||||
ignoreLayout = false;
|
ignoreLayout = false;
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
}
|
}
|
||||||
|
@ -3115,26 +3165,15 @@ public class AlertsCreator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
linearLayout.addView(dayPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f));
|
linearLayout.addView(numberPicker, LayoutHelper.createLinear(0, 54 * 5, 1f));
|
||||||
dayPicker.setMinValue(0);
|
|
||||||
dayPicker.setMaxValue(365);
|
|
||||||
dayPicker.setWrapSelectorWheel(false);
|
|
||||||
dayPicker.setFormatter(value -> LocaleController.formatPluralString("Days", value));
|
|
||||||
final NumberPicker.OnValueChangeListener onValueChangeListener = (picker, oldVal, newVal) -> {
|
final NumberPicker.OnValueChangeListener onValueChangeListener = (picker, oldVal, newVal) -> {
|
||||||
try {
|
try {
|
||||||
container.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
|
container.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
|
|
||||||
}
|
}
|
||||||
checkMuteForButton(dayPicker, hourPicker, buttonTextView, true);
|
|
||||||
};
|
};
|
||||||
dayPicker.setOnValueChangedListener(onValueChangeListener);
|
numberPicker.setOnValueChangedListener(onValueChangeListener);
|
||||||
|
|
||||||
hourPicker.setMinValue(0);
|
|
||||||
hourPicker.setMaxValue(23);
|
|
||||||
linearLayout.addView(hourPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f));
|
|
||||||
hourPicker.setFormatter(value -> LocaleController.formatPluralString("Hours", value));
|
|
||||||
hourPicker.setOnValueChangedListener(onValueChangeListener);
|
|
||||||
|
|
||||||
buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0);
|
buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0);
|
||||||
buttonTextView.setGravity(Gravity.CENTER);
|
buttonTextView.setGravity(Gravity.CENTER);
|
||||||
|
@ -3142,10 +3181,10 @@ public class AlertsCreator {
|
||||||
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||||
buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), datePickerColors.buttonBackgroundColor, datePickerColors.buttonBackgroundPressedColor));
|
buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), datePickerColors.buttonBackgroundColor, datePickerColors.buttonBackgroundPressedColor));
|
||||||
buttonTextView.setText(LocaleController.getString("SetTimeLimit", R.string.SetTimeLimit));
|
buttonTextView.setText(LocaleController.getString("AutoDeleteConfirm", R.string.AutoDeleteConfirm));
|
||||||
container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16));
|
container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16));
|
||||||
buttonTextView.setOnClickListener(v -> {
|
buttonTextView.setOnClickListener(v -> {
|
||||||
int time = hourPicker.getValue() * 60 + dayPicker.getValue() * 60 * 24;
|
int time = values[numberPicker.getValue()] * 60;
|
||||||
datePickerDelegate.didSelectDate(true, time);
|
datePickerDelegate.didSelectDate(true, time);
|
||||||
builder.getDismissRunnable().run();
|
builder.getDismissRunnable().run();
|
||||||
});
|
});
|
||||||
|
@ -3153,7 +3192,7 @@ public class AlertsCreator {
|
||||||
builder.setCustomView(container);
|
builder.setCustomView(container);
|
||||||
BottomSheet bottomSheet = builder.show();
|
BottomSheet bottomSheet = builder.show();
|
||||||
bottomSheet.setBackgroundColor(datePickerColors.backgroundColor);
|
bottomSheet.setBackgroundColor(datePickerColors.backgroundColor);
|
||||||
checkMuteForButton(dayPicker, hourPicker, buttonTextView, false);
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3191,46 +3230,6 @@ public class AlertsCreator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkAutoDeleteButton(NumberPicker dayPicker, NumberPicker hourPicker, NumberPicker minutePicker, TextView buttonTextView, boolean animated) {
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
if (dayPicker.getValue() != 0) {
|
|
||||||
stringBuilder.append(dayPicker.getValue()).append(LocaleController.getString("SecretChatTimerDays", R.string.SecretChatTimerDays));
|
|
||||||
}
|
|
||||||
if (hourPicker.getValue() != 0) {
|
|
||||||
if (stringBuilder.length() > 0) {
|
|
||||||
stringBuilder.append(" ");
|
|
||||||
}
|
|
||||||
stringBuilder.append(hourPicker.getValue()).append(LocaleController.getString("SecretChatTimerHours", R.string.SecretChatTimerHours));
|
|
||||||
}
|
|
||||||
if (minutePicker.getValue() != 0) {
|
|
||||||
if (stringBuilder.length() > 0) {
|
|
||||||
stringBuilder.append(" ");
|
|
||||||
}
|
|
||||||
stringBuilder.append(minutePicker.getValue() * 5).append(LocaleController.getString("SecretChatTimerMinutes", R.string.SecretChatTimerMinutes));
|
|
||||||
}
|
|
||||||
if (stringBuilder.length() == 0) {
|
|
||||||
buttonTextView.setText(LocaleController.formatString("ChooseTimeForAutoDelete", R.string.ChooseTimeForAutoDelete));
|
|
||||||
if (buttonTextView.isEnabled()) {
|
|
||||||
buttonTextView.setEnabled(false);
|
|
||||||
if (animated) {
|
|
||||||
buttonTextView.animate().alpha(0.5f);
|
|
||||||
} else {
|
|
||||||
buttonTextView.setAlpha(0.5f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buttonTextView.setText(LocaleController.formatString("AutoDeleteAfter", R.string.AutoDeleteAfter, stringBuilder.toString()));
|
|
||||||
if (!buttonTextView.isEnabled()) {
|
|
||||||
buttonTextView.setEnabled(true);
|
|
||||||
if (animated) {
|
|
||||||
buttonTextView.animate().alpha(1f);
|
|
||||||
} else {
|
|
||||||
buttonTextView.setAlpha(1f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkCalendarDate(long minDate, NumberPicker dayPicker, NumberPicker monthPicker, NumberPicker yearPicker) {
|
private static void checkCalendarDate(long minDate, NumberPicker dayPicker, NumberPicker monthPicker, NumberPicker yearPicker) {
|
||||||
int day = dayPicker.getValue();
|
int day = dayPicker.getValue();
|
||||||
int month = monthPicker.getValue();
|
int month = monthPicker.getValue();
|
||||||
|
|
|
@ -206,6 +206,9 @@ public class BotCommandsMenuView extends View {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMenuText(String menuText) {
|
public void setMenuText(String menuText) {
|
||||||
|
if (menuText == null) {
|
||||||
|
menuText = LocaleController.getString(R.string.BotsMenuTitle);
|
||||||
|
}
|
||||||
this.menuText = menuText;
|
this.menuText = menuText;
|
||||||
menuTextLayout = null;
|
menuTextLayout = null;
|
||||||
requestLayout();
|
requestLayout();
|
||||||
|
|
|
@ -20,8 +20,10 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.webkit.GeolocationPermissions;
|
import android.webkit.GeolocationPermissions;
|
||||||
import android.webkit.JavascriptInterface;
|
import android.webkit.JavascriptInterface;
|
||||||
import android.webkit.PermissionRequest;
|
import android.webkit.PermissionRequest;
|
||||||
|
@ -31,14 +33,18 @@ import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.core.graphics.ColorUtils;
|
||||||
import androidx.core.util.Consumer;
|
import androidx.core.util.Consumer;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
|
import org.telegram.messenger.ApplicationLoader;
|
||||||
import org.telegram.messenger.FileLog;
|
import org.telegram.messenger.FileLog;
|
||||||
import org.telegram.messenger.ImageLocation;
|
import org.telegram.messenger.ImageLocation;
|
||||||
import org.telegram.messenger.ImageReceiver;
|
import org.telegram.messenger.ImageReceiver;
|
||||||
|
@ -57,6 +63,7 @@ import org.telegram.ui.ActionBar.AlertDialog;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.voip.CellFlickerDrawable;
|
import org.telegram.ui.Components.voip.CellFlickerDrawable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -64,6 +71,7 @@ import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BotWebViewContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
|
public class BotWebViewContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
|
||||||
|
private final static boolean WEB_VIEW_CAN_GO_BACK = false;
|
||||||
private final static String DURGER_KING_USERNAME = "DurgerKingBot";
|
private final static String DURGER_KING_USERNAME = "DurgerKingBot";
|
||||||
private final static int REQUEST_CODE_WEB_VIEW_FILE = 3000, REQUEST_CODE_WEB_PERMISSION = 4000;
|
private final static int REQUEST_CODE_WEB_VIEW_FILE = 3000, REQUEST_CODE_WEB_PERMISSION = 4000;
|
||||||
|
|
||||||
|
@ -75,6 +83,9 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
private WebViewScrollListener webViewScrollListener;
|
private WebViewScrollListener webViewScrollListener;
|
||||||
private Theme.ResourcesProvider resourcesProvider;
|
private Theme.ResourcesProvider resourcesProvider;
|
||||||
|
|
||||||
|
private TextView webViewNotAvailableText;
|
||||||
|
private boolean webViewNotAvailable;
|
||||||
|
|
||||||
private CellFlickerDrawable flickerDrawable = new CellFlickerDrawable();
|
private CellFlickerDrawable flickerDrawable = new CellFlickerDrawable();
|
||||||
private BackupImageView flickerView;
|
private BackupImageView flickerView;
|
||||||
private boolean isFlickeringCenter;
|
private boolean isFlickeringCenter;
|
||||||
|
@ -83,13 +94,12 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
|
|
||||||
private ValueCallback<Uri[]> mFilePathCallback;
|
private ValueCallback<Uri[]> mFilePathCallback;
|
||||||
|
|
||||||
private int lastButtonColor = Theme.getColor(Theme.key_featuredStickers_addButton);
|
private int lastButtonColor = getColor(Theme.key_featuredStickers_addButton);
|
||||||
private int lastButtonTextColor = Theme.getColor(Theme.key_featuredStickers_buttonText);
|
private int lastButtonTextColor = getColor(Theme.key_featuredStickers_buttonText);
|
||||||
private String lastButtonText = "";
|
private String lastButtonText = "";
|
||||||
private String buttonData;
|
private String buttonData;
|
||||||
|
|
||||||
private boolean isPageLoaded;
|
private boolean isPageLoaded;
|
||||||
private int viewPortOffset;
|
|
||||||
private boolean lastExpanded;
|
private boolean lastExpanded;
|
||||||
|
|
||||||
private boolean hasUserPermissions;
|
private boolean hasUserPermissions;
|
||||||
|
@ -98,7 +108,6 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
|
|
||||||
private Activity parentActivity;
|
private Activity parentActivity;
|
||||||
|
|
||||||
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
|
|
||||||
public BotWebViewContainer(@NonNull Context context, Theme.ResourcesProvider resourcesProvider, int backgroundColor) {
|
public BotWebViewContainer(@NonNull Context context, Theme.ResourcesProvider resourcesProvider, int backgroundColor) {
|
||||||
super(context);
|
super(context);
|
||||||
this.resourcesProvider = resourcesProvider;
|
this.resourcesProvider = resourcesProvider;
|
||||||
|
@ -139,11 +148,47 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
flickerView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundGray), PorterDuff.Mode.SRC_IN));
|
flickerView.setColorFilter(new PorterDuffColorFilter(getColor(Theme.key_dialogSearchHint), PorterDuff.Mode.SRC_IN));
|
||||||
flickerView.getImageReceiver().setAspectFit(true);
|
flickerView.getImageReceiver().setAspectFit(true);
|
||||||
addView(flickerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP));
|
addView(flickerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP));
|
||||||
|
|
||||||
webView = new WebView(context) {
|
webViewNotAvailableText = new TextView(context);
|
||||||
|
webViewNotAvailableText.setText(LocaleController.getString(R.string.BotWebViewNotAvailablePlaceholder));
|
||||||
|
webViewNotAvailableText.setTextColor(getColor(Theme.key_windowBackgroundWhiteGrayText));
|
||||||
|
webViewNotAvailableText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
||||||
|
webViewNotAvailableText.setGravity(Gravity.CENTER);
|
||||||
|
webViewNotAvailableText.setVisibility(GONE);
|
||||||
|
int padding = AndroidUtilities.dp(16);
|
||||||
|
webViewNotAvailableText.setPadding(padding, padding, padding, padding);
|
||||||
|
addView(webViewNotAvailableText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
|
||||||
|
|
||||||
|
setFocusable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCreateWebView() {
|
||||||
|
if (webView == null && !webViewNotAvailable) {
|
||||||
|
try {
|
||||||
|
setupWebView();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
FileLog.e(t);
|
||||||
|
|
||||||
|
flickerView.setVisibility(GONE);
|
||||||
|
webViewNotAvailable = true;
|
||||||
|
webViewNotAvailableText.setVisibility(VISIBLE);
|
||||||
|
if (webView != null) {
|
||||||
|
removeView(webView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
|
||||||
|
private void setupWebView() {
|
||||||
|
if (webView != null) {
|
||||||
|
webView.destroy();
|
||||||
|
removeView(webView);
|
||||||
|
}
|
||||||
|
webView = new WebView(getContext()) {
|
||||||
private int prevScrollX, prevScrollY;
|
private int prevScrollX, prevScrollY;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -172,7 +217,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCheckIsTextEditor() {
|
public boolean onCheckIsTextEditor() {
|
||||||
return true;
|
return BotWebViewContainer.this.isFocusable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -180,12 +225,20 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY));
|
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
webView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
webView.setBackgroundColor(getColor(Theme.key_windowBackgroundWhite));
|
||||||
WebSettings settings = webView.getSettings();
|
WebSettings settings = webView.getSettings();
|
||||||
settings.setJavaScriptEnabled(true);
|
settings.setJavaScriptEnabled(true);
|
||||||
settings.setGeolocationEnabled(true);
|
settings.setGeolocationEnabled(true);
|
||||||
|
settings.setDomStorageEnabled(true);
|
||||||
|
settings.setDatabaseEnabled(true);
|
||||||
|
|
||||||
|
File databaseStorage = new File(ApplicationLoader.getFilesDirFixed(), "webview_database");
|
||||||
|
if (databaseStorage.exists() && databaseStorage.isDirectory() || databaseStorage.mkdirs()) {
|
||||||
|
settings.setDatabasePath(databaseStorage.getAbsolutePath());
|
||||||
|
}
|
||||||
GeolocationPermissions.getInstance().clearAll();
|
GeolocationPermissions.getInstance().clearAll();
|
||||||
|
|
||||||
|
webView.setVerticalScrollBarEnabled(false);
|
||||||
webView.setWebViewClient(new WebViewClient() {
|
webView.setWebViewClient(new WebViewClient() {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||||
|
@ -197,20 +250,32 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
override = true;
|
override = true;
|
||||||
|
|
||||||
if (WHITELISTED_SCHEMES.contains(uriNew.getScheme())) {
|
if (WHITELISTED_SCHEMES.contains(uriNew.getScheme())) {
|
||||||
new AlertDialog.Builder(context, resourcesProvider)
|
|
||||||
.setTitle(LocaleController.getString(R.string.OpenUrlTitle))
|
|
||||||
.setMessage(LocaleController.formatString(R.string.OpenUrlAlert2, uriNew.toString()))
|
|
||||||
.setPositiveButton(LocaleController.getString(R.string.Open), (dialog, which) -> {
|
|
||||||
boolean[] forceBrowser = {false};
|
boolean[] forceBrowser = {false};
|
||||||
boolean internal = Browser.isInternalUri(uriNew, forceBrowser);
|
boolean internal = Browser.isInternalUri(uriNew, forceBrowser);
|
||||||
|
|
||||||
|
if (internal) {
|
||||||
|
if (delegate != null) {
|
||||||
|
setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
|
||||||
|
BotWebViewContainer.this.setFocusable(false);
|
||||||
|
webView.setFocusable(false);
|
||||||
|
webView.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
|
||||||
|
webView.clearFocus();
|
||||||
|
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
|
||||||
|
|
||||||
|
delegate.onCloseRequested(()-> Browser.openUrl(getContext(), uriNew, true, false));
|
||||||
|
} else {
|
||||||
Browser.openUrl(getContext(), uriNew, true, false);
|
Browser.openUrl(getContext(), uriNew, true, false);
|
||||||
if (internal && delegate != null) {
|
|
||||||
delegate.onCloseRequested();
|
|
||||||
}
|
}
|
||||||
})
|
} else {
|
||||||
|
new AlertDialog.Builder(getContext(), resourcesProvider)
|
||||||
|
.setTitle(LocaleController.getString(R.string.OpenUrlTitle))
|
||||||
|
.setMessage(LocaleController.formatString(R.string.OpenUrlAlert2, uriNew.toString()))
|
||||||
|
.setPositiveButton(LocaleController.getString(R.string.Open), (dialog, which) -> Browser.openUrl(getContext(), uriNew, true, false))
|
||||||
.setNegativeButton(LocaleController.getString(R.string.Cancel), null)
|
.setNegativeButton(LocaleController.getString(R.string.Cancel), null)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
override = false;
|
override = false;
|
||||||
}
|
}
|
||||||
|
@ -375,6 +440,36 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getMainButtonRippleColor(int buttonColor) {
|
||||||
|
return ColorUtils.calculateLuminance(buttonColor) >= 0.3f ? 0x12000000 : 0x16FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Drawable getMainButtonRippleDrawable(int buttonColor) {
|
||||||
|
return Theme.createSelectorWithBackgroundDrawable(buttonColor, getMainButtonRippleColor(buttonColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateFlickerBackgroundColor(int backgroundColor) {
|
||||||
|
flickerDrawable.setColors(backgroundColor, 0x99, 0xCC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return If this press was consumed
|
||||||
|
*/
|
||||||
|
public boolean onBackPressed() {
|
||||||
|
if (!WEB_VIEW_CAN_GO_BACK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webView == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (webView.canGoBack()) {
|
||||||
|
webView.goBack();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void setPageLoaded(String url) {
|
private void setPageLoaded(String url) {
|
||||||
if (isPageLoaded) {
|
if (isPageLoaded) {
|
||||||
return;
|
return;
|
||||||
|
@ -393,6 +488,8 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
set.start();
|
set.start();
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
isPageLoaded = true;
|
isPageLoaded = true;
|
||||||
|
BotWebViewContainer.this.setFocusable(true);
|
||||||
|
delegate.onWebAppReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasUserPermissions() {
|
public boolean hasUserPermissions() {
|
||||||
|
@ -419,6 +516,10 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPageLoaded() {
|
||||||
|
return isPageLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
public void setParentActivity(Activity parentActivity) {
|
public void setParentActivity(Activity parentActivity) {
|
||||||
this.parentActivity = parentActivity;
|
this.parentActivity = parentActivity;
|
||||||
}
|
}
|
||||||
|
@ -467,11 +568,6 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setViewPortOffset(int viewPortOffset) {
|
|
||||||
this.viewPortOffset = viewPortOffset;
|
|
||||||
invalidateViewPortHeight(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
@ -487,6 +583,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidateViewPortHeight(boolean isStable, boolean force) {
|
public void invalidateViewPortHeight(boolean isStable, boolean force) {
|
||||||
|
invalidate();
|
||||||
if (!isPageLoaded && !force) {
|
if (!isPageLoaded && !force) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -498,7 +595,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
lastExpanded = swipeContainer.getSwipeOffsetY() == -swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY();
|
lastExpanded = swipeContainer.getSwipeOffsetY() == -swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY();
|
||||||
}
|
}
|
||||||
|
|
||||||
int viewPortHeight = (int) (swipeContainer.getMeasuredHeight() - swipeContainer.getOffsetY() - swipeContainer.getSwipeOffsetY() + swipeContainer.getTopActionBarOffsetY() + viewPortOffset);
|
int viewPortHeight = (int) (swipeContainer.getMeasuredHeight() - swipeContainer.getOffsetY() - swipeContainer.getSwipeOffsetY() + swipeContainer.getTopActionBarOffsetY());
|
||||||
try {
|
try {
|
||||||
JSONObject data = new JSONObject();
|
JSONObject data = new JSONObject();
|
||||||
data.put("height", viewPortHeight / AndroidUtilities.density);
|
data.put("height", viewPortHeight / AndroidUtilities.density);
|
||||||
|
@ -529,6 +626,14 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
invalidate();
|
invalidate();
|
||||||
return draw;
|
return draw;
|
||||||
}
|
}
|
||||||
|
if (child == webViewNotAvailableText) {
|
||||||
|
canvas.save();
|
||||||
|
View parent = (View) BotWebViewContainer.this.getParent();
|
||||||
|
canvas.translate(0, (ActionBar.getCurrentActionBarHeight() - parent.getTranslationY()) / 2f);
|
||||||
|
boolean draw = super.drawChild(canvas, child, drawingTime);
|
||||||
|
canvas.restore();
|
||||||
|
return draw;
|
||||||
|
}
|
||||||
return super.drawChild(canvas, child, drawingTime);
|
return super.drawChild(canvas, child, drawingTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,7 +657,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
if (user.username != null && Objects.equals(user.username, DURGER_KING_USERNAME)) {
|
if (user.username != null && Objects.equals(user.username, DURGER_KING_USERNAME)) {
|
||||||
flickerView.setVisibility(VISIBLE);
|
flickerView.setVisibility(VISIBLE);
|
||||||
flickerView.setAlpha(1f);
|
flickerView.setAlpha(1f);
|
||||||
flickerView.setImageDrawable(SvgHelper.getDrawable(R.raw.durgerking_placeholder, Theme.getColor(Theme.key_windowBackgroundGray)));
|
flickerView.setImageDrawable(SvgHelper.getDrawable(R.raw.durgerking_placeholder, getColor(Theme.key_windowBackgroundGray)));
|
||||||
setupFlickerParams(false);
|
setupFlickerParams(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -616,12 +721,26 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
flickerView.requestLayout();
|
flickerView.requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
checkCreateWebView();
|
||||||
|
|
||||||
|
isPageLoaded = false;
|
||||||
|
hasUserPermissions = false;
|
||||||
|
if (webView != null) {
|
||||||
|
webView.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void loadUrl(String url) {
|
public void loadUrl(String url) {
|
||||||
|
checkCreateWebView();
|
||||||
|
|
||||||
isPageLoaded = false;
|
isPageLoaded = false;
|
||||||
hasUserPermissions = false;
|
hasUserPermissions = false;
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
|
if (webView != null) {
|
||||||
webView.loadUrl(url);
|
webView.loadUrl(url);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
|
@ -642,11 +761,18 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroyWebView() {
|
public void destroyWebView() {
|
||||||
|
if (webView != null) {
|
||||||
webView.destroy();
|
webView.destroy();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public void evaluateJs(String script) {
|
public void evaluateJs(String script) {
|
||||||
|
checkCreateWebView();
|
||||||
|
if (webView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
webView.evaluateJavascript(script, value -> {});
|
webView.evaluateJavascript(script, value -> {});
|
||||||
} else {
|
} else {
|
||||||
|
@ -661,7 +787,11 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
@Override
|
@Override
|
||||||
public void didReceivedNotification(int id, int account, Object... args) {
|
public void didReceivedNotification(int id, int account, Object... args) {
|
||||||
if (id == NotificationCenter.didSetNewTheme) {
|
if (id == NotificationCenter.didSetNewTheme) {
|
||||||
evaluateJs("window.Telegram.WebView.receiveEvent('theme_changed', {theme_params: " + buildThemeParams() + "});");
|
if (webView != null) {
|
||||||
|
webView.setBackgroundColor(getColor(Theme.key_windowBackgroundWhite));
|
||||||
|
}
|
||||||
|
flickerView.setColorFilter(new PorterDuffColorFilter(getColor(Theme.key_dialogSearchHint), PorterDuff.Mode.SRC_IN));
|
||||||
|
notifyThemeChanged();
|
||||||
} else if (id == NotificationCenter.onActivityResultReceived) {
|
} else if (id == NotificationCenter.onActivityResultReceived) {
|
||||||
onActivityResult((int) args[0], (int) args[1], (Intent) args[2]);
|
onActivityResult((int) args[0], (int) args[1], (Intent) args[2]);
|
||||||
} else if (id == NotificationCenter.onRequestPermissionResultReceived) {
|
} else if (id == NotificationCenter.onRequestPermissionResultReceived) {
|
||||||
|
@ -669,6 +799,10 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyThemeChanged() {
|
||||||
|
evaluateJs("window.Telegram.WebView.receiveEvent('theme_changed', {theme_params: " + buildThemeParams() + "});");
|
||||||
|
}
|
||||||
|
|
||||||
public void setWebViewScrollListener(WebViewScrollListener webViewScrollListener) {
|
public void setWebViewScrollListener(WebViewScrollListener webViewScrollListener) {
|
||||||
this.webViewScrollListener = webViewScrollListener;
|
this.webViewScrollListener = webViewScrollListener;
|
||||||
}
|
}
|
||||||
|
@ -678,13 +812,21 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onEventReceived(String eventType, String eventData) {
|
private void onEventReceived(String eventType, String eventData) {
|
||||||
|
if (webView == null || delegate == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case "web_app_close": {
|
case "web_app_close": {
|
||||||
delegate.onCloseRequested();
|
delegate.onCloseRequested(null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "web_app_data_send": {
|
case "web_app_data_send": {
|
||||||
delegate.onSendWebViewData(eventData);
|
try {
|
||||||
|
JSONObject jsonData = new JSONObject(eventData);
|
||||||
|
delegate.onSendWebViewData(jsonData.optString("data"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "web_app_expand": {
|
case "web_app_expand": {
|
||||||
|
@ -696,6 +838,10 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
invalidateViewPortHeight(!hasSwipeInProgress, true);
|
invalidateViewPortHeight(!hasSwipeInProgress, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "web_app_request_theme": {
|
||||||
|
notifyThemeChanged();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "web_app_ready": {
|
case "web_app_ready": {
|
||||||
setPageLoaded(webView.getUrl());
|
setPageLoaded(webView.getUrl());
|
||||||
break;
|
break;
|
||||||
|
@ -740,11 +886,16 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatColor(String colorKey) {
|
private int getColor(String colorKey) {
|
||||||
Integer color = resourcesProvider != null ? resourcesProvider.getColor(colorKey) : Theme.getColor(colorKey);
|
Integer color = resourcesProvider != null ? resourcesProvider.getColor(colorKey) : Theme.getColor(colorKey);
|
||||||
if (color == null) {
|
if (color == null) {
|
||||||
color = Theme.getColor(colorKey);
|
color = Theme.getColor(colorKey);
|
||||||
}
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatColor(String colorKey) {
|
||||||
|
int color = getColor(colorKey);
|
||||||
return "#" + hexFixed(Color.red(color)) + hexFixed(Color.green(color)) + hexFixed(Color.blue(color));
|
return "#" + hexFixed(Color.red(color)) + hexFixed(Color.green(color)) + hexFixed(Color.blue(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,14 +929,14 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
/**
|
/**
|
||||||
* Called when WebView requests to close itself
|
* Called when WebView requests to close itself
|
||||||
*/
|
*/
|
||||||
void onCloseRequested();
|
void onCloseRequested(@Nullable Runnable callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when WebView requests to send custom data
|
* Called when WebView requests to send custom data
|
||||||
*
|
*
|
||||||
* @param data Custom data to send
|
* @param data Custom data to send
|
||||||
*/
|
*/
|
||||||
void onSendWebViewData(String data);
|
default void onSendWebViewData(String data) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when WebView requests to expand viewport
|
* Called when WebView requests to expand viewport
|
||||||
|
@ -796,5 +947,10 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent
|
||||||
* Setups main button
|
* Setups main button
|
||||||
*/
|
*/
|
||||||
void onSetupMainButton(boolean isVisible, boolean isActive, String text, int color, int textColor, boolean isProgressVisible);
|
void onSetupMainButton(boolean isVisible, boolean isActive, String text, int color, int textColor, boolean isProgressVisible);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when WebView is ready (Called web_app_ready or page load finished)
|
||||||
|
*/
|
||||||
|
default void onWebAppReady() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.telegram.messenger.MessageObject;
|
||||||
import org.telegram.messenger.MessagesController;
|
import org.telegram.messenger.MessagesController;
|
||||||
import org.telegram.messenger.NotificationCenter;
|
import org.telegram.messenger.NotificationCenter;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.Utilities;
|
|
||||||
import org.telegram.tgnet.ConnectionsManager;
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.ActionBar;
|
import org.telegram.ui.ActionBar.ActionBar;
|
||||||
|
@ -45,21 +44,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
private final static SimpleFloatPropertyCompat<BotWebViewMenuContainer> ACTION_BAR_TRANSITION_PROGRESS_VALUE = new SimpleFloatPropertyCompat<BotWebViewMenuContainer>("actionBarTransitionProgress", obj -> obj.actionBarTransitionProgress, (obj, value) -> {
|
private final static SimpleFloatPropertyCompat<BotWebViewMenuContainer> ACTION_BAR_TRANSITION_PROGRESS_VALUE = new SimpleFloatPropertyCompat<BotWebViewMenuContainer>("actionBarTransitionProgress", obj -> obj.actionBarTransitionProgress, (obj, value) -> {
|
||||||
obj.actionBarTransitionProgress = value;
|
obj.actionBarTransitionProgress = value;
|
||||||
obj.invalidate();
|
obj.invalidate();
|
||||||
|
obj.invalidateActionBar();
|
||||||
int subtitleColor = ColorUtils.blendARGB(obj.getColor(Theme.key_actionBarDefaultSubtitle), obj.getColor(Theme.key_windowBackgroundWhiteGrayText), value);
|
|
||||||
ChatActivity chatActivity = obj.parentEnterView.getParentFragment();
|
|
||||||
ActionBar actionBar = chatActivity.getActionBar();
|
|
||||||
actionBar.setBackgroundColor(ColorUtils.blendARGB(obj.getColor(Theme.key_actionBarDefault), obj.getColor(Theme.key_windowBackgroundWhite), value));
|
|
||||||
actionBar.setItemsColor(ColorUtils.blendARGB(obj.getColor(Theme.key_actionBarDefaultIcon), obj.getColor(Theme.key_windowBackgroundWhiteBlackText), value), false);
|
|
||||||
actionBar.setItemsBackgroundColor(ColorUtils.blendARGB(obj.getColor(Theme.key_actionBarDefaultSelector), obj.getColor(Theme.key_actionBarWhiteSelector), value), false);
|
|
||||||
actionBar.setSubtitleColor(subtitleColor);
|
|
||||||
|
|
||||||
ChatAvatarContainer chatAvatarContainer = chatActivity.getAvatarContainer();
|
|
||||||
chatAvatarContainer.getTitleTextView().setTextColor(ColorUtils.blendARGB(obj.getColor(Theme.key_actionBarDefaultTitle), obj.getColor(Theme.key_windowBackgroundWhiteBlackText), value));
|
|
||||||
chatAvatarContainer.getSubtitleTextView().setTextColor(subtitleColor);
|
|
||||||
chatAvatarContainer.setOverrideSubtitleColor(value == 0 ? null : subtitleColor);
|
|
||||||
|
|
||||||
obj.updateLightStatusBar();
|
|
||||||
}).setMultiplier(100f);
|
}).setMultiplier(100f);
|
||||||
|
|
||||||
private float actionBarTransitionProgress;
|
private float actionBarTransitionProgress;
|
||||||
|
@ -133,33 +118,16 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
actionBarOnItemClick = actionBar.getActionBarMenuOnItemClick();
|
actionBarOnItemClick = actionBar.getActionBarMenuOnItemClick();
|
||||||
|
|
||||||
webViewContainer = new BotWebViewContainer(context, parentEnterView.getParentFragment().getResourceProvider(), getColor(Theme.key_windowBackgroundWhite));
|
webViewContainer = new BotWebViewContainer(context, parentEnterView.getParentFragment().getResourceProvider(), getColor(Theme.key_windowBackgroundWhite));
|
||||||
webViewContainer.setViewPortOffset(-AndroidUtilities.dp(5));
|
|
||||||
webViewContainer.setDelegate(webViewDelegate = new BotWebViewContainer.Delegate() {
|
webViewContainer.setDelegate(webViewDelegate = new BotWebViewContainer.Delegate() {
|
||||||
private boolean sentWebViewData;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCloseRequested() {
|
public void onCloseRequested(Runnable callback) {
|
||||||
dismiss();
|
dismiss(callback);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSendWebViewData(String data) {
|
|
||||||
if (sentWebViewData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sentWebViewData = true;
|
|
||||||
|
|
||||||
TLRPC.TL_messages_sendWebViewData sendWebViewData = new TLRPC.TL_messages_sendWebViewData();
|
|
||||||
sendWebViewData.bot = MessagesController.getInstance(currentAccount).getInputUser(botId);
|
|
||||||
sendWebViewData.random_id = Utilities.random.nextLong();
|
|
||||||
sendWebViewData.button_text = "Menu";
|
|
||||||
sendWebViewData.data = data;
|
|
||||||
ConnectionsManager.getInstance(currentAccount).sendRequest(sendWebViewData, (response, error) -> AndroidUtilities.runOnUIThread(()-> dismiss()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWebAppExpand() {
|
public void onWebAppExpand() {
|
||||||
if (System.currentTimeMillis() - lastSwipeTime <= 1000 || swipeContainer.isSwipeInProgress()) {
|
if (/* System.currentTimeMillis() - lastSwipeTime <= 1000 || */ swipeContainer.isSwipeInProgress()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
swipeContainer.stickTo(-swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY());
|
swipeContainer.stickTo(-swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY());
|
||||||
|
@ -181,7 +149,6 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
linePaint.setStrokeCap(Paint.Cap.ROUND);
|
linePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
|
||||||
dimPaint.setColor(0x40000000);
|
dimPaint.setColor(0x40000000);
|
||||||
backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite));
|
|
||||||
|
|
||||||
swipeContainer = new ChatAttachAlertBotWebViewLayout.WebViewSwipeContainer(context) {
|
swipeContainer = new ChatAttachAlertBotWebViewLayout.WebViewSwipeContainer(context) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -207,7 +174,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) {
|
if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) {
|
||||||
widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f), MeasureSpec.EXACTLY);
|
widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f), MeasureSpec.EXACTLY);
|
||||||
}
|
}
|
||||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.statusBarHeight + AndroidUtilities.dp(24), MeasureSpec.EXACTLY));
|
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.statusBarHeight + AndroidUtilities.dp(24) - AndroidUtilities.dp(5), MeasureSpec.EXACTLY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -218,7 +185,6 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
super.requestLayout();
|
super.requestLayout();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
swipeContainer.setWebView(webViewContainer.getWebView());
|
|
||||||
swipeContainer.setScrollListener(() -> {
|
swipeContainer.setScrollListener(() -> {
|
||||||
if (swipeContainer.getSwipeOffsetY() > 0) {
|
if (swipeContainer.getSwipeOffsetY() > 0) {
|
||||||
dimPaint.setAlpha((int) (0x40 * (1f - Math.min(swipeContainer.getSwipeOffsetY(), swipeContainer.getHeight()) / (float)swipeContainer.getHeight())));
|
dimPaint.setAlpha((int) (0x40 * (1f - Math.min(swipeContainer.getSwipeOffsetY(), swipeContainer.getHeight()) / (float)swipeContainer.getHeight())));
|
||||||
|
@ -265,6 +231,27 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
setWillNotDraw(false);
|
setWillNotDraw(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void invalidateActionBar() {
|
||||||
|
int subtitleColor = ColorUtils.blendARGB(getColor(Theme.key_actionBarDefaultSubtitle), getColor(Theme.key_windowBackgroundWhiteGrayText), actionBarTransitionProgress);
|
||||||
|
ChatActivity chatActivity = parentEnterView.getParentFragment();
|
||||||
|
ActionBar actionBar = chatActivity.getActionBar();
|
||||||
|
actionBar.setBackgroundColor(ColorUtils.blendARGB(getColor(Theme.key_actionBarDefault), getColor(Theme.key_windowBackgroundWhite), actionBarTransitionProgress));
|
||||||
|
actionBar.setItemsColor(ColorUtils.blendARGB(getColor(Theme.key_actionBarDefaultIcon), getColor(Theme.key_windowBackgroundWhiteBlackText), actionBarTransitionProgress), false);
|
||||||
|
actionBar.setItemsBackgroundColor(ColorUtils.blendARGB(getColor(Theme.key_actionBarDefaultSelector), getColor(Theme.key_actionBarWhiteSelector), actionBarTransitionProgress), false);
|
||||||
|
actionBar.setSubtitleColor(subtitleColor);
|
||||||
|
|
||||||
|
ChatAvatarContainer chatAvatarContainer = chatActivity.getAvatarContainer();
|
||||||
|
chatAvatarContainer.getTitleTextView().setTextColor(ColorUtils.blendARGB(getColor(Theme.key_actionBarDefaultTitle), getColor(Theme.key_windowBackgroundWhiteBlackText), actionBarTransitionProgress));
|
||||||
|
chatAvatarContainer.getSubtitleTextView().setTextColor(subtitleColor);
|
||||||
|
chatAvatarContainer.setOverrideSubtitleColor(actionBarTransitionProgress == 0 ? null : subtitleColor);
|
||||||
|
|
||||||
|
updateLightStatusBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onBackPressed() {
|
||||||
|
return webViewContainer.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
private void animateBotButton(boolean isVisible) {
|
private void animateBotButton(boolean isVisible) {
|
||||||
ChatActivityBotWebViewButton botWebViewButton = parentEnterView.getBotWebViewButton();
|
ChatActivityBotWebViewButton botWebViewButton = parentEnterView.getBotWebViewButton();
|
||||||
if (botWebViewButtonAnimator != null) {
|
if (botWebViewButtonAnimator != null) {
|
||||||
|
@ -316,7 +303,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
chatAvatarContainer.getAvatarImageView().setClickable(value == 0);
|
chatAvatarContainer.getAvatarImageView().setClickable(value == 0);
|
||||||
|
|
||||||
ActionBar actionBar = chatActivity.getActionBar();
|
ActionBar actionBar = chatActivity.getActionBar();
|
||||||
if (value == 100) {
|
if (value == 100 && parentEnterView.hasBotWebView()) {
|
||||||
chatActivity.showHeaderItem(false);
|
chatActivity.showHeaderItem(false);
|
||||||
botMenuItem.setVisibility(VISIBLE);
|
botMenuItem.setVisibility(VISIBLE);
|
||||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||||
|
@ -325,11 +312,19 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
dismiss();
|
dismiss();
|
||||||
} else if (id == R.id.menu_reload_page) {
|
} else if (id == R.id.menu_reload_page) {
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().animate().cancel();
|
webViewContainer.getWebView().animate().cancel();
|
||||||
webViewContainer.getWebView().animate().alpha(0).start();
|
webViewContainer.getWebView().animate().alpha(0).start();
|
||||||
|
}
|
||||||
|
|
||||||
isLoaded = false;
|
isLoaded = false;
|
||||||
loadWebView();
|
progressView.setLoadProgress(0);
|
||||||
|
progressView.setAlpha(1f);
|
||||||
|
progressView.setVisibility(VISIBLE);
|
||||||
|
|
||||||
|
webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId));
|
||||||
|
webViewContainer.loadFlicker(currentAccount, botId);
|
||||||
|
webViewContainer.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -341,6 +336,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.webViewResultSent);
|
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.webViewResultSent);
|
||||||
|
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -351,7 +347,9 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
springAnimation.cancel();
|
springAnimation.cancel();
|
||||||
springAnimation = null;
|
springAnimation = null;
|
||||||
}
|
}
|
||||||
|
actionBarTransitionProgress = 0f;
|
||||||
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.webViewResultSent);
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.webViewResultSent);
|
||||||
|
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -377,18 +375,23 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
webViewScrollAnimator = null;
|
webViewScrollAnimator = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
int fromY = webViewContainer.getWebView().getScrollY();
|
int fromY = webViewContainer.getWebView().getScrollY();
|
||||||
int toY = fromY + (oldh - contentHeight);
|
int toY = fromY + (oldh - contentHeight);
|
||||||
webViewScrollAnimator = ValueAnimator.ofInt(fromY, toY).setDuration(250);
|
webViewScrollAnimator = ValueAnimator.ofInt(fromY, toY).setDuration(250);
|
||||||
webViewScrollAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR);
|
webViewScrollAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR);
|
||||||
webViewScrollAnimator.addUpdateListener(animation -> {
|
webViewScrollAnimator.addUpdateListener(animation -> {
|
||||||
int val = (int) animation.getAnimatedValue();
|
int val = (int) animation.getAnimatedValue();
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().setScrollY(val);
|
webViewContainer.getWebView().setScrollY(val);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
webViewScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
webViewScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().setScrollY(toY);
|
webViewContainer.getWebView().setScrollY(toY);
|
||||||
|
}
|
||||||
if (animation == webViewScrollAnimator) {
|
if (animation == webViewScrollAnimator) {
|
||||||
webViewScrollAnimator = null;
|
webViewScrollAnimator = null;
|
||||||
}
|
}
|
||||||
|
@ -396,6 +399,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
});
|
});
|
||||||
webViewScrollAnimator.start();
|
webViewScrollAnimator.start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onPanTransitionEnd() {
|
public void onPanTransitionEnd() {
|
||||||
ignoreMeasure = false;
|
ignoreMeasure = false;
|
||||||
|
@ -426,6 +430,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite));
|
||||||
AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight());
|
AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight());
|
||||||
canvas.drawRect(AndroidUtilities.rectTmp, dimPaint);
|
canvas.drawRect(AndroidUtilities.rectTmp, dimPaint);
|
||||||
|
|
||||||
|
@ -437,7 +442,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() <= AndroidUtilities.lerp(swipeContainer.getTranslationY(), 0, actionBarTransitionProgress)) {
|
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() <= AndroidUtilities.lerp(swipeContainer.getTranslationY() + AndroidUtilities.dp(24), 0, actionBarTransitionProgress)) {
|
||||||
dismiss();
|
dismiss();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -448,7 +453,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
super.draw(canvas);
|
super.draw(canvas);
|
||||||
|
|
||||||
linePaint.setColor(Theme.getColor(Theme.key_dialogGrayLine));
|
linePaint.setColor(getColor(Theme.key_dialogGrayLine));
|
||||||
linePaint.setAlpha((int) (linePaint.getAlpha() * (1f - Math.min(0.5f, actionBarTransitionProgress) / 0.5f)));
|
linePaint.setAlpha((int) (linePaint.getAlpha() * (1f - Math.min(0.5f, actionBarTransitionProgress) / 0.5f)));
|
||||||
|
|
||||||
canvas.save();
|
canvas.save();
|
||||||
|
@ -499,7 +504,10 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
.setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
|
.setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
|
||||||
.setStiffness(500.0f)
|
.setStiffness(500.0f)
|
||||||
)
|
)
|
||||||
.addEndListener((animation, canceled, value, velocity) -> webViewContainer.restoreButtonData())
|
.addEndListener((animation, canceled, value, velocity) -> {
|
||||||
|
webViewContainer.restoreButtonData();
|
||||||
|
webViewContainer.invalidateViewPortHeight(true);
|
||||||
|
})
|
||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -544,6 +552,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response;
|
TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response;
|
||||||
queryId = resultUrl.query_id;
|
queryId = resultUrl.query_id;
|
||||||
webViewContainer.loadUrl(resultUrl.url);
|
webViewContainer.loadUrl(resultUrl.url);
|
||||||
|
swipeContainer.setWebView(webViewContainer.getWebView());
|
||||||
|
|
||||||
AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD);
|
AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD);
|
||||||
}
|
}
|
||||||
|
@ -594,7 +603,6 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
swipeContainer.removeView(webViewContainer);
|
swipeContainer.removeView(webViewContainer);
|
||||||
|
|
||||||
webViewContainer = new BotWebViewContainer(getContext(), parentEnterView.getParentFragment().getResourceProvider(), getColor(Theme.key_windowBackgroundWhite));
|
webViewContainer = new BotWebViewContainer(getContext(), parentEnterView.getParentFragment().getResourceProvider(), getColor(Theme.key_windowBackgroundWhite));
|
||||||
webViewContainer.setViewPortOffset(-AndroidUtilities.dp(5));
|
|
||||||
webViewContainer.setDelegate(webViewDelegate);
|
webViewContainer.setDelegate(webViewDelegate);
|
||||||
webViewContainer.setWebViewProgressListener(progress -> {
|
webViewContainer.setWebViewProgressListener(progress -> {
|
||||||
progressView.setLoadProgressAnimated(progress);
|
progressView.setLoadProgressAnimated(progress);
|
||||||
|
@ -612,7 +620,6 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
swipeContainer.addView(webViewContainer);
|
swipeContainer.addView(webViewContainer);
|
||||||
swipeContainer.setWebView(webViewContainer.getWebView());
|
|
||||||
isLoaded = false;
|
isLoaded = false;
|
||||||
|
|
||||||
AndroidUtilities.cancelRunOnUIThread(pollRunnable);
|
AndroidUtilities.cancelRunOnUIThread(pollRunnable);
|
||||||
|
@ -652,6 +659,11 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification
|
||||||
if (this.queryId == queryId) {
|
if (this.queryId == queryId) {
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
|
} else if (id == NotificationCenter.didSetNewTheme) {
|
||||||
|
webViewContainer.updateFlickerBackgroundColor(getColor(Theme.key_windowBackgroundWhite));
|
||||||
|
invalidate();
|
||||||
|
invalidateActionBar();
|
||||||
|
AndroidUtilities.runOnUIThread(this::invalidateActionBar, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
|
import androidx.core.math.MathUtils;
|
||||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||||
import androidx.dynamicanimation.animation.SpringForce;
|
import androidx.dynamicanimation.animation.SpringForce;
|
||||||
|
|
||||||
|
@ -161,19 +162,17 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
webViewContainer = new BotWebViewContainer(context, resourcesProvider, getColor(Theme.key_windowBackgroundWhite));
|
webViewContainer = new BotWebViewContainer(context, resourcesProvider, getColor(Theme.key_windowBackgroundWhite));
|
||||||
|
|
||||||
webViewContainer.getWebView().setVerticalScrollBarEnabled(false);
|
|
||||||
webViewContainer.setDelegate(new BotWebViewContainer.Delegate() {
|
webViewContainer.setDelegate(new BotWebViewContainer.Delegate() {
|
||||||
private boolean sentWebViewData;
|
private boolean sentWebViewData;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCloseRequested() {
|
public void onCloseRequested(Runnable callback) {
|
||||||
dismiss();
|
dismiss(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSendWebViewData(String data) {
|
public void onSendWebViewData(String data) {
|
||||||
if (sentWebViewData) {
|
if (queryId != 0 || sentWebViewData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sentWebViewData = true;
|
sentWebViewData = true;
|
||||||
|
@ -188,7 +187,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWebAppExpand() {
|
public void onWebAppExpand() {
|
||||||
if (System.currentTimeMillis() - lastSwipeTime <= 1000 || swipeContainer.isSwipeInProgress()) {
|
if (/* System.currentTimeMillis() - lastSwipeTime <= 1000 || */ swipeContainer.isSwipeInProgress()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
swipeContainer.stickTo(-swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY());
|
swipeContainer.stickTo(-swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY());
|
||||||
|
@ -199,7 +198,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
mainButton.setClickable(isActive);
|
mainButton.setClickable(isActive);
|
||||||
mainButton.setText(text);
|
mainButton.setText(text);
|
||||||
mainButton.setTextColor(textColor);
|
mainButton.setTextColor(textColor);
|
||||||
mainButton.setBackground(Theme.createSelectorWithBackgroundDrawable(color, Theme.getColor(Theme.key_listSelector)));
|
mainButton.setBackground(BotWebViewContainer.getMainButtonRippleDrawable(color));
|
||||||
if (isVisible != mainButtonWasVisible) {
|
if (isVisible != mainButtonWasVisible) {
|
||||||
mainButtonWasVisible = isVisible;
|
mainButtonWasVisible = isVisible;
|
||||||
mainButton.animate().cancel();
|
mainButton.animate().cancel();
|
||||||
|
@ -245,7 +244,6 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
linePaint.setStrokeWidth(AndroidUtilities.dp(4));
|
linePaint.setStrokeWidth(AndroidUtilities.dp(4));
|
||||||
linePaint.setStrokeCap(Paint.Cap.ROUND);
|
linePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
|
||||||
backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite));
|
|
||||||
dimPaint.setColor(0x40000000);
|
dimPaint.setColor(0x40000000);
|
||||||
frameLayout = new SizeNotifierFrameLayout(context) {
|
frameLayout = new SizeNotifierFrameLayout(context) {
|
||||||
{
|
{
|
||||||
|
@ -256,6 +254,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite));
|
||||||
AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight());
|
AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight());
|
||||||
canvas.drawRect(AndroidUtilities.rectTmp, dimPaint);
|
canvas.drawRect(AndroidUtilities.rectTmp, dimPaint);
|
||||||
|
|
||||||
|
@ -287,7 +286,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() < AndroidUtilities.lerp(swipeContainer.getTranslationY(), 0, actionBarTransitionProgress)) {
|
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() <= AndroidUtilities.lerp(swipeContainer.getTranslationY() + AndroidUtilities.dp(24), 0, actionBarTransitionProgress)) {
|
||||||
dismiss();
|
dismiss();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -327,10 +326,8 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
|
|
||||||
actionBar = new ActionBar(context, resourcesProvider);
|
actionBar = new ActionBar(context, resourcesProvider);
|
||||||
actionBar.setBackgroundColor(Color.TRANSPARENT);
|
actionBar.setBackgroundColor(Color.TRANSPARENT);
|
||||||
actionBar.setTitleColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
|
||||||
actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), false);
|
|
||||||
actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarWhiteSelector), false);
|
|
||||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||||
|
updateActionBarColors();
|
||||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(int id) {
|
public void onItemClick(int id) {
|
||||||
|
@ -360,10 +357,9 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
});
|
});
|
||||||
|
|
||||||
swipeContainer.addView(webViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
swipeContainer.addView(webViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
swipeContainer.setWebView(webViewContainer.getWebView());
|
|
||||||
swipeContainer.setScrollListener(()->{
|
swipeContainer.setScrollListener(()->{
|
||||||
if (swipeContainer.getSwipeOffsetY() > 0) {
|
if (swipeContainer.getSwipeOffsetY() > 0) {
|
||||||
dimPaint.setAlpha((int) (0x40 * (1f - swipeContainer.getSwipeOffsetY() / (float)swipeContainer.getHeight())));
|
dimPaint.setAlpha((int) (0x40 * (1f - MathUtils.clamp(swipeContainer.getSwipeOffsetY() / (float)swipeContainer.getHeight(), 0, 1))));
|
||||||
} else {
|
} else {
|
||||||
dimPaint.setAlpha(0x40);
|
dimPaint.setAlpha(0x40);
|
||||||
}
|
}
|
||||||
|
@ -394,6 +390,16 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
this.parentActivity = parentActivity;
|
this.parentActivity = parentActivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateActionBarColors() {
|
||||||
|
actionBar.setTitleColor(getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||||
|
actionBar.setItemsColor(getColor(Theme.key_windowBackgroundWhiteBlackText), false);
|
||||||
|
actionBar.setItemsBackgroundColor(getColor(Theme.key_actionBarWhiteSelector), false);
|
||||||
|
actionBar.setPopupBackgroundColor(getColor(Theme.key_actionBarDefaultSubmenuBackground), false);
|
||||||
|
actionBar.setPopupItemsColor(getColor(Theme.key_actionBarDefaultSubmenuItem), false, false);
|
||||||
|
actionBar.setPopupItemsColor(getColor(Theme.key_actionBarDefaultSubmenuItemIcon), true, false);
|
||||||
|
actionBar.setPopupItemsSelectorColor(getColor(Theme.key_dialogButtonSelector), false);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateLightStatusBar() {
|
private void updateLightStatusBar() {
|
||||||
int color = Theme.getColor(Theme.key_windowBackgroundWhite, null, true);
|
int color = Theme.getColor(Theme.key_windowBackgroundWhite, null, true);
|
||||||
boolean lightStatusBar = ColorUtils.calculateLuminance(color) >= 0.9 && actionBarTransitionProgress >= 0.85f;
|
boolean lightStatusBar = ColorUtils.calculateLuminance(color) >= 0.9 && actionBarTransitionProgress >= 0.85f;
|
||||||
|
@ -454,6 +460,8 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
int color = Theme.getColor(Theme.key_windowBackgroundWhite, null, true);
|
int color = Theme.getColor(Theme.key_windowBackgroundWhite, null, true);
|
||||||
AndroidUtilities.setLightNavigationBar(window, ColorUtils.calculateLuminance(color) >= 0.9);
|
AndroidUtilities.setLightNavigationBar(window, ColorUtils.calculateLuminance(color) >= 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -507,9 +515,18 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
} else if (id == R.id.menu_reload_page) {
|
} else if (id == R.id.menu_reload_page) {
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().animate().cancel();
|
webViewContainer.getWebView().animate().cancel();
|
||||||
webViewContainer.getWebView().animate().alpha(0).start();
|
webViewContainer.getWebView().animate().alpha(0).start();
|
||||||
requestWebView(currentAccount, peerId, botId, buttonText, buttonUrl, simple, replyToMsgId, silent);
|
}
|
||||||
|
|
||||||
|
progressView.setLoadProgress(0);
|
||||||
|
progressView.setAlpha(1f);
|
||||||
|
progressView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId));
|
||||||
|
webViewContainer.loadFlicker(currentAccount, botId);
|
||||||
|
webViewContainer.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -545,7 +562,9 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()->{
|
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()->{
|
||||||
if (response instanceof TLRPC.TL_simpleWebViewResultUrl) {
|
if (response instanceof TLRPC.TL_simpleWebViewResultUrl) {
|
||||||
TLRPC.TL_simpleWebViewResultUrl resultUrl = (TLRPC.TL_simpleWebViewResultUrl) response;
|
TLRPC.TL_simpleWebViewResultUrl resultUrl = (TLRPC.TL_simpleWebViewResultUrl) response;
|
||||||
|
queryId = 0;
|
||||||
webViewContainer.loadUrl(resultUrl.url);
|
webViewContainer.loadUrl(resultUrl.url);
|
||||||
|
swipeContainer.setWebView(webViewContainer.getWebView());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
@ -573,6 +592,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response;
|
TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response;
|
||||||
queryId = resultUrl.query_id;
|
queryId = resultUrl.query_id;
|
||||||
webViewContainer.loadUrl(resultUrl.url);
|
webViewContainer.loadUrl(resultUrl.url);
|
||||||
|
swipeContainer.setWebView(webViewContainer.getWebView());
|
||||||
|
|
||||||
AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD);
|
AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD);
|
||||||
}
|
}
|
||||||
|
@ -612,8 +632,20 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
super.show();
|
super.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
if (webViewContainer.onBackPressed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dismiss() {
|
public void dismiss() {
|
||||||
|
dismiss(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dismiss(Runnable callback) {
|
||||||
if (dismissed) {
|
if (dismissed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -622,8 +654,14 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
|
|
||||||
webViewContainer.destroyWebView();
|
webViewContainer.destroyWebView();
|
||||||
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.webViewResultSent);
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.webViewResultSent);
|
||||||
|
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewTheme);
|
||||||
|
|
||||||
swipeContainer.stickTo(swipeContainer.getHeight() + frameLayout.measureKeyboardHeight(), super::dismiss);
|
swipeContainer.stickTo(swipeContainer.getHeight() + frameLayout.measureKeyboardHeight(), ()->{
|
||||||
|
super.dismiss();
|
||||||
|
if (callback != null) {
|
||||||
|
callback.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -634,6 +672,11 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
|
||||||
if (this.queryId == queryId) {
|
if (this.queryId == queryId) {
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
|
} else if (id == NotificationCenter.didSetNewTheme) {
|
||||||
|
frameLayout.invalidate();
|
||||||
|
webViewContainer.updateFlickerBackgroundColor(getColor(Theme.key_windowBackgroundWhite));
|
||||||
|
updateActionBarColors();
|
||||||
|
updateLightStatusBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,18 +42,18 @@ public class ChatActivityBotWebViewButton extends FrameLayout {
|
||||||
textView.setAlpha(0f);
|
textView.setAlpha(0f);
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT, 0, 0, 0, 4));
|
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT, 0, 0, 0, 0));
|
||||||
|
|
||||||
progressView = new RadialProgressView(context);
|
progressView = new RadialProgressView(context);
|
||||||
progressView.setSize(AndroidUtilities.dp(18));
|
progressView.setSize(AndroidUtilities.dp(18));
|
||||||
progressView.setAlpha(0f);
|
progressView.setAlpha(0f);
|
||||||
progressView.setScaleX(0);
|
progressView.setScaleX(0);
|
||||||
progressView.setScaleY(0);
|
progressView.setScaleY(0);
|
||||||
addView(progressView, LayoutHelper.createFrame(28, 28, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 12, 4));
|
addView(progressView, LayoutHelper.createFrame(28, 28, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 12, 0));
|
||||||
|
|
||||||
rippleView = new View(context);
|
rippleView = new View(context);
|
||||||
rippleView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 2));
|
rippleView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_featuredStickers_addButtonPressed), 2));
|
||||||
addView(rippleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT, 0, -4, 0, 0));
|
addView(rippleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT, 0, 0, 0, 0));
|
||||||
|
|
||||||
setWillNotDraw(false);
|
setWillNotDraw(false);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,8 @@ public class ChatActivityBotWebViewButton extends FrameLayout {
|
||||||
textView.setTextColor(textColor);
|
textView.setTextColor(textColor);
|
||||||
buttonColor = color;
|
buttonColor = color;
|
||||||
|
|
||||||
|
rippleView.setBackground(Theme.createSelectorDrawable(BotWebViewContainer.getMainButtonRippleColor(buttonColor), 2));
|
||||||
|
|
||||||
progressView.setProgressColor(textColor);
|
progressView.setProgressColor(textColor);
|
||||||
if (progressWasVisible != isProgressVisible) {
|
if (progressWasVisible != isProgressVisible) {
|
||||||
progressWasVisible = isProgressVisible;
|
progressWasVisible = isProgressVisible;
|
||||||
|
@ -91,6 +93,7 @@ public class ChatActivityBotWebViewButton extends FrameLayout {
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgress(float progress) {
|
public void setProgress(float progress) {
|
||||||
|
@ -110,9 +113,10 @@ public class ChatActivityBotWebViewButton extends FrameLayout {
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
|
float menuY = (getHeight() - AndroidUtilities.dp(32)) / 2f;
|
||||||
float offset = Math.max(getWidth() - menuButtonWidth - AndroidUtilities.dp(4), getHeight()) * progress;
|
float offset = Math.max(getWidth() - menuButtonWidth - AndroidUtilities.dp(4), getHeight()) * progress;
|
||||||
float rad = AndroidUtilities.dp(16) + offset;
|
float rad = AndroidUtilities.dp(16) + offset;
|
||||||
AndroidUtilities.rectTmp.set(AndroidUtilities.dp(14) - offset, AndroidUtilities.dp(8) - offset, AndroidUtilities.dp(6) + menuButtonWidth + offset, getHeight() - AndroidUtilities.dp(12) + offset);
|
AndroidUtilities.rectTmp.set(AndroidUtilities.dp(14) - offset, menuY + AndroidUtilities.dp(4) - offset, AndroidUtilities.dp(6) + menuButtonWidth + offset, getHeight() - AndroidUtilities.dp(12) + offset);
|
||||||
|
|
||||||
path.rewind();
|
path.rewind();
|
||||||
path.addRoundRect(AndroidUtilities.rectTmp, rad, rad, Path.Direction.CW);
|
path.addRoundRect(AndroidUtilities.rectTmp, rad, rad, Path.Direction.CW);
|
||||||
|
@ -120,7 +124,7 @@ public class ChatActivityBotWebViewButton extends FrameLayout {
|
||||||
canvas.drawColor(backgroundColor);
|
canvas.drawColor(backgroundColor);
|
||||||
|
|
||||||
canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) ((1f - Math.min(0.5f, progress) / 0.5f) * 0xFF), Canvas.ALL_SAVE_FLAG);
|
canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) ((1f - Math.min(0.5f, progress) / 0.5f) * 0xFF), Canvas.ALL_SAVE_FLAG);
|
||||||
canvas.translate(AndroidUtilities.dp(10), AndroidUtilities.dp(4));
|
canvas.translate(AndroidUtilities.dp(10), menuY);
|
||||||
if (menuButton != null) {
|
if (menuButton != null) {
|
||||||
menuButton.setDrawBackgroundDrawable(false);
|
menuButton.setDrawBackgroundDrawable(false);
|
||||||
menuButton.draw(canvas);
|
menuButton.draw(canvas);
|
||||||
|
|
|
@ -1720,6 +1720,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
|
||||||
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer);
|
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer);
|
||||||
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.sendingMessagesChanged);
|
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.sendingMessagesChanged);
|
||||||
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.audioRecordTooShort);
|
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.audioRecordTooShort);
|
||||||
|
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateBotMenuButton);
|
||||||
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
|
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
|
||||||
|
|
||||||
parentActivity = context;
|
parentActivity = context;
|
||||||
|
@ -4180,6 +4181,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
|
||||||
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer);
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer);
|
||||||
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.sendingMessagesChanged);
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.sendingMessagesChanged);
|
||||||
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.audioRecordTooShort);
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.audioRecordTooShort);
|
||||||
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateBotMenuButton);
|
||||||
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
|
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
|
||||||
if (emojiView != null) {
|
if (emojiView != null) {
|
||||||
emojiView.onDestroy();
|
emojiView.onDestroy();
|
||||||
|
@ -6882,7 +6884,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasBotWebView() {
|
public boolean onBotWebViewBackPressed() {
|
||||||
|
return botWebViewMenuContainer != null && botWebViewMenuContainer.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasBotWebView() {
|
||||||
return botMenuButtonType == BotMenuButtonType.WEB_VIEW;
|
return botMenuButtonType == BotMenuButtonType.WEB_VIEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8356,6 +8362,24 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
|
||||||
}
|
}
|
||||||
} else if (id == NotificationCenter.audioRecordTooShort) {
|
} else if (id == NotificationCenter.audioRecordTooShort) {
|
||||||
updateRecordIntefrace(RECORD_STATE_CANCEL_BY_TIME);
|
updateRecordIntefrace(RECORD_STATE_CANCEL_BY_TIME);
|
||||||
|
} else if (id == NotificationCenter.updateBotMenuButton) {
|
||||||
|
long botId = (long) args[0];
|
||||||
|
TLRPC.BotMenuButton botMenuButton = (TLRPC.BotMenuButton) args[1];
|
||||||
|
|
||||||
|
if (botId == dialog_id) {
|
||||||
|
if (botMenuButton instanceof TLRPC.TL_botMenuButton) {
|
||||||
|
TLRPC.TL_botMenuButton webViewButton = (TLRPC.TL_botMenuButton) botMenuButton;
|
||||||
|
botMenuWebViewTitle = webViewButton.text;
|
||||||
|
botMenuWebViewUrl = webViewButton.url;
|
||||||
|
botMenuButtonType = BotMenuButtonType.WEB_VIEW;
|
||||||
|
} else if (hasBotCommands) {
|
||||||
|
botMenuButtonType = BotMenuButtonType.COMMANDS;
|
||||||
|
} else {
|
||||||
|
botMenuButtonType = BotMenuButtonType.NO_BUTTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBotButton(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9187,7 +9211,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
|
||||||
if (botCommandsMenuButton != null) {
|
if (botCommandsMenuButton != null) {
|
||||||
botWebViewButton.setMeasuredButtonWidth(botCommandsMenuButton.getMeasuredWidth());
|
botWebViewButton.setMeasuredButtonWidth(botCommandsMenuButton.getMeasuredWidth());
|
||||||
}
|
}
|
||||||
botWebViewButton.getLayoutParams().height = messageEditText.getMeasuredHeight();
|
botWebViewButton.getLayoutParams().height = getMeasuredHeight() - AndroidUtilities.dp(2);
|
||||||
measureChild(botWebViewButton, widthMeasureSpec, heightMeasureSpec);
|
measureChild(botWebViewButton, widthMeasureSpec, heightMeasureSpec);
|
||||||
}
|
}
|
||||||
if (botWebViewMenuContainer != null) {
|
if (botWebViewMenuContainer != null) {
|
||||||
|
@ -9219,13 +9243,13 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
|
||||||
if (botInfo.size() == 1 && botInfo.valueAt(0).user_id == dialog_id) {
|
if (botInfo.size() == 1 && botInfo.valueAt(0).user_id == dialog_id) {
|
||||||
TLRPC.BotInfo info = botInfo.valueAt(0);
|
TLRPC.BotInfo info = botInfo.valueAt(0);
|
||||||
TLRPC.BotMenuButton menuButton = info.menu_button;
|
TLRPC.BotMenuButton menuButton = info.menu_button;
|
||||||
if (menuButton instanceof TLRPC.TL_botMenuButtonCommands || menuButton instanceof TLRPC.TL_botMenuButtonDefault) {
|
if (menuButton instanceof TLRPC.TL_botMenuButton) {
|
||||||
botMenuButtonType = info.commands.isEmpty() ? BotMenuButtonType.NO_BUTTON : BotMenuButtonType.COMMANDS;
|
|
||||||
} else if (menuButton instanceof TLRPC.TL_botMenuButton) {
|
|
||||||
TLRPC.TL_botMenuButton webViewButton = (TLRPC.TL_botMenuButton) menuButton;
|
TLRPC.TL_botMenuButton webViewButton = (TLRPC.TL_botMenuButton) menuButton;
|
||||||
botMenuWebViewTitle = webViewButton.text;
|
botMenuWebViewTitle = webViewButton.text;
|
||||||
botMenuWebViewUrl = webViewButton.url;
|
botMenuWebViewUrl = webViewButton.url;
|
||||||
botMenuButtonType = BotMenuButtonType.WEB_VIEW;
|
botMenuButtonType = BotMenuButtonType.WEB_VIEW;
|
||||||
|
} else if (!info.commands.isEmpty()) {
|
||||||
|
botMenuButtonType = BotMenuButtonType.COMMANDS;
|
||||||
} else {
|
} else {
|
||||||
botMenuButtonType = BotMenuButtonType.NO_BUTTON;
|
botMenuButtonType = BotMenuButtonType.NO_BUTTON;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
|
@ -136,16 +137,19 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
botAttachLayouts.put(id, webViewLayout);
|
botAttachLayouts.put(id, webViewLayout);
|
||||||
botAttachLayouts.get(id).setDelegate(new BotWebViewContainer.Delegate() {
|
botAttachLayouts.get(id).setDelegate(new BotWebViewContainer.Delegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onCloseRequested() {
|
public void onCloseRequested(Runnable callback) {
|
||||||
if (currentAttachLayout != webViewLayout) {
|
if (currentAttachLayout != webViewLayout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dismiss();
|
ChatAttachAlert.this.setFocusable(false);
|
||||||
}
|
ChatAttachAlert.this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
|
||||||
|
|
||||||
@Override
|
dismiss();
|
||||||
public void onSendWebViewData(String data) {
|
AndroidUtilities.runOnUIThread(()->{
|
||||||
// Empty as it's delegate from attachments menu. Data is only available for buttons
|
if (callback != null) {
|
||||||
|
callback.run();
|
||||||
|
}
|
||||||
|
}, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -167,7 +171,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
botMainButtonTextView.setClickable(isActive);
|
botMainButtonTextView.setClickable(isActive);
|
||||||
botMainButtonTextView.setText(text);
|
botMainButtonTextView.setText(text);
|
||||||
botMainButtonTextView.setTextColor(textColor);
|
botMainButtonTextView.setTextColor(textColor);
|
||||||
botMainButtonTextView.setBackground(Theme.createSelectorWithBackgroundDrawable(color, Theme.getColor(Theme.key_listSelector)));
|
botMainButtonTextView.setBackground(BotWebViewContainer.getMainButtonRippleDrawable(color));
|
||||||
if (botButtonWasVisible != isVisible) {
|
if (botButtonWasVisible != isVisible) {
|
||||||
ValueAnimator animator = ValueAnimator.ofFloat(isVisible ? 0 : 1, isVisible ? 1 : 0).setDuration(250);
|
ValueAnimator animator = ValueAnimator.ofFloat(isVisible ? 0 : 1, isVisible ? 1 : 0).setDuration(250);
|
||||||
animator.addUpdateListener(animation -> {
|
animator.addUpdateListener(animation -> {
|
||||||
|
@ -184,6 +188,11 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
botMainButtonTextView.setAlpha(0f);
|
botMainButtonTextView.setAlpha(0f);
|
||||||
botMainButtonTextView.setVisibility(View.VISIBLE);
|
botMainButtonTextView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
int offsetY = AndroidUtilities.dp(36);
|
||||||
|
for (int i = 0; i < botAttachLayouts.size(); i++) {
|
||||||
|
botAttachLayouts.valueAt(i).setMeasureOffsetY(offsetY);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
buttonsRecyclerView.setAlpha(0f);
|
buttonsRecyclerView.setAlpha(0f);
|
||||||
buttonsRecyclerView.setVisibility(View.VISIBLE);
|
buttonsRecyclerView.setVisibility(View.VISIBLE);
|
||||||
|
@ -915,7 +924,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
|
|
||||||
TLRPC.Document iconDoc = icon.icon;
|
TLRPC.Document iconDoc = icon.icon;
|
||||||
imageView.getImageReceiver().setAllowStartLottieAnimation(false);
|
imageView.getImageReceiver().setAllowStartLottieAnimation(false);
|
||||||
imageView.setImage(ImageLocation.getForDocument(iconDoc), "32_32", animated ? "tgs" : "svg", null, icon);
|
imageView.setImage(ImageLocation.getForDocument(iconDoc), String.valueOf(bot.bot_id), animated ? "tgs" : "svg", null, bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
imageView.setSize(AndroidUtilities.dp(28), AndroidUtilities.dp(28));
|
imageView.setSize(AndroidUtilities.dp(28), AndroidUtilities.dp(28));
|
||||||
|
@ -1444,7 +1453,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int color1 = getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground);
|
int color1 = getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground);
|
||||||
int finalColor = Color.argb((int) (255 * actionBar.getAlpha()), (int) (Color.red(color1) * 0.8f), (int) (Color.green(color1) * 0.8f), (int) (Color.blue(color1) * 0.8f));
|
int finalColor = Color.argb((int) (255 * actionBar.getAlpha()), Color.red(color1), Color.green(color1), Color.blue(color1));
|
||||||
Theme.dialogs_onlineCirclePaint.setColor(finalColor);
|
Theme.dialogs_onlineCirclePaint.setColor(finalColor);
|
||||||
canvas.drawRect(backgroundPaddingLeft, currentPanTranslationY, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight + currentPanTranslationY, Theme.dialogs_onlineCirclePaint);
|
canvas.drawRect(backgroundPaddingLeft, currentPanTranslationY, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight + currentPanTranslationY, Theme.dialogs_onlineCirclePaint);
|
||||||
}
|
}
|
||||||
|
@ -1524,7 +1533,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
actionBar = new ActionBar(context, resourcesProvider) {
|
actionBar = new ActionBar(context, resourcesProvider) {
|
||||||
@Override
|
@Override
|
||||||
public void setAlpha(float alpha) {
|
public void setAlpha(float alpha) {
|
||||||
|
float oldAlpha = getAlpha();
|
||||||
super.setAlpha(alpha);
|
super.setAlpha(alpha);
|
||||||
|
if (oldAlpha != alpha) {
|
||||||
containerView.invalidate();
|
containerView.invalidate();
|
||||||
if (frameLayout2 != null && buttonsRecyclerView != null) {
|
if (frameLayout2 != null && buttonsRecyclerView != null) {
|
||||||
if (frameLayout2.getTag() == null) {
|
if (frameLayout2.getTag() == null) {
|
||||||
|
@ -1543,6 +1554,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
actionBar.setBackgroundColor(getThemedColor(Theme.key_dialogBackground));
|
actionBar.setBackgroundColor(getThemedColor(Theme.key_dialogBackground));
|
||||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||||
|
@ -2324,11 +2336,24 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (baseFragment != null) {
|
||||||
|
AndroidUtilities.setLightStatusBar(getWindow(), baseFragment.isLightStatusBar());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLightStatusBar() {
|
||||||
|
int color = getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground);
|
||||||
|
return ColorUtils.calculateLuminance(color) > 0.7f;
|
||||||
|
}
|
||||||
|
|
||||||
public void onLongClickBotButton(TLRPC.TL_attachMenuBot attachMenuBot, TLRPC.User currentUser) {
|
public void onLongClickBotButton(TLRPC.TL_attachMenuBot attachMenuBot, TLRPC.User currentUser) {
|
||||||
String botName = attachMenuBot != null ? attachMenuBot.short_name : UserObject.getUserName(currentUser);
|
String botName = attachMenuBot != null ? attachMenuBot.short_name : UserObject.getUserName(currentUser);
|
||||||
new AlertDialog.Builder(getContext())
|
new AlertDialog.Builder(getContext())
|
||||||
.setTitle(LocaleController.getString(attachMenuBot != null ? R.string.BotRemoveFromMenuTitle : R.string.AppName))
|
.setTitle(LocaleController.getString(R.string.BotRemoveFromMenuTitle))
|
||||||
.setMessage(AndroidUtilities.replaceTags(attachMenuBot != null ? LocaleController.formatString("BotRemoveFromMenu", R.string.BotRemoveFromMenu, botName) : LocaleController.formatString("ChatHintsDelete", R.string.ChatHintsDelete, botName)))
|
.setMessage(AndroidUtilities.replaceTags(attachMenuBot != null ? LocaleController.formatString("BotRemoveFromMenu", R.string.BotRemoveFromMenu, botName) : LocaleController.formatString("BotRemoveInlineFromMenu", R.string.BotRemoveInlineFromMenu, botName)))
|
||||||
.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> {
|
.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> {
|
||||||
if (attachMenuBot != null) {
|
if (attachMenuBot != null) {
|
||||||
TLRPC.TL_messages_toggleBotInAttachMenu req = new TLRPC.TL_messages_toggleBotInAttachMenu();
|
TLRPC.TL_messages_toggleBotInAttachMenu req = new TLRPC.TL_messages_toggleBotInAttachMenu();
|
||||||
|
@ -3192,6 +3217,14 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
|
||||||
} else if (typeButtonsAvailable && frameLayout2.getTag() == null) {
|
} else if (typeButtonsAvailable && frameLayout2.getTag() == null) {
|
||||||
buttonsRecyclerView.setVisibility(View.VISIBLE);
|
buttonsRecyclerView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getWindow() != null && baseFragment != null) {
|
||||||
|
if (show) {
|
||||||
|
AndroidUtilities.setLightStatusBar(getWindow(), isLightStatusBar());
|
||||||
|
} else {
|
||||||
|
AndroidUtilities.setLightStatusBar(getWindow(), baseFragment.isLightStatusBar());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (animated) {
|
if (animated) {
|
||||||
actionBarAnimation = new AnimatorSet();
|
actionBarAnimation = new AnimatorSet();
|
||||||
actionBarAnimation.setDuration((long) (180 * Math.abs((show ? 1.0f : 0.0f) - actionBar.getAlpha())));
|
actionBarAnimation.setDuration((long) (180 * Math.abs((show ? 1.0f : 0.0f) - actionBar.getAlpha())));
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
@ -114,9 +115,18 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
parentAlert.baseFragment.presentFragment(new ChatActivity(bundle));
|
parentAlert.baseFragment.presentFragment(new ChatActivity(bundle));
|
||||||
parentAlert.dismiss();
|
parentAlert.dismiss();
|
||||||
} else if (id == R.id.menu_reload_page) {
|
} else if (id == R.id.menu_reload_page) {
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().animate().cancel();
|
webViewContainer.getWebView().animate().cancel();
|
||||||
webViewContainer.getWebView().animate().alpha(0).start();
|
webViewContainer.getWebView().animate().alpha(0).start();
|
||||||
requestWebView(currentAccount, peerId, botId, silent, replyToMsgId, startCommand);
|
}
|
||||||
|
|
||||||
|
progressView.setLoadProgress(0);
|
||||||
|
progressView.setAlpha(1f);
|
||||||
|
progressView.setVisibility(VISIBLE);
|
||||||
|
|
||||||
|
webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId));
|
||||||
|
webViewContainer.loadFlicker(currentAccount, botId);
|
||||||
|
webViewContainer.reload();
|
||||||
} else if (id == R.id.menu_delete_bot) {
|
} else if (id == R.id.menu_delete_bot) {
|
||||||
for (TLRPC.TL_attachMenuBot bot : MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots) {
|
for (TLRPC.TL_attachMenuBot bot : MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots) {
|
||||||
if (bot.bot_id == botId) {
|
if (bot.bot_id == botId) {
|
||||||
|
@ -140,7 +150,6 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
return super.dispatchTouchEvent(ev);
|
return super.dispatchTouchEvent(ev);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
webViewContainer.getWebView().setVerticalScrollBarEnabled(false);
|
|
||||||
swipeContainer = new WebViewSwipeContainer(context) {
|
swipeContainer = new WebViewSwipeContainer(context) {
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
@ -148,7 +157,6 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
swipeContainer.addView(webViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
swipeContainer.addView(webViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
swipeContainer.setWebView(webViewContainer.getWebView());
|
|
||||||
swipeContainer.setScrollListener(() -> {
|
swipeContainer.setScrollListener(() -> {
|
||||||
parentAlert.updateLayout(this, true, 0);
|
parentAlert.updateLayout(this, true, 0);
|
||||||
webViewContainer.invalidateViewPortHeight();
|
webViewContainer.invalidateViewPortHeight();
|
||||||
|
@ -173,12 +181,16 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
animator.start();
|
animator.start();
|
||||||
|
|
||||||
|
requestEnableKeyboard();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canExpandByRequest() {
|
public boolean canExpandByRequest() {
|
||||||
return System.currentTimeMillis() - lastSwipeTime > 1000 && !swipeContainer.isSwipeInProgress();
|
return /* System.currentTimeMillis() - lastSwipeTime > 1000 && */ !swipeContainer.isSwipeInProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMeasureOffsetY(int measureOffsetY) {
|
public void setMeasureOffsetY(int measureOffsetY) {
|
||||||
|
@ -214,18 +226,23 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
webViewScrollAnimator = null;
|
webViewScrollAnimator = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
int fromY = webViewContainer.getWebView().getScrollY();
|
int fromY = webViewContainer.getWebView().getScrollY();
|
||||||
int toY = fromY + (oldh - contentHeight);
|
int toY = fromY + (oldh - contentHeight);
|
||||||
webViewScrollAnimator = ValueAnimator.ofInt(fromY, toY).setDuration(250);
|
webViewScrollAnimator = ValueAnimator.ofInt(fromY, toY).setDuration(250);
|
||||||
webViewScrollAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR);
|
webViewScrollAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR);
|
||||||
webViewScrollAnimator.addUpdateListener(animation -> {
|
webViewScrollAnimator.addUpdateListener(animation -> {
|
||||||
int val = (int) animation.getAnimatedValue();
|
int val = (int) animation.getAnimatedValue();
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().setScrollY(val);
|
webViewContainer.getWebView().setScrollY(val);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
webViewScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
webViewScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().setScrollY(toY);
|
webViewContainer.getWebView().setScrollY(toY);
|
||||||
|
}
|
||||||
if (animation == webViewScrollAnimator) {
|
if (animation == webViewScrollAnimator) {
|
||||||
webViewScrollAnimator = null;
|
webViewScrollAnimator = null;
|
||||||
}
|
}
|
||||||
|
@ -233,6 +250,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
});
|
});
|
||||||
webViewScrollAnimator.start();
|
webViewScrollAnimator.start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPanTransitionEnd() {
|
public void onPanTransitionEnd() {
|
||||||
|
@ -244,7 +262,9 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
void onShow(ChatAttachAlert.AttachAlertLayout previousLayout) {
|
void onShow(ChatAttachAlert.AttachAlertLayout previousLayout) {
|
||||||
parentAlert.actionBar.setTitle(UserObject.getUserName(MessagesController.getInstance(currentAccount).getUser(botId)));
|
parentAlert.actionBar.setTitle(UserObject.getUserName(MessagesController.getInstance(currentAccount).getUser(botId)));
|
||||||
swipeContainer.setSwipeOffsetY(0);
|
swipeContainer.setSwipeOffsetY(0);
|
||||||
|
if (webViewContainer.getWebView() != null) {
|
||||||
webViewContainer.getWebView().scrollTo(0, 0);
|
webViewContainer.getWebView().scrollTo(0, 0);
|
||||||
|
}
|
||||||
if (parentAlert.getBaseFragment() != null) {
|
if (parentAlert.getBaseFragment() != null) {
|
||||||
webViewContainer.setParentActivity(parentAlert.getBaseFragment().getParentActivity());
|
webViewContainer.setParentActivity(parentAlert.getBaseFragment().getParentActivity());
|
||||||
}
|
}
|
||||||
|
@ -253,7 +273,9 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void onShown() {
|
void onShown() {
|
||||||
|
if (webViewContainer.isPageLoaded()) {
|
||||||
requestEnableKeyboard();
|
requestEnableKeyboard();
|
||||||
|
}
|
||||||
|
|
||||||
swipeContainer.setSwipeOffsetAnimationDisallowed(false);
|
swipeContainer.setSwipeOffsetAnimationDisallowed(false);
|
||||||
AndroidUtilities.runOnUIThread(() -> webViewContainer.restoreButtonData());
|
AndroidUtilities.runOnUIThread(() -> webViewContainer.restoreButtonData());
|
||||||
|
@ -263,13 +285,13 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
BaseFragment fragment = parentAlert.getBaseFragment();
|
BaseFragment fragment = parentAlert.getBaseFragment();
|
||||||
if (fragment instanceof ChatActivity && ((ChatActivity) fragment).contentView.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
|
if (fragment instanceof ChatActivity && ((ChatActivity) fragment).contentView.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
|
||||||
AndroidUtilities.hideKeyboard(parentAlert.baseFragment.getFragmentView());
|
AndroidUtilities.hideKeyboard(parentAlert.baseFragment.getFragmentView());
|
||||||
AndroidUtilities.runOnUIThread(this::requestEnableKeyboard, 150);
|
AndroidUtilities.runOnUIThread(this::requestEnableKeyboard, 250);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parentAlert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
parentAlert.setFocusable(true);
|
parentAlert.setFocusable(true);
|
||||||
parentAlert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -345,6 +367,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response;
|
TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response;
|
||||||
queryId = resultUrl.query_id;
|
queryId = resultUrl.query_id;
|
||||||
webViewContainer.loadUrl(resultUrl.url);
|
webViewContainer.loadUrl(resultUrl.url);
|
||||||
|
swipeContainer.setWebView(webViewContainer.getWebView());
|
||||||
|
|
||||||
AndroidUtilities.runOnUIThread(pollRunnable);
|
AndroidUtilities.runOnUIThread(pollRunnable);
|
||||||
}
|
}
|
||||||
|
@ -356,6 +379,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
@Override
|
@Override
|
||||||
void onDestroy() {
|
void onDestroy() {
|
||||||
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.webViewResultSent);
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.webViewResultSent);
|
||||||
|
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewTheme);
|
||||||
|
|
||||||
ActionBarMenu menu = parentAlert.actionBar.createMenu();
|
ActionBarMenu menu = parentAlert.actionBar.createMenu();
|
||||||
otherItem.removeAllSubItems();
|
otherItem.removeAllSubItems();
|
||||||
|
@ -422,6 +446,11 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
return AndroidUtilities.dp(56);
|
return AndroidUtilities.dp(56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean onBackPressed() {
|
||||||
|
return webViewContainer.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestLayout() {
|
public void requestLayout() {
|
||||||
if (ignoreLayout) {
|
if (ignoreLayout) {
|
||||||
|
@ -467,6 +496,8 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
needReload = true;
|
needReload = true;
|
||||||
parentAlert.dismiss();
|
parentAlert.dismiss();
|
||||||
}
|
}
|
||||||
|
} else if (id == NotificationCenter.didSetNewTheme) {
|
||||||
|
webViewContainer.updateFlickerBackgroundColor(getThemedColor(Theme.key_dialogBackground));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,6 +523,8 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
|
|
||||||
private SpringAnimation scrollAnimator;
|
private SpringAnimation scrollAnimator;
|
||||||
|
|
||||||
|
private int swipeStickyRange;
|
||||||
|
|
||||||
public WebViewSwipeContainer(@NonNull Context context) {
|
public WebViewSwipeContainer(@NonNull Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
|
@ -502,10 +535,10 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
if (isSwipeDisallowed) {
|
if (isSwipeDisallowed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (velocityY >= 700 && webView.getScrollY() == 0) {
|
if (velocityY >= 700 && (webView == null || webView.getScrollY() == 0)) {
|
||||||
flingInProgress = true;
|
flingInProgress = true;
|
||||||
|
|
||||||
if (swipeOffsetY >= AndroidUtilities.dp(64)) {
|
if (swipeOffsetY >= swipeStickyRange) {
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
delegate.onDismiss();
|
delegate.onDismiss();
|
||||||
}
|
}
|
||||||
|
@ -524,7 +557,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
@Override
|
@Override
|
||||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
||||||
if (!isScrolling && !isSwipeDisallowed) {
|
if (!isScrolling && !isSwipeDisallowed) {
|
||||||
if (Math.abs(distanceY) >= touchSlop && Math.abs(distanceY) * 1.5f >= Math.abs(distanceX) && (swipeOffsetY != -offsetY + topActionBarOffsetY || distanceY < 0 && webView.getScrollY() == 0)) {
|
if (Math.abs(distanceY) >= touchSlop && Math.abs(distanceY) * 1.5f >= Math.abs(distanceX) && (swipeOffsetY != -offsetY + topActionBarOffsetY || webView == null || distanceY < 0 && webView.getScrollY() == 0)) {
|
||||||
isScrolling = true;
|
isScrolling = true;
|
||||||
|
|
||||||
MotionEvent ev = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
|
MotionEvent ev = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
|
||||||
|
@ -534,7 +567,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
ev.recycle();
|
ev.recycle();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (webView.canScrollHorizontally(distanceX >= 0 ? 1 : -1)) {
|
} else if (webView != null && webView.canScrollHorizontally(distanceX >= 0 ? 1 : -1)) {
|
||||||
isSwipeDisallowed = true;
|
isSwipeDisallowed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -542,18 +575,20 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
if (distanceY < 0) {
|
if (distanceY < 0) {
|
||||||
if (swipeOffsetY > -offsetY + topActionBarOffsetY) {
|
if (swipeOffsetY > -offsetY + topActionBarOffsetY) {
|
||||||
swipeOffsetY -= distanceY;
|
swipeOffsetY -= distanceY;
|
||||||
} else {
|
} else if (webView != null) {
|
||||||
float newWebScrollY = webView.getScrollY() + distanceY;
|
float newWebScrollY = webView.getScrollY() + distanceY;
|
||||||
webView.setScrollY((int) MathUtils.clamp(newWebScrollY, 0, Math.max(webView.getContentHeight(), webView.getHeight()) - topActionBarOffsetY));
|
webView.setScrollY((int) MathUtils.clamp(newWebScrollY, 0, Math.max(webView.getContentHeight(), webView.getHeight()) - topActionBarOffsetY));
|
||||||
|
|
||||||
if (newWebScrollY < 0) {
|
if (newWebScrollY < 0) {
|
||||||
swipeOffsetY -= newWebScrollY;
|
swipeOffsetY -= newWebScrollY;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
swipeOffsetY -= distanceY;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
swipeOffsetY = swipeOffsetY - distanceY;
|
swipeOffsetY -= distanceY;
|
||||||
|
|
||||||
if (swipeOffsetY < -offsetY + topActionBarOffsetY) {
|
if (webView != null && swipeOffsetY < -offsetY + topActionBarOffsetY) {
|
||||||
float newWebScrollY = webView.getScrollY() - (swipeOffsetY + offsetY - topActionBarOffsetY);
|
float newWebScrollY = webView.getScrollY() - (swipeOffsetY + offsetY - topActionBarOffsetY);
|
||||||
webView.setScrollY((int) MathUtils.clamp(newWebScrollY, 0, Math.max(webView.getContentHeight(), webView.getHeight()) - topActionBarOffsetY));
|
webView.setScrollY((int) MathUtils.clamp(newWebScrollY, 0, Math.max(webView.getContentHeight(), webView.getHeight()) - topActionBarOffsetY));
|
||||||
}
|
}
|
||||||
|
@ -567,6 +602,17 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
updateStickyRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
updateStickyRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStickyRange() {
|
||||||
|
swipeStickyRange = AndroidUtilities.dp(AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? 8 : 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -677,9 +723,9 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert
|
||||||
if (flingInProgress) {
|
if (flingInProgress) {
|
||||||
flingInProgress = false;
|
flingInProgress = false;
|
||||||
} else {
|
} else {
|
||||||
if (swipeOffsetY <= -AndroidUtilities.dp(64)) {
|
if (swipeOffsetY <= -swipeStickyRange) {
|
||||||
stickTo(-offsetY + topActionBarOffsetY);
|
stickTo(-offsetY + topActionBarOffsetY);
|
||||||
} else if (swipeOffsetY > -AndroidUtilities.dp(64) && swipeOffsetY <= AndroidUtilities.dp(64)) {
|
} else if (swipeOffsetY > -swipeStickyRange && swipeOffsetY <= swipeStickyRange) {
|
||||||
stickTo(0);
|
stickTo(0);
|
||||||
} else {
|
} else {
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
|
|
|
@ -69,19 +69,20 @@ public class ChatNotificationsPopupWrapper {
|
||||||
ActionBarMenuSubItem item = ActionBarMenuItem.addItem(windowLayout, R.drawable.msg_mute_period, LocaleController.getString("MuteForPopup", R.string.MuteForPopup), false, resourcesProvider);
|
ActionBarMenuSubItem item = ActionBarMenuItem.addItem(windowLayout, R.drawable.msg_mute_period, LocaleController.getString("MuteForPopup", R.string.MuteForPopup), false, resourcesProvider);
|
||||||
item.setOnClickListener(view -> {
|
item.setOnClickListener(view -> {
|
||||||
dismiss();
|
dismiss();
|
||||||
AlertsCreator.createMuteForPickerDialog(context, (notify, inMinutes) -> {
|
AlertsCreator.createMuteForPickerDialog(context, (notify, inSecond) -> {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
if (inSecond != 0) {
|
||||||
SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount);
|
SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount);
|
||||||
int time1 = sharedPreferences.getInt(LAST_SELECTED_TIME_KEY_1, 0);
|
int time1 = sharedPreferences.getInt(LAST_SELECTED_TIME_KEY_1, 0);
|
||||||
int time2;
|
int time2;
|
||||||
int timeInSeconds = inMinutes * 60;
|
|
||||||
time2 = time1;
|
time2 = time1;
|
||||||
time1 = timeInSeconds;
|
time1 = inSecond;
|
||||||
sharedPreferences.edit()
|
sharedPreferences.edit()
|
||||||
.putInt(LAST_SELECTED_TIME_KEY_1, time1)
|
.putInt(LAST_SELECTED_TIME_KEY_1, time1)
|
||||||
.putInt(LAST_SELECTED_TIME_KEY_2, time2)
|
.putInt(LAST_SELECTED_TIME_KEY_2, time2)
|
||||||
.apply();
|
.apply();
|
||||||
callback.muteFor(timeInSeconds);
|
}
|
||||||
|
callback.muteFor(inSecond);
|
||||||
}, 16);
|
}, 16);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class CrossfadeDrawable extends Drawable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setColorFilter(ColorFilter colorFilter) {
|
public void setColorFilter(ColorFilter colorFilter) {
|
||||||
|
topDrawable.setColorFilter(colorFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -324,7 +324,7 @@ public class MotionBackgroundDrawable extends Drawable {
|
||||||
} else {
|
} else {
|
||||||
gradientDrawable = null;
|
gradientDrawable = null;
|
||||||
}
|
}
|
||||||
if (colors[0] == c1 || colors[1] == c2 || colors[2] == c3 || colors[3] == c4) {
|
if (colors[0] == c1 && colors[1] == c2 && colors[2] == c3 && colors[3] == c4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
colors[0] = c1;
|
colors[0] = c1;
|
||||||
|
|
|
@ -41,6 +41,7 @@ public class PopupSwipeBackLayout extends FrameLayout {
|
||||||
private boolean isSwipeDisallowed;
|
private boolean isSwipeDisallowed;
|
||||||
private Paint overlayPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
private Paint overlayPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
private Paint foregroundPaint = new Paint();
|
private Paint foregroundPaint = new Paint();
|
||||||
|
private int foregroundColor = 0;
|
||||||
|
|
||||||
private Path mPath = new Path();
|
private Path mPath = new Path();
|
||||||
private RectF mRect = new RectF();
|
private RectF mRect = new RectF();
|
||||||
|
@ -128,7 +129,11 @@ public class PopupSwipeBackLayout extends FrameLayout {
|
||||||
int i = indexOfChild(child);
|
int i = indexOfChild(child);
|
||||||
int s = canvas.save();
|
int s = canvas.save();
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
|
if (foregroundColor == 0) {
|
||||||
foregroundPaint.setColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider));
|
foregroundPaint.setColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider));
|
||||||
|
} else {
|
||||||
|
foregroundPaint.setColor(foregroundColor);
|
||||||
|
}
|
||||||
canvas.drawRect(child.getX(), 0, child.getX() + child.getMeasuredWidth(), getMeasuredHeight(), foregroundPaint);
|
canvas.drawRect(child.getX(), 0, child.getX() + child.getMeasuredWidth(), getMeasuredHeight(), foregroundPaint);
|
||||||
}
|
}
|
||||||
boolean b = super.drawChild(canvas, child, drawingTime);
|
boolean b = super.drawChild(canvas, child, drawingTime);
|
||||||
|
@ -444,6 +449,10 @@ public class PopupSwipeBackLayout extends FrameLayout {
|
||||||
foregroundAnimator = animator;
|
foregroundAnimator = animator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setForegroundColor(int color) {
|
||||||
|
foregroundColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
public interface OnSwipeBackProgressListener {
|
public interface OnSwipeBackProgressListener {
|
||||||
void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, float progress);
|
void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, float progress);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,8 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
|
||||||
Runnable lastSearchRunnable;
|
Runnable lastSearchRunnable;
|
||||||
RecyclerItemsEnterAnimator itemsEnterAnimator;
|
RecyclerItemsEnterAnimator itemsEnterAnimator;
|
||||||
|
|
||||||
|
boolean checkingFilesExist;
|
||||||
|
|
||||||
public SearchDownloadsContainer(BaseFragment fragment, int currentAccount) {
|
public SearchDownloadsContainer(BaseFragment fragment, int currentAccount) {
|
||||||
super(fragment.getParentActivity());
|
super(fragment.getParentActivity());
|
||||||
this.parentFragment = fragment;
|
this.parentFragment = fragment;
|
||||||
|
@ -177,7 +179,46 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
|
||||||
recyclerListView.setEmptyView(emptyView);
|
recyclerListView.setEmptyView(emptyView);
|
||||||
|
|
||||||
FileLoader.getInstance(currentAccount).getCurrentLoadingFiles(currentLoadingFiles);
|
FileLoader.getInstance(currentAccount).getCurrentLoadingFiles(currentLoadingFiles);
|
||||||
update(false);
|
}
|
||||||
|
|
||||||
|
private void checkFilesExist() {
|
||||||
|
if (checkingFilesExist) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkingFilesExist = true;
|
||||||
|
Utilities.searchQueue.postRunnable(() -> {
|
||||||
|
ArrayList<MessageObject> currentLoadingFiles = new ArrayList<>();
|
||||||
|
ArrayList<MessageObject> recentLoadingFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
ArrayList<MessageObject> moveToRecent = new ArrayList<>();
|
||||||
|
ArrayList<MessageObject> removeFromRecent = new ArrayList<>();
|
||||||
|
|
||||||
|
FileLoader.getInstance(currentAccount).getCurrentLoadingFiles(currentLoadingFiles);
|
||||||
|
FileLoader.getInstance(currentAccount).getRecentLoadingFiles(recentLoadingFiles);
|
||||||
|
|
||||||
|
for (int i = 0; i < currentLoadingFiles.size(); i++) {
|
||||||
|
if (FileLoader.getPathToMessage(currentLoadingFiles.get(i).messageOwner).exists()) {
|
||||||
|
moveToRecent.add(currentLoadingFiles.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < recentLoadingFiles.size(); i++) {
|
||||||
|
if (!FileLoader.getPathToMessage(recentLoadingFiles.get(i).messageOwner).exists()) {
|
||||||
|
removeFromRecent.add(recentLoadingFiles.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
for (int i = 0; i < moveToRecent.size(); i++) {
|
||||||
|
DownloadController.getInstance(currentAccount).onDownloadComplete(moveToRecent.get(i));
|
||||||
|
}
|
||||||
|
if (!removeFromRecent.isEmpty()) {
|
||||||
|
DownloadController.getInstance(currentAccount).deleteRecentFiles(removeFromRecent);
|
||||||
|
}
|
||||||
|
checkingFilesExist = false;
|
||||||
|
update(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(boolean animated) {
|
public void update(boolean animated) {
|
||||||
|
@ -185,6 +226,10 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
|
||||||
if (rowCount == 0) {
|
if (rowCount == 0) {
|
||||||
itemsEnterAnimator.showItemsAnimated(0);
|
itemsEnterAnimator.showItemsAnimated(0);
|
||||||
}
|
}
|
||||||
|
if (checkingFilesExist) {
|
||||||
|
currentLoadingFilesTmp.clear();
|
||||||
|
recentLoadingFilesTmp.clear();
|
||||||
|
}
|
||||||
FileLoader.getInstance(currentAccount).getCurrentLoadingFiles(currentLoadingFilesTmp);
|
FileLoader.getInstance(currentAccount).getCurrentLoadingFiles(currentLoadingFilesTmp);
|
||||||
FileLoader.getInstance(currentAccount).getRecentLoadingFiles(recentLoadingFilesTmp);
|
FileLoader.getInstance(currentAccount).getRecentLoadingFiles(recentLoadingFilesTmp);
|
||||||
|
|
||||||
|
@ -583,6 +628,8 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
|
||||||
if (getVisibility() == View.VISIBLE) {
|
if (getVisibility() == View.VISIBLE) {
|
||||||
DownloadController.getInstance(currentAccount).clearUnviewedDownloads();
|
DownloadController.getInstance(currentAccount).clearUnviewedDownloads();
|
||||||
}
|
}
|
||||||
|
checkFilesExist();
|
||||||
|
update(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6581,6 +6581,18 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
|
||||||
return newColumnsCount;
|
return newColumnsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||||
|
if (child == fragmentContextView) {
|
||||||
|
canvas.save();
|
||||||
|
canvas.clipRect(0, mediaPages[0].getTop(), child.getMeasuredWidth(),mediaPages[0].getTop() + child.getMeasuredHeight() + AndroidUtilities.dp(12));
|
||||||
|
boolean b = super.drawChild(canvas, child, drawingTime);
|
||||||
|
canvas.restore();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return super.drawChild(canvas, child, drawingTime);
|
||||||
|
}
|
||||||
|
|
||||||
private class ScrollSlidingTextTabStripInner extends ScrollSlidingTextTabStrip {
|
private class ScrollSlidingTextTabStripInner extends ScrollSlidingTextTabStrip {
|
||||||
|
|
||||||
protected Paint backgroundPaint;
|
protected Paint backgroundPaint;
|
||||||
|
|
|
@ -150,8 +150,9 @@ public class TimerDrawable extends Drawable {
|
||||||
currentTtlIcon.setColorFilter(new PorterDuffColorFilter(iconColor, PorterDuff.Mode.MULTIPLY));
|
currentTtlIcon.setColorFilter(new PorterDuffColorFilter(iconColor, PorterDuff.Mode.MULTIPLY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AndroidUtilities.rectTmp2.set(getBounds());
|
AndroidUtilities.rectTmp2.set((int) (getBounds().centerX() - AndroidUtilities.dp(10.5f)), (int) (getBounds().centerY() - AndroidUtilities.dp(10.5f)),
|
||||||
AndroidUtilities.rectTmp2.inset(AndroidUtilities.dp(1f), AndroidUtilities.dp(1f));
|
(int) (getBounds().centerX() - AndroidUtilities.dp(10.5f)) + currentTtlIcon.getIntrinsicWidth(),
|
||||||
|
(int) (getBounds().centerY() - AndroidUtilities.dp(10.5f)) + currentTtlIcon.getIntrinsicHeight());
|
||||||
currentTtlIcon.setBounds(AndroidUtilities.rectTmp2);
|
currentTtlIcon.setBounds(AndroidUtilities.rectTmp2);
|
||||||
currentTtlIcon.draw(canvas);
|
currentTtlIcon.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package org.telegram.ui;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffColorFilter;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
|
@ -34,6 +36,7 @@ public class DownloadProgressIcon extends View implements NotificationCenter.Not
|
||||||
RLottieDrawable downloadCompleteDrawable;
|
RLottieDrawable downloadCompleteDrawable;
|
||||||
boolean showCompletedIcon;
|
boolean showCompletedIcon;
|
||||||
boolean hasUnviewedDownloads;
|
boolean hasUnviewedDownloads;
|
||||||
|
int currentColor;
|
||||||
|
|
||||||
public DownloadProgressIcon(int currentAccount, Context context) {
|
public DownloadProgressIcon(int currentAccount, Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -65,9 +68,13 @@ public class DownloadProgressIcon extends View implements NotificationCenter.Not
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentColor != Theme.getColor(Theme.key_actionBarDefaultIcon)) {
|
||||||
|
currentColor = Theme.getColor(Theme.key_actionBarDefaultIcon);
|
||||||
paint.setColor(Theme.getColor(Theme.key_actionBarDefaultIcon));
|
paint.setColor(Theme.getColor(Theme.key_actionBarDefaultIcon));
|
||||||
paint2.setColor(Theme.getColor(Theme.key_actionBarDefaultIcon));
|
paint2.setColor(Theme.getColor(Theme.key_actionBarDefaultIcon));
|
||||||
|
downloadImageReceiver.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY));
|
||||||
paint2.setAlpha(100);
|
paint2.setAlpha(100);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentProgress != progress) {
|
if (currentProgress != progress) {
|
||||||
currentProgress += progressDt;
|
currentProgress += progressDt;
|
||||||
|
|
|
@ -242,7 +242,11 @@ public class IntroActivity extends BaseFragment implements NotificationCenter.No
|
||||||
Intro.setPage(currentViewPagerPage);
|
Intro.setPage(currentViewPagerPage);
|
||||||
Intro.setDate(time);
|
Intro.setDate(time);
|
||||||
Intro.onDrawFrame(0);
|
Intro.onDrawFrame(0);
|
||||||
|
if (eglThread != null && eglThread.isAlive() && eglThread.eglDisplay != null && eglThread.eglSurface != null) {
|
||||||
|
try {
|
||||||
eglThread.egl10.eglSwapBuffers(eglThread.eglDisplay, eglThread.eglSurface);
|
eglThread.egl10.eglSwapBuffers(eglThread.eglDisplay, eglThread.eglSurface);
|
||||||
|
} catch (Exception ignored) {} // If display or surface already destroyed
|
||||||
|
}
|
||||||
});
|
});
|
||||||
eglThread.postRunnable(eglThread.drawRunnable);
|
eglThread.postRunnable(eglThread.drawRunnable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,12 +275,12 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
try {
|
try {
|
||||||
setTaskDescription(new ActivityManager.TaskDescription(null, null, Theme.getColor(Theme.key_actionBarDefault) | 0xff000000));
|
setTaskDescription(new ActivityManager.TaskDescription(null, null, Theme.getColor(Theme.key_actionBarDefault) | 0xff000000));
|
||||||
} catch (Exception ignore) {
|
} catch (Throwable ignore) {
|
||||||
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
getWindow().setNavigationBarColor(0xff000000);
|
getWindow().setNavigationBarColor(0xff000000);
|
||||||
} catch (Exception ignore) {
|
} catch (Throwable ignore) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2941,6 +2941,8 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar
|
||||||
.setNegativeButton(LocaleController.getString(R.string.Cancel), null)
|
.setNegativeButton(LocaleController.getString(R.string.Cancel), null)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
BulletinFactory.of(mainFragmentsStack.get(mainFragmentsStack.size() - 1)).createErrorBulletin(LocaleController.getString(R.string.BotCantAddToAttachMenu)).show();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4749,8 +4749,8 @@ public class LoginActivity extends BaseFragment {
|
||||||
codeField[a].setPadding(padding, padding, padding, padding);
|
codeField[a].setPadding(padding, padding, padding, padding);
|
||||||
if (stage == 0) {
|
if (stage == 0) {
|
||||||
codeField[a].setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
codeField[a].setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||||
}
|
|
||||||
codeField[a].setTransformationMethod(PasswordTransformationMethod.getInstance());
|
codeField[a].setTransformationMethod(PasswordTransformationMethod.getInstance());
|
||||||
|
}
|
||||||
codeField[a].setTypeface(Typeface.DEFAULT);
|
codeField[a].setTypeface(Typeface.DEFAULT);
|
||||||
codeField[a].setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
codeField[a].setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.ChatObject;
|
import org.telegram.messenger.ChatObject;
|
||||||
import org.telegram.messenger.ContactsController;
|
import org.telegram.messenger.ContactsController;
|
||||||
import org.telegram.messenger.DialogObject;
|
import org.telegram.messenger.DialogObject;
|
||||||
|
import org.telegram.messenger.FileLoader;
|
||||||
import org.telegram.messenger.FileLog;
|
import org.telegram.messenger.FileLog;
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.NotificationCenter;
|
import org.telegram.messenger.NotificationCenter;
|
||||||
|
@ -1247,7 +1248,11 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements
|
||||||
}
|
}
|
||||||
if (documentId != 0) {
|
if (documentId != 0) {
|
||||||
TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId);
|
TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId);
|
||||||
value = NotificationsSoundActivity.trimTitle(document, document.file_name_fixed);
|
if (document == null) {
|
||||||
|
value = LocaleController.getString("CustomSound", R.string.CustomSound);
|
||||||
|
} else {
|
||||||
|
value = NotificationsSoundActivity.trimTitle(document, FileLoader.getDocumentFileName(document));
|
||||||
|
}
|
||||||
} else if (value.equals("NoSound")) {
|
} else if (value.equals("NoSound")) {
|
||||||
value = LocaleController.getString("NoSound", R.string.NoSound);
|
value = LocaleController.getString("NoSound", R.string.NoSound);
|
||||||
} else if (value.equals("Default")) {
|
} else if (value.equals("Default")) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.telegram.ui;
|
package org.telegram.ui;
|
||||||
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
@ -284,9 +283,11 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta
|
||||||
avatarContainer.setTitle(chatLocal.title);
|
avatarContainer.setTitle(chatLocal.title);
|
||||||
} else {
|
} else {
|
||||||
TLRPC.User user = getMessagesController().getUser(dialogId);
|
TLRPC.User user = getMessagesController().getUser(dialogId);
|
||||||
|
if (user != null) {
|
||||||
avatarContainer.setUserAvatar(user);
|
avatarContainer.setUserAvatar(user);
|
||||||
avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
|
avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
avatarContainer.setSubtitle(LocaleController.getString("NotificationsSound", R.string.NotificationsSound));
|
avatarContainer.setSubtitle(LocaleController.getString("NotificationsSound", R.string.NotificationsSound));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +324,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta
|
||||||
}
|
}
|
||||||
if (view instanceof ToneCell) {
|
if (view instanceof ToneCell) {
|
||||||
ToneCell cell = (ToneCell) view;
|
ToneCell cell = (ToneCell) view;
|
||||||
if (actionBar.isActionModeShowed()) {
|
if (actionBar.isActionModeShowed() || cell.tone == null) {
|
||||||
checkSelection(cell.tone);
|
checkSelection(cell.tone);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -357,14 +358,13 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta
|
||||||
lastPlayedRingtone = r;
|
lastPlayedRingtone = r;
|
||||||
r.play();
|
r.play();
|
||||||
} else {
|
} else {
|
||||||
getFileLoader().loadFile(cell.tone.document, null, 2, 0);
|
getFileLoader().loadFile(cell.tone.document, cell.tone.document, 2, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
startSelectedTone = null;
|
startSelectedTone = null;
|
||||||
selectedTone = cell.tone;
|
selectedTone = cell.tone;
|
||||||
selectedToneChanged = true;
|
selectedToneChanged = true;
|
||||||
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
|
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
|
||||||
checkDisabledBySystem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -415,6 +415,9 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta
|
||||||
|
|
||||||
private void loadTones() {
|
private void loadTones() {
|
||||||
getMediaDataController().ringtoneDataStore.loadUserRingtones();
|
getMediaDataController().ringtoneDataStore.loadUserRingtones();
|
||||||
|
serverTones.clear();
|
||||||
|
systemTones.clear();
|
||||||
|
|
||||||
for (int i = 0; i < getMediaDataController().ringtoneDataStore.userRingtones.size(); i++) {
|
for (int i = 0; i < getMediaDataController().ringtoneDataStore.userRingtones.size(); i++) {
|
||||||
RingtoneDataStore.CachedTone cachedTone = getMediaDataController().ringtoneDataStore.userRingtones.get(i);
|
RingtoneDataStore.CachedTone cachedTone = getMediaDataController().ringtoneDataStore.userRingtones.get(i);
|
||||||
Tone tone = new Tone();
|
Tone tone = new Tone();
|
||||||
|
@ -439,7 +442,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta
|
||||||
manager.setType(RingtoneManager.TYPE_NOTIFICATION);
|
manager.setType(RingtoneManager.TYPE_NOTIFICATION);
|
||||||
Cursor cursor = manager.getCursor();
|
Cursor cursor = manager.getCursor();
|
||||||
|
|
||||||
systemTones.clear();
|
|
||||||
|
|
||||||
|
|
||||||
Tone noSoundTone = new Tone();
|
Tone noSoundTone = new Tone();
|
||||||
|
@ -942,15 +945,4 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDisabledBySystem() {
|
|
||||||
NotificationManager manager = (NotificationManager) ApplicationLoader.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
boolean notificationsEnabled = true;
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
notificationsEnabled = manager.areNotificationsEnabled();
|
|
||||||
}
|
|
||||||
// if (!notificationsEnabled) {
|
|
||||||
// BulletinFactory.of(this).createErrorBulletin(LocaleController.getString()).show();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,16 +307,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
private TextView docNameTextView;
|
private TextView docNameTextView;
|
||||||
private TextView docInfoTextView;
|
private TextView docInfoTextView;
|
||||||
private ActionBarMenuItem menuItem;
|
private ActionBarMenuItem menuItem;
|
||||||
private ActionBarMenuItem menuItemSpeed;
|
|
||||||
private ActionBarMenuSubItem allMediaItem;
|
private ActionBarMenuSubItem allMediaItem;
|
||||||
private ActionBarMenuSubItem speedItem;
|
private ActionBarMenuSubItem speedItem;
|
||||||
private ActionBarMenuSubItem[] speedItems = new ActionBarMenuSubItem[5];
|
private ActionBarPopupWindow.GapView speedGap;
|
||||||
private View speedGap;
|
|
||||||
private ActionBarMenuItem sendItem;
|
private ActionBarMenuItem sendItem;
|
||||||
private ActionBarMenuItem pipItem;
|
private ActionBarMenuItem pipItem;
|
||||||
private ActionBarMenuItem masksItem;
|
private ActionBarMenuItem masksItem;
|
||||||
private ActionBarMenuItem shareItem;
|
private ActionBarMenuItem shareItem;
|
||||||
private LinearLayout itemsLayout;
|
private LinearLayout itemsLayout;
|
||||||
|
ChooseSpeedLayout chooseSpeedLayout;
|
||||||
private Map<View, Boolean> actionBarItemsVisibility = new HashMap<>(3);
|
private Map<View, Boolean> actionBarItemsVisibility = new HashMap<>(3);
|
||||||
private LinearLayout bottomButtonsLayout;
|
private LinearLayout bottomButtonsLayout;
|
||||||
private ImageView shareButton;
|
private ImageView shareButton;
|
||||||
|
@ -412,7 +411,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (videoPlayerControlVisible && isPlaying && !ApplicationLoader.mainInterfacePaused) {
|
if (videoPlayerControlVisible && isPlaying && !ApplicationLoader.mainInterfacePaused) {
|
||||||
if (menuItem != null && menuItem.isSubMenuShowing() || menuItemSpeed != null && menuItemSpeed.isSubMenuShowing()) {
|
if (menuItem != null && menuItem.isSubMenuShowing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (captionScrollView != null && captionScrollView.getScrollY() != 0) {
|
if (captionScrollView != null && captionScrollView.getScrollY() != 0) {
|
||||||
|
@ -1204,12 +1203,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
private final static int gallery_menu_edit_avatar = 17;
|
private final static int gallery_menu_edit_avatar = 17;
|
||||||
private final static int gallery_menu_share2 = 18;
|
private final static int gallery_menu_share2 = 18;
|
||||||
private final static int gallery_menu_speed = 19;
|
private final static int gallery_menu_speed = 19;
|
||||||
private final static int gallery_menu_gap = 20;
|
|
||||||
private final static int gallery_menu_speed_veryslow = 21;
|
|
||||||
private final static int gallery_menu_speed_slow = 22;
|
|
||||||
private final static int gallery_menu_speed_normal = 23;
|
|
||||||
private final static int gallery_menu_speed_fast = 24;
|
|
||||||
private final static int gallery_menu_speed_veryfast = 25;
|
|
||||||
|
|
||||||
private static DecelerateInterpolator decelerateInterpolator;
|
private static DecelerateInterpolator decelerateInterpolator;
|
||||||
private static Paint progressPaint;
|
private static Paint progressPaint;
|
||||||
|
@ -4189,20 +4182,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
}
|
}
|
||||||
} else if (id == gallery_menu_share || id == gallery_menu_share2) {
|
} else if (id == gallery_menu_share || id == gallery_menu_share2) {
|
||||||
onSharePressed();
|
onSharePressed();
|
||||||
} else if (id == gallery_menu_speed) {
|
|
||||||
menuItemSpeed.setVisibility(View.VISIBLE);
|
|
||||||
menuItemSpeed.toggleSubMenu();
|
|
||||||
for (int a = 0; a < speedItems.length; a++) {
|
|
||||||
if (a == 0 && Math.abs(currentVideoSpeed - 0.25f) < 0.001f ||
|
|
||||||
a == 1 && Math.abs(currentVideoSpeed - 0.5f) < 0.001f ||
|
|
||||||
a == 2 && Math.abs(currentVideoSpeed - 1.0f) < 0.001f ||
|
|
||||||
a == 3 && Math.abs(currentVideoSpeed - 1.5f) < 0.001f ||
|
|
||||||
a == 4 && Math.abs(currentVideoSpeed - 2.0f) < 0.001f) {
|
|
||||||
speedItems[a].setColors(0xff6BB6F9, 0xff6BB6F9);
|
|
||||||
} else {
|
|
||||||
speedItems[a].setColors(0xfffafafa, 0xfffafafa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (id == gallery_menu_openin) {
|
} else if (id == gallery_menu_openin) {
|
||||||
try {
|
try {
|
||||||
if (isEmbedVideo) {
|
if (isEmbedVideo) {
|
||||||
|
@ -4403,7 +4382,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canOpenMenu() {
|
public boolean canOpenMenu() {
|
||||||
menuItemSpeed.setVisibility(View.INVISIBLE);
|
|
||||||
if (currentMessageObject != null || currentSecureDocument != null) {
|
if (currentMessageObject != null || currentSecureDocument != null) {
|
||||||
return true;
|
return true;
|
||||||
} else if (currentFileLocationVideo != null) {
|
} else if (currentFileLocationVideo != null) {
|
||||||
|
@ -4428,26 +4406,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
shareItem.setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile));
|
shareItem.setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile));
|
||||||
|
|
||||||
menuItem = menu.addItem(0, R.drawable.ic_ab_other);
|
menuItem = menu.addItem(0, R.drawable.ic_ab_other);
|
||||||
menuItemSpeed = new ActionBarMenuItem(parentActivity, null, 0, 0, resourcesProvider);
|
|
||||||
menuItemSpeed.setDelegate(id -> {
|
menuItem.getPopupLayout().swipeBackGravityRight = true;
|
||||||
if (id >= gallery_menu_speed_veryslow && id <= gallery_menu_speed_veryfast) {
|
chooseSpeedLayout = new ChooseSpeedLayout(activityContext, menuItem.getPopupLayout().getSwipeBack(), new ChooseSpeedLayout.Callback() {
|
||||||
switch (id) {
|
|
||||||
case gallery_menu_speed_veryslow:
|
@Override
|
||||||
currentVideoSpeed = 0.25f;
|
public void onSpeedSelected(float speed) {
|
||||||
break;
|
menuItem.toggleSubMenu();
|
||||||
case gallery_menu_speed_slow:
|
if (speed != currentVideoSpeed) {
|
||||||
currentVideoSpeed = 0.5f;
|
currentVideoSpeed = speed;
|
||||||
break;
|
|
||||||
case gallery_menu_speed_normal:
|
|
||||||
currentVideoSpeed = 1.0f;
|
|
||||||
break;
|
|
||||||
case gallery_menu_speed_fast:
|
|
||||||
currentVideoSpeed = 1.5f;
|
|
||||||
break;
|
|
||||||
case gallery_menu_speed_veryfast:
|
|
||||||
currentVideoSpeed = 2.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (currentMessageObject != null) {
|
if (currentMessageObject != null) {
|
||||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("playback_speed", Activity.MODE_PRIVATE);
|
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("playback_speed", Activity.MODE_PRIVATE);
|
||||||
if (Math.abs(currentVideoSpeed - 1.0f) < 0.001f) {
|
if (Math.abs(currentVideoSpeed - 1.0f) < 0.001f) {
|
||||||
|
@ -4463,27 +4430,17 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
photoViewerWebView.setPlaybackSpeed(currentVideoSpeed);
|
photoViewerWebView.setPlaybackSpeed(currentVideoSpeed);
|
||||||
}
|
}
|
||||||
setMenuItemIcon();
|
setMenuItemIcon();
|
||||||
menuItemSpeed.setVisibility(View.INVISIBLE);
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menuItem.addView(menuItemSpeed);
|
speedItem = menuItem.addSwipeBackItem(R.drawable.msg_speed, null, LocaleController.getString("Speed", R.string.Speed), chooseSpeedLayout.speedSwipeBackLayout);
|
||||||
menuItemSpeed.setVisibility(View.INVISIBLE);
|
menuItem.getPopupLayout().setSwipeBackForegroundColor(0xff222222);
|
||||||
|
|
||||||
speedItem = menuItem.addSubItem(gallery_menu_speed, R.drawable.msg_speed, null, LocaleController.getString("Speed", R.string.Speed), true, false);
|
|
||||||
speedItem.setSubtext(LocaleController.getString("SpeedNormal", R.string.SpeedNormal));
|
speedItem.setSubtext(LocaleController.getString("SpeedNormal", R.string.SpeedNormal));
|
||||||
speedItem.setItemHeight(56);
|
|
||||||
speedItem.setTag(R.id.width_tag, 240);
|
|
||||||
speedItem.setColors(0xfffafafa, 0xfffafafa);
|
speedItem.setColors(0xfffafafa, 0xfffafafa);
|
||||||
speedItem.setRightIcon(R.drawable.msg_arrowright);
|
speedGap = menuItem.addColoredGap();
|
||||||
speedGap = menuItem.addGap(gallery_menu_gap);
|
speedGap.setColor(0xff181818);
|
||||||
menuItem.getPopupLayout().setFitItems(true);
|
menuItem.getPopupLayout().setFitItems(true);
|
||||||
|
|
||||||
speedItems[0] = menuItemSpeed.addSubItem(gallery_menu_speed_veryslow, R.drawable.msg_speed_0_2, LocaleController.getString("SpeedVerySlow", R.string.SpeedVerySlow)).setColors(0xfffafafa, 0xfffafafa);
|
|
||||||
speedItems[1] = menuItemSpeed.addSubItem(gallery_menu_speed_slow, R.drawable.msg_speed_0_5, LocaleController.getString("SpeedSlow", R.string.SpeedSlow)).setColors(0xfffafafa, 0xfffafafa);
|
|
||||||
speedItems[2] = menuItemSpeed.addSubItem(gallery_menu_speed_normal, R.drawable.msg_speed_1, LocaleController.getString("SpeedNormal", R.string.SpeedNormal)).setColors(0xfffafafa, 0xfffafafa);
|
|
||||||
speedItems[3] = menuItemSpeed.addSubItem(gallery_menu_speed_fast, R.drawable.msg_speed_1_5, LocaleController.getString("SpeedFast", R.string.SpeedFast)).setColors(0xfffafafa, 0xfffafafa);
|
|
||||||
speedItems[4] = menuItemSpeed.addSubItem(gallery_menu_speed_veryfast, R.drawable.msg_speed_2, LocaleController.getString("SpeedVeryFast", R.string.SpeedVeryFast)).setColors(0xfffafafa, 0xfffafafa);
|
|
||||||
|
|
||||||
menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa);
|
menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa);
|
||||||
menuItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions));
|
menuItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions));
|
||||||
allMediaItem = menuItem.addSubItem(gallery_menu_showall, R.drawable.msg_media, LocaleController.getString("ShowAllMedia", R.string.ShowAllMedia));
|
allMediaItem = menuItem.addSubItem(gallery_menu_showall, R.drawable.msg_media, LocaleController.getString("ShowAllMedia", R.string.ShowAllMedia));
|
||||||
|
@ -4498,7 +4455,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
menuItem.addSubItem(gallery_menu_delete, R.drawable.msg_delete, LocaleController.getString("Delete", R.string.Delete)).setColors(0xfffafafa, 0xfffafafa);
|
menuItem.addSubItem(gallery_menu_delete, R.drawable.msg_delete, LocaleController.getString("Delete", R.string.Delete)).setColors(0xfffafafa, 0xfffafafa);
|
||||||
menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.msg_cancel, LocaleController.getString("StopDownload", R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa);
|
menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.msg_cancel, LocaleController.getString("StopDownload", R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa);
|
||||||
menuItem.redrawPopup(0xf9222222);
|
menuItem.redrawPopup(0xf9222222);
|
||||||
menuItemSpeed.redrawPopup(0xf9222222);
|
|
||||||
setMenuItemIcon();
|
setMenuItemIcon();
|
||||||
|
|
||||||
menuItem.setSubMenuDelegate(new ActionBarMenuItem.ActionBarSubMenuItemDelegate() {
|
menuItem.setSubMenuDelegate(new ActionBarMenuItem.ActionBarSubMenuItemDelegate() {
|
||||||
|
@ -6161,6 +6117,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
menuItem.setIcon(R.drawable.msg_more_2);
|
menuItem.setIcon(R.drawable.msg_more_2);
|
||||||
speedItem.setSubtext(LocaleController.getString("SpeedVeryFast", R.string.SpeedVeryFast));
|
speedItem.setSubtext(LocaleController.getString("SpeedVeryFast", R.string.SpeedVeryFast));
|
||||||
}
|
}
|
||||||
|
chooseSpeedLayout.update(currentVideoSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkInlinePermissions() {
|
private boolean checkInlinePermissions() {
|
||||||
|
@ -9976,7 +9933,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
menuItem.hideSubItem(gallery_menu_edit_avatar);
|
menuItem.hideSubItem(gallery_menu_edit_avatar);
|
||||||
menuItem.hideSubItem(gallery_menu_set_as_main);
|
menuItem.hideSubItem(gallery_menu_set_as_main);
|
||||||
menuItem.hideSubItem(gallery_menu_delete);
|
menuItem.hideSubItem(gallery_menu_delete);
|
||||||
menuItem.hideSubItem(gallery_menu_speed);
|
speedItem.setVisibility(View.GONE);
|
||||||
speedGap.setVisibility(View.GONE);
|
speedGap.setVisibility(View.GONE);
|
||||||
actionBar.setTranslationY(0);
|
actionBar.setTranslationY(0);
|
||||||
|
|
||||||
|
@ -10398,6 +10355,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
}
|
}
|
||||||
menuItem.checkHideMenuItem();
|
menuItem.checkHideMenuItem();
|
||||||
} else {
|
} else {
|
||||||
|
speedItem.setVisibility(View.GONE);
|
||||||
speedGap.setVisibility(View.GONE);
|
speedGap.setVisibility(View.GONE);
|
||||||
menuItem.hideSubItem(gallery_menu_openin);
|
menuItem.hideSubItem(gallery_menu_openin);
|
||||||
menuItem.checkHideMenuItem();
|
menuItem.checkHideMenuItem();
|
||||||
|
@ -10989,10 +10947,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isVideo || isEmbedVideo) {
|
if (isVideo || isEmbedVideo) {
|
||||||
|
speedItem.setVisibility(View.VISIBLE);
|
||||||
speedGap.setVisibility(View.VISIBLE);
|
speedGap.setVisibility(View.VISIBLE);
|
||||||
menuItem.showSubItem(gallery_menu_speed);
|
menuItem.showSubItem(gallery_menu_speed);
|
||||||
} else {
|
} else {
|
||||||
menuItem.hideSubItem(gallery_menu_speed);
|
speedItem.setVisibility(View.GONE);
|
||||||
speedGap.setVisibility(View.GONE);
|
speedGap.setVisibility(View.GONE);
|
||||||
menuItem.checkHideMenuItem();
|
menuItem.checkHideMenuItem();
|
||||||
}
|
}
|
||||||
|
@ -11453,7 +11412,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||||
Theme.createChatResources(null, true);
|
Theme.createChatResources(null, true);
|
||||||
CharSequence str;
|
CharSequence str;
|
||||||
if (messageObject != null && !messageObject.messageOwner.entities.isEmpty()) {
|
if (messageObject != null && !messageObject.messageOwner.entities.isEmpty()) {
|
||||||
Spannable spannableString = SpannableString.valueOf(caption);
|
Spannable spannableString = new SpannableString(caption);
|
||||||
messageObject.addEntitiesToText(spannableString, true, false);
|
messageObject.addEntitiesToText(spannableString, true, false);
|
||||||
if (messageObject.isVideo()) {
|
if (messageObject.isVideo()) {
|
||||||
MessageObject.addUrlsByPattern(messageObject.isOutOwner(), spannableString, false, 3, messageObject.getDuration(), false);
|
MessageObject.addUrlsByPattern(messageObject.isOutOwner(), spannableString, false, 3, messageObject.getDuration(), false);
|
||||||
|
|
|
@ -60,6 +60,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.view.animation.AccelerateInterpolator;
|
import android.view.animation.AccelerateInterpolator;
|
||||||
import android.view.animation.DecelerateInterpolator;
|
import android.view.animation.DecelerateInterpolator;
|
||||||
import android.webkit.WebStorage;
|
import android.webkit.WebStorage;
|
||||||
|
import android.webkit.WebView;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -1525,6 +1526,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
||||||
}
|
}
|
||||||
return super.onTouchEvent(event);
|
return super.onTouchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItemsColor(int color, boolean isActionMode) {
|
||||||
|
super.setItemsColor(color, isActionMode);
|
||||||
|
if (!isActionMode && ttlIconView != null) {
|
||||||
|
ttlIconView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
actionBar.setBackgroundColor(Color.TRANSPARENT);
|
actionBar.setBackgroundColor(Color.TRANSPARENT);
|
||||||
actionBar.setItemsBackgroundColor(AvatarDrawable.getButtonColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId), false);
|
actionBar.setItemsBackgroundColor(AvatarDrawable.getButtonColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId), false);
|
||||||
|
@ -2432,6 +2441,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
||||||
editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit));
|
editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit));
|
||||||
otherItem = menu.addItem(10, R.drawable.ic_ab_other);
|
otherItem = menu.addItem(10, R.drawable.ic_ab_other);
|
||||||
ttlIconView = new ImageView(context);
|
ttlIconView = new ImageView(context);
|
||||||
|
ttlIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY));
|
||||||
AndroidUtilities.updateViewVisibilityAnimated(ttlIconView, false, 0.8f, false);
|
AndroidUtilities.updateViewVisibilityAnimated(ttlIconView, false, 0.8f, false);
|
||||||
ttlIconView.setImageResource(R.drawable.msg_mini_autodelete_timer);
|
ttlIconView.setImageResource(R.drawable.msg_mini_autodelete_timer);
|
||||||
otherItem.addView(ttlIconView, LayoutHelper.createFrame(12, 12, Gravity.CENTER_VERTICAL | Gravity.LEFT, 8, 2, 0, 0));
|
otherItem.addView(ttlIconView, LayoutHelper.createFrame(12, 12, Gravity.CENTER_VERTICAL | Gravity.LEFT, 8, 2, 0, 0));
|
||||||
|
@ -2729,6 +2739,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void muteFor(int timeInSeconds) {
|
public void muteFor(int timeInSeconds) {
|
||||||
|
if (timeInSeconds == 0) {
|
||||||
|
if (getMessagesController().isDialogMuted(did)) {
|
||||||
|
toggleMute();
|
||||||
|
}
|
||||||
|
if (BulletinFactory.canShowBulletin(ProfileActivity.this)) {
|
||||||
|
BulletinFactory.createMuteBulletin(ProfileActivity.this, NotificationsController.SETTING_MUTE_UNMUTE, timeInSeconds, getResourceProvider()).show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
getNotificationsController().muteUntil(did, timeInSeconds);
|
getNotificationsController().muteUntil(did, timeInSeconds);
|
||||||
if (BulletinFactory.canShowBulletin(ProfileActivity.this)) {
|
if (BulletinFactory.canShowBulletin(ProfileActivity.this)) {
|
||||||
BulletinFactory.createMuteBulletin(ProfileActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show();
|
BulletinFactory.createMuteBulletin(ProfileActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show();
|
||||||
|
@ -2737,6 +2755,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
||||||
listAdapter.notifyItemChanged(notificationsRow);
|
listAdapter.notifyItemChanged(notificationsRow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showCustomize() {
|
public void showCustomize() {
|
||||||
|
@ -2919,7 +2938,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
||||||
BuildVars.DEBUG_PRIVATE_VERSION ? "Clean app update" : null,
|
BuildVars.DEBUG_PRIVATE_VERSION ? "Clean app update" : null,
|
||||||
BuildVars.DEBUG_PRIVATE_VERSION ? "Reset suggestions" : null,
|
BuildVars.DEBUG_PRIVATE_VERSION ? "Reset suggestions" : null,
|
||||||
BuildVars.DEBUG_PRIVATE_VERSION ? LocaleController.getString(SharedConfig.forceRtmpStream ? R.string.DebugMenuDisableForceRtmpStreamFlag : R.string.DebugMenuEnableForceRtmpStreamFlag) : null,
|
BuildVars.DEBUG_PRIVATE_VERSION ? LocaleController.getString(SharedConfig.forceRtmpStream ? R.string.DebugMenuDisableForceRtmpStreamFlag : R.string.DebugMenuEnableForceRtmpStreamFlag) : null,
|
||||||
BuildVars.DEBUG_PRIVATE_VERSION ? LocaleController.getString(R.string.DebugMenuClearWebViewCache) : null
|
BuildVars.DEBUG_PRIVATE_VERSION ? LocaleController.getString(R.string.DebugMenuClearWebViewCache) : null,
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? LocaleController.getString(R.string.DebugMenuEnableWebViewDebug) : null
|
||||||
};
|
};
|
||||||
builder.setItems(items, (dialog, which) -> {
|
builder.setItems(items, (dialog, which) -> {
|
||||||
if (which == 0) {
|
if (which == 0) {
|
||||||
|
@ -2996,6 +3016,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
||||||
ApplicationLoader.applicationContext.deleteDatabase("webview.db");
|
ApplicationLoader.applicationContext.deleteDatabase("webview.db");
|
||||||
ApplicationLoader.applicationContext.deleteDatabase("webviewCache.db");
|
ApplicationLoader.applicationContext.deleteDatabase("webviewCache.db");
|
||||||
WebStorage.getInstance().deleteAllData();
|
WebStorage.getInstance().deleteAllData();
|
||||||
|
} else if (which == 19) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
WebView.setWebContentsDebuggingEnabled(true);
|
||||||
|
Toast.makeText(getParentActivity(), LocaleController.getString(R.string.DebugMenuWebViewDebugEnabled), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||||
|
|
|
@ -504,7 +504,11 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi
|
||||||
@Override
|
@Override
|
||||||
public void didReceivedNotification(int id, int account, Object... args) {
|
public void didReceivedNotification(int id, int account, Object... args) {
|
||||||
if (id == NotificationCenter.notificationsSettingsUpdated) {
|
if (id == NotificationCenter.notificationsSettingsUpdated) {
|
||||||
|
try {
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,8 +524,13 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi
|
||||||
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.getChildViewHolder(child);
|
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.getChildViewHolder(child);
|
||||||
int type = holder.getItemViewType();
|
int type = holder.getItemViewType();
|
||||||
int position = holder.getAdapterPosition();
|
int position = holder.getAdapterPosition();
|
||||||
if (position != customRow && position != enableRow && type != 0) {
|
if (position != customRow && position != enableRow) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case 0: {
|
||||||
|
HeaderCell textCell = (HeaderCell) holder.itemView;
|
||||||
|
textCell.setEnabled(customEnabled && notificationsEnabled, animators);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
TextSettingsCell textCell = (TextSettingsCell) holder.itemView;
|
TextSettingsCell textCell = (TextSettingsCell) holder.itemView;
|
||||||
textCell.setEnabled(customEnabled && notificationsEnabled, animators);
|
textCell.setEnabled(customEnabled && notificationsEnabled, animators);
|
||||||
|
@ -681,7 +690,11 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi
|
||||||
long documentId = preferences.getLong("sound_document_id_" + dialogId, 0);
|
long documentId = preferences.getLong("sound_document_id_" + dialogId, 0);
|
||||||
if (documentId != 0) {
|
if (documentId != 0) {
|
||||||
TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId);
|
TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId);
|
||||||
|
if (document == null) {
|
||||||
|
value = LocaleController.getString("CustomSound", R.string.CustomSound);
|
||||||
|
} else {
|
||||||
value = NotificationsSoundActivity.trimTitle(document, document.file_name_fixed);
|
value = NotificationsSoundActivity.trimTitle(document, document.file_name_fixed);
|
||||||
|
}
|
||||||
} else if (value.equals("NoSound")) {
|
} else if (value.equals("NoSound")) {
|
||||||
value = LocaleController.getString("NoSound", R.string.NoSound);
|
value = LocaleController.getString("NoSound", R.string.NoSound);
|
||||||
} else if (value.equals("Default")) {
|
} else if (value.equals("Default")) {
|
||||||
|
@ -840,8 +853,12 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
|
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
|
||||||
if (holder.getItemViewType() != 0) {
|
|
||||||
switch (holder.getItemViewType()) {
|
switch (holder.getItemViewType()) {
|
||||||
|
case 0: {
|
||||||
|
HeaderCell textCell = (HeaderCell) holder.itemView;
|
||||||
|
textCell.setEnabled(customEnabled && notificationsEnabled, null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
TextSettingsCell textCell = (TextSettingsCell) holder.itemView;
|
TextSettingsCell textCell = (TextSettingsCell) holder.itemView;
|
||||||
textCell.setEnabled(customEnabled && notificationsEnabled, null);
|
textCell.setEnabled(customEnabled && notificationsEnabled, null);
|
||||||
|
@ -872,7 +889,6 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
|
|
|
@ -904,11 +904,6 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
|
||||||
colors[6] = 0x212020;
|
colors[6] = 0x212020;
|
||||||
colors[7] = Theme.getColor(Theme.key_windowBackgroundWhite);
|
colors[7] = Theme.getColor(Theme.key_windowBackgroundWhite);
|
||||||
|
|
||||||
// imageView.replaceColors(colors);
|
|
||||||
// imageView.setAnimation(R.raw.qr_login, 230, 230, colors);
|
|
||||||
// imageView.setScaleType(ImageView.ScaleType.CENTER);
|
|
||||||
// imageView.playAnimation();
|
|
||||||
|
|
||||||
textView = new TextView(context);
|
textView = new TextView(context);
|
||||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 36, 152, 36, 0));
|
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 36, 152, 36, 0));
|
||||||
textView.setGravity(Gravity.CENTER_HORIZONTAL);
|
textView.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
|
|
Before Width: | Height: | Size: 755 B After Width: | Height: | Size: 898 B |
Before Width: | Height: | Size: 638 B After Width: | Height: | Size: 809 B |
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 444 B After Width: | Height: | Size: 532 B |
Before Width: | Height: | Size: 984 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 829 B After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.4 KiB |
|
@ -186,6 +186,7 @@
|
||||||
<string name="AutoDelete1Hour">1 hour</string>
|
<string name="AutoDelete1Hour">1 hour</string>
|
||||||
<string name="AutoDeleteInfo">Automatically delete new messages sent in this chat after a certain period of time.</string>
|
<string name="AutoDeleteInfo">Automatically delete new messages sent in this chat after a certain period of time.</string>
|
||||||
<string name="AutoDeleteNever">Never</string>
|
<string name="AutoDeleteNever">Never</string>
|
||||||
|
<string name="MuteNever">Never</string>
|
||||||
<string name="AutoDeleteSet">Set for this chat</string>
|
<string name="AutoDeleteSet">Set for this chat</string>
|
||||||
<string name="AutoDeleteSetInfo">Messages in this chat are automatically\ndeleted %1$s after they are sent.</string>
|
<string name="AutoDeleteSetInfo">Messages in this chat are automatically\ndeleted %1$s after they are sent.</string>
|
||||||
<string name="AutoDeleteHintOnText">New messages in this chat will be automatically deleted in %1$s.</string>
|
<string name="AutoDeleteHintOnText">New messages in this chat will be automatically deleted in %1$s.</string>
|
||||||
|
@ -230,7 +231,7 @@
|
||||||
<string name="CompatibilityChat">%1$s is using an older version of Telegram, so secret photos will be shown in compatibility mode.\n\nOnce %2$s updates Telegram, photos with timers for 1 minute or less will start working in \'Tap and hold to view\' mode, and you will be notified whenever the other party takes a screenshot.</string>
|
<string name="CompatibilityChat">%1$s is using an older version of Telegram, so secret photos will be shown in compatibility mode.\n\nOnce %2$s updates Telegram, photos with timers for 1 minute or less will start working in \'Tap and hold to view\' mode, and you will be notified whenever the other party takes a screenshot.</string>
|
||||||
<string name="SearchMessages">Messages</string>
|
<string name="SearchMessages">Messages</string>
|
||||||
<string name="Search">Search</string>
|
<string name="Search">Search</string>
|
||||||
<string name="MuteNotifications">Mute notifications</string>
|
<string name="MuteNotifications">Mute forever</string>
|
||||||
<string name="MuteFor">Mute for %1$s</string>
|
<string name="MuteFor">Mute for %1$s</string>
|
||||||
<string name="MuteFor1h">Mute for 1 hour</string>
|
<string name="MuteFor1h">Mute for 1 hour</string>
|
||||||
<string name="UnmuteNotifications">Unmute</string>
|
<string name="UnmuteNotifications">Unmute</string>
|
||||||
|
@ -2150,6 +2151,8 @@
|
||||||
<string name="DebugMenuEnableForceRtmpStreamFlag">Enable forced RTMP Stream Flag</string>
|
<string name="DebugMenuEnableForceRtmpStreamFlag">Enable forced RTMP Stream Flag</string>
|
||||||
<string name="DebugMenuDisableForceRtmpStreamFlag">Disable forced RTMP Stream Flag</string>
|
<string name="DebugMenuDisableForceRtmpStreamFlag">Disable forced RTMP Stream Flag</string>
|
||||||
<string name="DebugMenuClearWebViewCache">Clear WebView cache</string>
|
<string name="DebugMenuClearWebViewCache">Clear WebView cache</string>
|
||||||
|
<string name="DebugMenuEnableWebViewDebug">Enable WebView debug</string>
|
||||||
|
<string name="DebugMenuWebViewDebugEnabled">Debug enabled!</string>
|
||||||
<string name="ChangeLanguageLater">You can change your language later in Settings.</string>
|
<string name="ChangeLanguageLater">You can change your language later in Settings.</string>
|
||||||
<string name="ChooseYourLanguage">Choose your language</string>
|
<string name="ChooseYourLanguage">Choose your language</string>
|
||||||
<string name="ChooseYourLanguageOther">Other</string>
|
<string name="ChooseYourLanguageOther">Other</string>
|
||||||
|
@ -3335,6 +3338,7 @@
|
||||||
<string name="UserChannelTooMuchJoin">Sorry, the target user is a member of too many groups and channels. Please ask them to leave some first.</string>
|
<string name="UserChannelTooMuchJoin">Sorry, the target user is a member of too many groups and channels. Please ask them to leave some first.</string>
|
||||||
<!--Alert messages-->
|
<!--Alert messages-->
|
||||||
<string name="DeleteAllMessagesAlert">Warning! This will **delete all messages** in this chat for **both** participants.</string>
|
<string name="DeleteAllMessagesAlert">Warning! This will **delete all messages** in this chat for **both** participants.</string>
|
||||||
|
<string name="DeleteAllMessagesChannelAlert">Warning! This will **delete all messages** in this channel.</string>
|
||||||
<string name="DeleteAllMessagesSavedAlert">Warning! This will **delete all messages** in this chat.</string>
|
<string name="DeleteAllMessagesSavedAlert">Warning! This will **delete all messages** in this chat.</string>
|
||||||
<string name="DeleteAll">Delete All</string>
|
<string name="DeleteAll">Delete All</string>
|
||||||
<string name="StopLoading">Stop loading?</string>
|
<string name="StopLoading">Stop loading?</string>
|
||||||
|
@ -3406,7 +3410,8 @@
|
||||||
<string name="StopVerification">Do you want to stop the verification process?</string>
|
<string name="StopVerification">Do you want to stop the verification process?</string>
|
||||||
<string name="AreYouSureClearHistoryWithUser">Are you sure you want to clear your chat history with **%1$s**?</string>
|
<string name="AreYouSureClearHistoryWithUser">Are you sure you want to clear your chat history with **%1$s**?</string>
|
||||||
<string name="AreYouSureClearHistoryWithSecretUser">Are you sure you want to clear your secret chat history with **%1$s**?</string>
|
<string name="AreYouSureClearHistoryWithSecretUser">Are you sure you want to clear your secret chat history with **%1$s**?</string>
|
||||||
<string name="AreYouSureClearHistoryWithChat">Are you sure you want to clear the chat history in **%1$s**?</string>
|
<string name="AreYouSureClearHistoryWithChat">Are you sure you want to clear the chat history in **%1$s** for all users?</string>
|
||||||
|
<string name="AreYouSureClearHistoryWithChannel">Are you sure you want to clear the channel history in **%1$s**?</string>
|
||||||
<string name="AreYouSureClearHistory">Are you sure you want to delete all messages in this chat?</string>
|
<string name="AreYouSureClearHistory">Are you sure you want to delete all messages in this chat?</string>
|
||||||
<string name="AreYouSureClearHistorySavedMessages">Are you sure you want to clear **Saved Messages**?</string>
|
<string name="AreYouSureClearHistorySavedMessages">Are you sure you want to clear **Saved Messages**?</string>
|
||||||
<string name="AreYouSureClearHistoryChannel">Delete all cached text and media from this channel?</string>
|
<string name="AreYouSureClearHistoryChannel">Delete all cached text and media from this channel?</string>
|
||||||
|
@ -5067,38 +5072,38 @@
|
||||||
<string name="NobodyViewed">Nobody viewed</string>
|
<string name="NobodyViewed">Nobody viewed</string>
|
||||||
<string name="QrCode">QR Code</string>
|
<string name="QrCode">QR Code</string>
|
||||||
|
|
||||||
<string name="PushReactText">%1$s: %2$s to your "%3$s"</string>
|
<string name="PushReactText">%2$s to your "%3$s"</string>
|
||||||
<string name="PushReactNoText">%1$s: %2$s to your message</string>
|
<string name="PushReactNoText">%2$s to your message</string>
|
||||||
<string name="PushReactPhoto">%1$s: %2$s to your photo</string>
|
<string name="PushReactPhoto">%2$s to your photo</string>
|
||||||
<string name="PushReactVideo">%1$s: %2$s to your video</string>
|
<string name="PushReactVideo">%2$s to your video</string>
|
||||||
<string name="PushReactRound">%1$s: %2$s to your video message</string>
|
<string name="PushReactRound">%2$s to your video message</string>
|
||||||
<string name="PushReactDoc">%1$s: %2$s to your file</string>
|
<string name="PushReactDoc">%2$s to your file</string>
|
||||||
<string name="PushReactSticker">%1$s: %2$s to your %3$s sticker</string>
|
<string name="PushReactSticker">%2$s to your %3$s sticker</string>
|
||||||
<string name="PushReactAudio">%1$s: %2$s to your voice message</string>
|
<string name="PushReactAudio">%2$s to your voice message</string>
|
||||||
<string name="PushReactContect">%1$s: %2$s to your contact %3$s</string>
|
<string name="PushReactContect">%2$s to your contact %3$s</string>
|
||||||
<string name="PushReactGeo">%1$s: %2$s to your map</string>
|
<string name="PushReactGeo">%2$s to your map</string>
|
||||||
<string name="PushReactGeoLocation">%1$s: %2$s to your live location</string>
|
<string name="PushReactGeoLocation">%2$s to your live location</string>
|
||||||
<string name="PushReactPoll">%1$s: %2$s to your poll %3$s</string>
|
<string name="PushReactPoll">%2$s to your poll %3$s</string>
|
||||||
<string name="PushReactQuiz">%1$s: %2$s to your quiz %3$s</string>
|
<string name="PushReactQuiz">%2$s to your quiz %3$s</string>
|
||||||
<string name="PushReactGame">%1$s: %2$s to your game</string>
|
<string name="PushReactGame">%2$s to your game</string>
|
||||||
<string name="PushReactInvoice">%1$s: %2$s to your invoice</string>
|
<string name="PushReactInvoice">%2$s to your invoice</string>
|
||||||
<string name="PushReactGif">%1$s: %2$s to your GIF</string>
|
<string name="PushReactGif">%2$s to your GIF</string>
|
||||||
<string name="PushChatReactText">%1$s: %3$s in %2$s to your "%4$s"</string>
|
<string name="PushChatReactText">%3$s in %2$s to your "%4$s"</string>
|
||||||
<string name="PushChatReactNotext">%1$s: %3$s to your message in %2$s</string>
|
<string name="PushChatReactNotext">%3$s to your message in %2$s</string>
|
||||||
<string name="PushChatReactPhoto">%1$s: %3$s to your photo in %2$s</string>
|
<string name="PushChatReactPhoto">%3$s to your photo in %2$s</string>
|
||||||
<string name="PushChatReactVideo">%1$s: %3$s to your video in %2$s</string>
|
<string name="PushChatReactVideo">%3$s to your video in %2$s</string>
|
||||||
<string name="PushChatReactRound">%1$s: %3$s to your video message in %2$s</string>
|
<string name="PushChatReactRound">%3$s to your video message in %2$s</string>
|
||||||
<string name="PushChatReactDoc">%1$s: %3$s to your file in %2$s</string>
|
<string name="PushChatReactDoc">%3$s to your file in %2$s</string>
|
||||||
<string name="PushChatReactSticker">%1$s: %3$s to your %4$s sticker in %2$s</string>
|
<string name="PushChatReactSticker">%3$s to your %4$s sticker in %2$s</string>
|
||||||
<string name="PushChatReactAudio">%1$s: %3$s to your voice message in %2$s</string>
|
<string name="PushChatReactAudio">%3$s to your voice message in %2$s</string>
|
||||||
<string name="PushChatReactContact">%1$s: %3$s to your contact %4$s in %2$s</string>
|
<string name="PushChatReactContact">%3$s to your contact %4$s in %2$s</string>
|
||||||
<string name="PushChatReactGeo">%1$s: %3$s to your map in %2$s</string>
|
<string name="PushChatReactGeo">%3$s to your map in %2$s</string>
|
||||||
<string name="PushChatReactGeoLive">%1$s: %3$s to your live location in %2$s</string>
|
<string name="PushChatReactGeoLive">%3$s to your live location in %2$s</string>
|
||||||
<string name="PushChatReactPoll">%1$s: %3$s to your poll %4$s in %2$s</string>
|
<string name="PushChatReactPoll">%3$s to your poll %4$s in %2$s</string>
|
||||||
<string name="PushChatReactQuiz">%1$s: %3$s to your quiz %4$s in %2$s</string>
|
<string name="PushChatReactQuiz">%3$s to your quiz %4$s in %2$s</string>
|
||||||
<string name="PushChatReactGame">%1$s: %3$s to your game in %2$s</string>
|
<string name="PushChatReactGame">%3$s to your game in %2$s</string>
|
||||||
<string name="PushChatReactInvoice">%1$s: %3$s to your invoice in %2$s</string>
|
<string name="PushChatReactInvoice">%3$s to your invoice in %2$s</string>
|
||||||
<string name="PushChatReactGif">%1$s: %3$s to your GIF in %2$s</string>
|
<string name="PushChatReactGif">%3$s to your GIF in %2$s</string>
|
||||||
<string name="BlurInChat">Blur in chat</string>
|
<string name="BlurInChat">Blur in chat</string>
|
||||||
|
|
||||||
<string name="AllowBackgroundActivity">Allow background activity</string>
|
<string name="AllowBackgroundActivity">Allow background activity</string>
|
||||||
|
@ -5186,6 +5191,7 @@
|
||||||
<string name="BotCantAddToAttachMenu">This bot can\'t be added to the attachment menu.</string>
|
<string name="BotCantAddToAttachMenu">This bot can\'t be added to the attachment menu.</string>
|
||||||
<string name="BotAlreadyAddedToAttachMenu">This bot is already in your attachment menu.</string>
|
<string name="BotAlreadyAddedToAttachMenu">This bot is already in your attachment menu.</string>
|
||||||
<string name="BotRemoveFromMenu">Remove **%1$s** from the attachment menu?</string>
|
<string name="BotRemoveFromMenu">Remove **%1$s** from the attachment menu?</string>
|
||||||
|
<string name="BotRemoveInlineFromMenu">Remove **%1$s** from suggestions?</string>
|
||||||
<string name="BotWebViewRequestGeolocationPermission">Allow **%1$s** to access to your location?\n\nThe developer of **%1$s** will be able to access your location when this web app is open.</string>
|
<string name="BotWebViewRequestGeolocationPermission">Allow **%1$s** to access to your location?\n\nThe developer of **%1$s** will be able to access your location when this web app is open.</string>
|
||||||
<string name="BotWebViewRequestGeolocationPermissionWithHint">Allow **%1$s** to access to your location?\n\nThe developer of **%1$s** will be able to access your location when this web app is open.\n\nGo to Settings > Permissions and turn **Location** on to share location data.</string>
|
<string name="BotWebViewRequestGeolocationPermissionWithHint">Allow **%1$s** to access to your location?\n\nThe developer of **%1$s** will be able to access your location when this web app is open.\n\nGo to Settings > Permissions and turn **Location** on to share location data.</string>
|
||||||
<string name="BotWebViewRequestMicrophonePermission">Allow **%1$s** to access to your microphone?\n\nThe developer of **%1$s** will be able to access your microphone when this web app is open.</string>
|
<string name="BotWebViewRequestMicrophonePermission">Allow **%1$s** to access to your microphone?\n\nThe developer of **%1$s** will be able to access your microphone when this web app is open.</string>
|
||||||
|
@ -5202,4 +5208,8 @@
|
||||||
<string name="DeleteTonesMessage_few">Do you want to delete **%d notification sounds**?</string>
|
<string name="DeleteTonesMessage_few">Do you want to delete **%d notification sounds**?</string>
|
||||||
<string name="DeleteTonesMessage_many">Do you want to delete **%d notification sounds**?</string>
|
<string name="DeleteTonesMessage_many">Do you want to delete **%d notification sounds**?</string>
|
||||||
<string name="DeleteTonesMessage_other">Do you want to delete **%d notification sounds**?</string>
|
<string name="DeleteTonesMessage_other">Do you want to delete **%d notification sounds**?</string>
|
||||||
|
<string name="CustomSound">Custom Sound</string>
|
||||||
|
<string name="ClearForAll">Clear for all</string>
|
||||||
|
<string name="ClearForMe">Clear for me</string>
|
||||||
|
<string name="BotWebViewNotAvailablePlaceholder">WebView not available. Please update it to use WebView bots.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|