Update to 7.4.0 (2221)

This commit is contained in:
DrKLO 2021-01-28 17:15:51 +03:00
parent d52de1a40a
commit 77bbe5baec
232 changed files with 16305 additions and 2717 deletions

View File

@ -21,7 +21,7 @@ dependencies {
implementation 'androidx.exifinterface:exifinterface:1.3.2'
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
implementation 'androidx.multidex:multidex:2.0.1'
implementation "androidx.sharetarget:sharetarget:1.0.0"
implementation "androidx.sharetarget:sharetarget:1.1.0"
compileOnly 'org.checkerframework:checker-qual:2.5.2'
compileOnly 'org.checkerframework:checker-compat-qual:2.5.0'
@ -290,7 +290,7 @@ android {
}
}
defaultConfig.versionCode = 2206
defaultConfig.versionCode = 2221
applicationVariants.all { variant ->
variant.outputs.all { output ->
@ -309,7 +309,7 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 29
versionName "7.3.1"
versionName "7.4.0"
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']

View File

@ -426,6 +426,21 @@ JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_makeNati
env->CallVoidMethod(globalRef, env->GetMethodID(NativeInstanceClass, "onSignalBarsUpdated", "(I)V"), count);
});
},
.audioLevelUpdated = [platformContext](float level) {
tgvoip::jni::DoWithJNI([platformContext, level](JNIEnv *env) {
jintArray intArray = nullptr;
jfloatArray floatArray = env->NewFloatArray(1);
jbooleanArray boolArray = nullptr;
jfloat floatFill[1];
floatFill[0] = level;
env->SetFloatArrayRegion(floatArray, 0, 1, floatFill);
jobject globalRef = ((AndroidContext *) platformContext.get())->getJavaInstance();
env->CallVoidMethod(globalRef, env->GetMethodID(NativeInstanceClass, "onAudioLevelsUpdated", "([I[F[Z)V"), intArray, floatArray, boolArray);
env->DeleteLocalRef(floatArray);
});
},
.remoteMediaStateUpdated = [platformContext](AudioState audioState, VideoState videoState) {
jobject globalRef = ((AndroidContext *) platformContext.get())->getJavaInstance();
tgvoip::jni::DoWithJNI([globalRef, audioState, videoState](JNIEnv *env) {
@ -521,6 +536,13 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setMuteMi
}
}
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setVolume(JNIEnv *env, jobject obj, jint ssrc, jdouble volume) {
InstanceHolder *instance = getInstanceHolder(env, obj);
if (instance->groupNativeInstance != nullptr) {
instance->groupNativeInstance->setVolume(ssrc, volume);
}
}
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setAudioOutputGainControlEnabled(JNIEnv *env, jobject obj, jboolean enabled) {
InstanceHolder *instance = getInstanceHolder(env, obj);
if (instance->nativeInstance == nullptr) {

View File

@ -19,6 +19,7 @@
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "api/call/audio_sink.h"
#include "modules/audio_processing/audio_buffer.h"
#include "modules/audio_device/include/audio_device_factory.h"
namespace tgcalls {
namespace {
@ -45,6 +46,31 @@ VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(VideoCaptureInter
: nullptr;
}
class AudioCaptureAnalyzer : public webrtc::CustomAudioAnalyzer {
private:
void Initialize(int sample_rate_hz, int num_channels) override {
}
// Analyzes the given capture or render signal.
void Analyze(const webrtc::AudioBuffer* audio) override {
_analyze(audio);
}
// Returns a string representation of the module state.
std::string ToString() const override {
return "analyzing";
}
std::function<void(const webrtc::AudioBuffer*)> _analyze;
public:
AudioCaptureAnalyzer(std::function<void(const webrtc::AudioBuffer*)> analyze) :
_analyze(analyze) {
}
virtual ~AudioCaptureAnalyzer() = default;
};
} // namespace
class VideoSinkInterfaceProxyImpl : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
@ -87,7 +113,7 @@ private:
class AudioTrackSinkInterfaceImpl: public webrtc::AudioSinkInterface {
private:
std::function<void(float)> _update;
int _peakCount = 0;
uint16_t _peak = 0;
@ -103,7 +129,7 @@ public:
if (audio.channels == 1) {
int16_t *samples = (int16_t *)audio.data;
int numberOfSamplesInFrame = (int)audio.samples_per_channel;
for (int i = 0; i < numberOfSamplesInFrame; i++) {
int16_t sample = samples[i];
if (sample < 0) {
@ -114,7 +140,7 @@ public:
}
_peakCount += 1;
}
if (_peakCount >= 1200) {
float level = ((float)(_peak)) / 4000.0f;
_peak = 0;
@ -206,7 +232,49 @@ _platformContext(platformContext) {
preferredCodecs,
_platformContext);
mediaDeps.audio_processing = webrtc::AudioProcessingBuilder().Create();
// [this] should outlive the analyzer
auto analyzer = new AudioCaptureAnalyzer([this](const webrtc::AudioBuffer* buffer) {
if (!buffer) {
return;
}
if (buffer->num_channels() != 1) {
return;
}
float peak = 0;
int peakCount = 0;
const float *samples = buffer->channels_const()[0];
for (int i = 0; i < buffer->num_frames(); i++) {
float sample = samples[i];
if (sample < 0) {
sample = -sample;
}
if (peak < sample) {
peak = sample;
}
peakCount += 1;
}
this->_thread->PostTask(RTC_FROM_HERE, [this, peak, peakCount](){
auto strong = this;
strong->_myAudioLevelPeakCount += peakCount;
if (strong->_myAudioLevelPeak < peak) {
strong->_myAudioLevelPeak = peak;
}
if (strong->_myAudioLevelPeakCount >= 1200) {
float level = strong->_myAudioLevelPeak / 4000.0f;
strong->_myAudioLevelPeak = 0;
strong->_myAudioLevelPeakCount = 0;
strong->_currentMyAudioLevel = level;
}
});
});
webrtc::AudioProcessingBuilder builder;
builder.SetCaptureAnalyzer(std::unique_ptr<AudioCaptureAnalyzer>(analyzer));
mediaDeps.audio_processing = builder.Create();
/*_audioDeviceModule = createAudioDeviceModule();
if (!_audioDeviceModule) {
@ -298,6 +366,13 @@ rtc::scoped_refptr<webrtc::AudioDeviceModule> MediaManager::createAudioDeviceMod
_taskQueueFactory.get());
return (result && (result->Init() == 0)) ? result : nullptr;
};
#ifdef WEBRTC_WIN
if (auto result = webrtc::CreateWindowsCoreAudioAudioDeviceModule(_taskQueueFactory.get())) {
if (result->Init() == 0) {
return result;
}
}
#endif // WEBRTC_WIN
if (auto result = check(webrtc::AudioDeviceModule::kPlatformDefaultAudio)) {
return result;
#ifdef WEBRTC_LINUX
@ -310,7 +385,7 @@ rtc::scoped_refptr<webrtc::AudioDeviceModule> MediaManager::createAudioDeviceMod
void MediaManager::start() {
const auto weak = std::weak_ptr<MediaManager>(shared_from_this());
// Here we hope that thread outlives the sink
rtc::Thread *thread = _thread;
std::unique_ptr<AudioTrackSinkInterfaceImpl> incomingSink(new AudioTrackSinkInterfaceImpl([weak, thread](float level) {
@ -320,24 +395,16 @@ void MediaManager::start() {
}
});
}));
std::unique_ptr<AudioTrackSinkInterfaceImpl> outgoingSink(new AudioTrackSinkInterfaceImpl([weak, thread](float level) {
thread->PostTask(RTC_FROM_HERE, [weak, level] {
if (const auto strong = weak.lock()) {
strong->_currentMyAudioLevel = level;
}
});
}));
_audioChannel->SetRawAudioSink(_ssrcAudio.incoming, std::move(incomingSink));
_audioChannel->SetRawAudioSink(_ssrcAudio.outgoing, std::move(outgoingSink));
_sendSignalingMessage({ _myVideoFormats });
_sendSignalingMessage({ _myVideoFormats });
if (_videoCapture != nullptr) {
setSendVideo(_videoCapture);
}
beginStatsTimer(3000);
if (_audioLevelUpdated != nullptr) {
if (_audioLevelUpdated != nullptr) {
beginLevelsTimer(50);
}
}

View File

@ -164,6 +164,8 @@ private:
float _currentAudioLevel = 0.0f;
float _currentMyAudioLevel = 0.0f;
int _myAudioLevelPeakCount = 0;
int _myAudioLevelPeak = 0;
std::unique_ptr<MediaManager::NetworkInterfaceImpl> _audioNetworkInterface;
std::unique_ptr<MediaManager::NetworkInterfaceImpl> _videoNetworkInterface;

View File

@ -19,6 +19,7 @@
#include "system_wrappers/include/field_trial.h"
#include "api/stats/rtcstats_objects.h"
#include "modules/audio_processing/audio_buffer.h"
#include "modules/audio_device/include/audio_device_factory.h"
#include "common_audio/include/audio_util.h"
#include "common_audio/vad/include/webrtc_vad.h"
#include "modules/audio_processing/agc2/vad_with_level.h"
@ -1091,6 +1092,14 @@ public:
dependencies.task_queue_factory.get());
return (result && (result->Init() == 0)) ? result : nullptr;
};
#ifdef WEBRTC_WIN
if (auto result = webrtc::CreateWindowsCoreAudioAudioDeviceModule(dependencies.task_queue_factory.get())) {
if (result->Init() == 0) {
_adm_use_withAudioDeviceModule = new rtc::RefCountedObject<WrappedAudioDeviceModule>(result);
return;
}
}
#endif // WEBRTC_WIN
if (auto result = check(webrtc::AudioDeviceModule::kPlatformDefaultAudio)) {
_adm_use_withAudioDeviceModule = new rtc::RefCountedObject<WrappedAudioDeviceModule>(result);
#ifdef WEBRTC_LINUX
@ -1326,7 +1335,7 @@ public:
adm->EnableBuiltInAEC(false);
#endif // WEBRTC_WIN
if (adm->InitPlayout()) {
if (adm->InitPlayout() == 0) {
adm->StartPlayout();
} else {
getMediaThread()->PostDelayedTask(RTC_FROM_HERE, [weak](){
@ -1335,7 +1344,7 @@ public:
return;
}
strong->withAudioDeviceModule([](webrtc::AudioDeviceModule *adm) {
if (adm->InitPlayout()) {
if (adm->InitPlayout() == 0) {
adm->StartPlayout();
}
});
@ -1443,6 +1452,27 @@ public:
});
#endif
}
void setVolume(uint32_t ssrc, double volume) {
auto current = _audioTrackVolumes.find(ssrc);
bool updated = false;
if (current != _audioTrackVolumes.end()) {
if (abs(current->second - volume) > 0.001) {
updated = true;
}
} else {
if (volume < 1.0 - 0.001) {
updated = true;
}
}
if (updated) {
_audioTrackVolumes[ssrc] = volume;
auto track = _audioTracks.find(ssrc);
if (track != _audioTracks.end()) {
track->second->GetSource()->SetVolume(volume);
}
}
}
void updateIsConnected(bool isConnected) {
_isConnected = isConnected;
@ -1792,7 +1822,14 @@ public:
uint32_t ssrc = 0;
iss >> ssrc;
auto remoteAudioTrack = static_cast<webrtc::AudioTrackInterface *>(transceiver->receiver()->track().get());
rtc::scoped_refptr<webrtc::AudioTrackInterface> remoteAudioTrack(static_cast<webrtc::AudioTrackInterface *>(transceiver->receiver()->track().get()));
if (_audioTracks.find(ssrc) == _audioTracks.end()) {
_audioTracks.insert(std::make_pair(ssrc, remoteAudioTrack));
}
auto currentVolume = _audioTrackVolumes.find(ssrc);
if (currentVolume != _audioTrackVolumes.end()) {
remoteAudioTrack->GetSource()->SetVolume(currentVolume->second);
}
if (_audioTrackSinks.find(ssrc) == _audioTrackSinks.end()) {
const auto weak = std::weak_ptr<GroupInstanceManager>(shared_from_this());
std::shared_ptr<AudioTrackSinkInterfaceImpl> sink(new AudioTrackSinkInterfaceImpl([weak, ssrc](float level, bool hasSpeech) {
@ -1821,6 +1858,7 @@ public:
}));
_audioTrackSinks[ssrc] = sink;
remoteAudioTrack->AddSink(sink.get());
//remoteAudioTrack->GetSource()->SetVolume(0.01);
}
}
}
@ -2048,8 +2086,10 @@ private:
rtc::Thread *_adm_thread = nullptr;
rtc::scoped_refptr<webrtc::AudioDeviceModule> _adm_use_withAudioDeviceModule;
std::map<uint32_t, rtc::scoped_refptr<webrtc::AudioTrackInterface>> _audioTracks;
std::map<uint32_t, std::shared_ptr<AudioTrackSinkInterfaceImpl>> _audioTrackSinks;
std::map<uint32_t, GroupLevelValue> _audioLevels;
std::map<uint32_t, double> _audioTrackVolumes;
std::shared_ptr<PlatformContext> _platformContext;
};
@ -2122,4 +2162,10 @@ void GroupInstanceImpl::setAudioOutputDevice(std::string id) {
});
}
void GroupInstanceImpl::setVolume(uint32_t ssrc, double volume) {
_manager->perform(RTC_FROM_HERE, [ssrc, volume](GroupInstanceManager *manager) {
manager->setVolume(ssrc, volume);
});
}
} // namespace tgcalls

View File

@ -102,6 +102,8 @@ public:
void setIsMuted(bool isMuted);
void setAudioOutputDevice(std::string id);
void setAudioInputDevice(std::string id);
void setVolume(uint32_t ssrc, double volume);
struct AudioDevice {
enum class Type {Input, Output};

View File

@ -240,9 +240,9 @@ void InstanceImplLegacy::setOutputVolume(float level) {
}
void InstanceImplLegacy::setAudioOutputDuckingEnabled(bool enabled) {
#if defined(__APPLE__) && defined(TARGET_OS_OSX)
#if defined(__APPLE__) && TARGET_OS_OSX
controller_->SetAudioOutputDuckingEnabled(enabled);
#endif
#endif // TARGET_OS_OSX
}
void InstanceImplLegacy::setIsLowBatteryLevel(bool isLowBatteryLevel) {

View File

@ -199,6 +199,24 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<!-- <activity-->
<!-- android:name="org.telegram.ui.ShortcutWidgetConfigActivity"-->
<!-- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"-->
<!-- android:hardwareAccelerated="@bool/useHardwareAcceleration"-->
<!-- android:windowSoftInputMode="adjustPan">-->
<!-- <intent-filter android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round">-->
<!-- <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>-->
<!-- </intent-filter>-->
<!-- </activity>-->
<!-- <activity-->
<!-- android:name="org.telegram.ui.FeedWidgetConfigActivity"-->
<!-- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"-->
<!-- android:hardwareAccelerated="@bool/useHardwareAcceleration"-->
<!-- android:windowSoftInputMode="adjustPan">-->
<!-- <intent-filter android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round">-->
<!-- <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>-->
<!-- </intent-filter>-->
<!-- </activity>-->
<activity
android:name="org.telegram.ui.IntroActivity"
android:launchMode="singleTask"
@ -302,6 +320,7 @@
<service android:name=".NotificationsService" android:enabled="true"/>
<service android:name=".NotificationRepeat" android:exported="false"/>
<service android:name=".VideoEncodingService" android:enabled="true"/>
<service android:name=".ImportingService" android:enabled="true"/>
<service android:name=".LocationSharingService"
android:foregroundServiceType="location"
android:enabled="true"/>
@ -396,6 +415,30 @@
android:name=".voip.CallNotificationSoundProvider"
android:exported="true"/>
<!-- <receiver android:name=".ShortcutWidgetProvider">-->
<!-- <meta-data android:name="android.appwidget.provider"-->
<!-- android:resource="@xml/shortcut_widget_info" />-->
<!-- <intent-filter>-->
<!-- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- <service android:name=".ShortcutWidgetService"-->
<!-- android:permission="android.permission.BIND_REMOTEVIEWS"-->
<!-- android:exported="false" />-->
<!-- <receiver android:name=".FeedWidgetProvider">-->
<!-- <meta-data android:name="android.appwidget.provider"-->
<!-- android:resource="@xml/feed_widget_info" />-->
<!-- <intent-filter>-->
<!-- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- <service android:name=".FeedWidgetService"-->
<!-- android:permission="android.permission.BIND_REMOTEVIEWS"-->
<!-- android:exported="false" />-->
<uses-library android:name="com.sec.android.app.multiwindow" android:required="false" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632dp" />

View File

@ -1397,9 +1397,6 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements
}
final int scrolled = absDelta > consumed ? layoutDirection * consumed : delta;
mOrientationHelper.offsetChildren(-scrolled);
if (DEBUG) {
Log.d(TAG, "scroll req: " + delta + " scrolled: " + scrolled);
}
mLayoutState.mLastScrollDelta = scrolled;
return scrolled;
}

View File

@ -32,6 +32,9 @@ import com.google.zxing.qrcode.encoder.Encoder;
import com.google.zxing.qrcode.encoder.QRCode;
import org.telegram.messenger.R;
import org.telegram.messenger.SvgHelper;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.RLottieDrawable;
import java.util.Arrays;
import java.util.Map;
@ -115,7 +118,7 @@ public final class QRCodeWriter {
imageBloks++;
}
imageBlockX = (inputWidth - imageBloks) / 2;
int imageSize = imageBloks * multiple;
int imageSize = imageBloks * multiple - 24;
int imageX = (size - imageSize) / 2;
for (int a = 0; a < 3; a++) {
@ -206,9 +209,14 @@ public final class QRCodeWriter {
}
}
Drawable drawable = context.getResources().getDrawable(R.drawable.gem_l).mutate();
drawable.setBounds(imageX, imageX, imageX + imageSize, imageX + imageSize);
drawable.draw(canvas);
String svg = RLottieDrawable.readRes(null, R.raw.qr_logo);
Bitmap icon = SvgHelper.getBitmap(svg, imageSize, imageSize, false);
// Drawable drawable = context.getResources().getDrawable(R.drawable.ic_launcher_dr).mutate();
// drawable.setBounds(imageX, imageX, imageX + imageSize, imageX + imageSize);
// drawable.draw(canvas);
canvas.drawBitmap(icon, imageX, imageX, null);
icon.recycle();
canvas.setBitmap(null);

View File

@ -50,6 +50,7 @@ import android.provider.Settings;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import android.telephony.TelephonyManager;
@ -65,6 +66,10 @@ import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.transition.ChangeBounds;
import android.transition.TransitionSet;
import android.transition.TransitionValues;
import android.transition.Visibility;
import android.util.DisplayMetrics;
import android.util.StateSet;
import android.util.TypedValue;
@ -107,12 +112,14 @@ import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBarLayout;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.TextDetailSettingsCell;
import org.telegram.ui.Components.BackgroundGradientDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.ForegroundColorSpanThemable;
import org.telegram.ui.Components.ForegroundDetector;
import org.telegram.ui.Components.LayoutHelper;
@ -3624,4 +3631,25 @@ public class AndroidUtilities {
}
return false;
}
public static void updateVisibleRows(RecyclerListView listView) {
if (listView == null) {
return;
}
RecyclerView.Adapter adapter = listView.getAdapter();
if (adapter == null) {
return;
}
for (int i = 0; i < listView.getChildCount(); i++) {
View child = listView.getChildAt(i);
int p = listView.getChildAdapterPosition(child);
if (p >= 0) {
RecyclerView.ViewHolder holder = listView.getChildViewHolder(child);
if (holder == null || holder.shouldIgnore()) {
continue;
}
adapter.onBindViewHolder(holder, p);
}
}
}
}

View File

@ -18,8 +18,8 @@ public class BuildVars {
public static boolean LOGS_ENABLED = false;
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
public static int BUILD_VERSION = 2206;
public static String BUILD_VERSION_STRING = "7.3.0";
public static int BUILD_VERSION = 2221;
public static String BUILD_VERSION_STRING = "7.4.0";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
public static String APPCENTER_HASH = "a5b5c4f5-51da-dedc-9918-d9766a22ca7c";

View File

@ -143,17 +143,27 @@ public class ChatObject {
call.version = groupParticipants.version;
call.participants_count = groupParticipants.count;
}
long time = SystemClock.elapsedRealtime();
currentAccount.getNotificationCenter().postNotificationName(NotificationCenter.applyGroupCallVisibleParticipants, time);
for (int a = 0, N = groupParticipants.participants.size(); a < N; a++) {
TLRPC.TL_groupCallParticipant participant = groupParticipants.participants.get(a);
TLRPC.TL_groupCallParticipant oldParticipant = participants.get(participant.user_id);
if (oldParticipant != null) {
sortedParticipants.remove(oldParticipant);
participantsBySources.remove(oldParticipant.source);
participant.active_date = Math.max(participant.active_date, oldParticipant.active_date);
participant.lastTypingDate = Math.max(participant.active_date, oldParticipant.active_date);
if (time != participant.lastVisibleDate) {
participant.active_date = participant.lastTypingDate;
}
} else if (old != null) {
oldParticipant = old.get(participant.user_id);
if (oldParticipant != null) {
participant.active_date = Math.max(participant.active_date, oldParticipant.active_date);
participant.lastTypingDate = Math.max(participant.active_date, oldParticipant.active_date);
if (time != participant.lastVisibleDate) {
participant.active_date = participant.lastTypingDate;
} else {
participant.active_date = oldParticipant.active_date;
}
}
}
participants.put(participant.user_id, participant);
@ -180,12 +190,19 @@ public class ChatObject {
public void processTypingsUpdate(AccountInstance accountInstance, ArrayList<Integer> uids, int date) {
boolean updated = false;
ArrayList<Integer> participantsToLoad = null;
long time = SystemClock.elapsedRealtime();
currentAccount.getNotificationCenter().postNotificationName(NotificationCenter.applyGroupCallVisibleParticipants, time);
for (int a = 0, N = uids.size(); a < N; a++) {
Integer id = uids.get(a);
TLRPC.TL_groupCallParticipant participant = participants.get(id);
if (participant != null) {
participant.active_date = date;
updated = true;
if (date - participant.lastTypingDate > 10) {
if (participant.lastVisibleDate != date) {
participant.active_date = date;
}
participant.lastTypingDate = date;
updated = true;
}
} else {
if (participantsToLoad == null) {
participantsToLoad = new ArrayList<>();
@ -252,6 +269,8 @@ public class ChatObject {
boolean updated = false;
int currentTime = currentAccount.getConnectionsManager().getCurrentTime();
ArrayList<Integer> participantsToLoad = null;
long time = SystemClock.elapsedRealtime();
currentAccount.getNotificationCenter().postNotificationName(NotificationCenter.applyGroupCallVisibleParticipants, time);
for (int a = 0; a < ssrc.length; a++) {
TLRPC.TL_groupCallParticipant participant;
if (ssrc[a] == 0) {
@ -262,8 +281,11 @@ public class ChatObject {
if (participant != null) {
participant.hasVoice = voice[a];
if (levels[a] > 0.1f) {
if (voice[a] && participant.active_date + 1 < currentTime) {
participant.active_date = currentTime;
if (voice[a] && participant.lastTypingDate + 1 < currentTime) {
if (time != participant.lastVisibleDate) {
participant.active_date = currentTime;
}
participant.lastTypingDate = currentTime;
updated = true;
}
participant.lastSpeakTime = SystemClock.uptimeMillis();
@ -388,6 +410,8 @@ public class ChatObject {
boolean updated = false;
boolean selfUpdated = false;
int selfId = currentAccount.getUserConfig().getClientUserId();
long time = SystemClock.elapsedRealtime();
currentAccount.getNotificationCenter().postNotificationName(NotificationCenter.applyGroupCallVisibleParticipants, time);
for (int a = 0, N = update.participants.size(); a < N; a++) {
TLRPC.TL_groupCallParticipant participant = update.participants.get(a);
TLRPC.TL_groupCallParticipant oldParticipant = participants.get(participant.user_id);
@ -414,9 +438,14 @@ public class ChatObject {
if (oldParticipant != null) {
oldParticipant.flags = participant.flags;
oldParticipant.muted = participant.muted;
oldParticipant.muted_by_you = participant.muted_by_you;
oldParticipant.volume = participant.volume;
oldParticipant.can_self_unmute = participant.can_self_unmute;
oldParticipant.date = participant.date;
oldParticipant.active_date = Math.max(oldParticipant.active_date, participant.active_date);
oldParticipant.lastTypingDate = Math.max(oldParticipant.active_date, participant.active_date);
if (time != oldParticipant.lastVisibleDate) {
oldParticipant.active_date = oldParticipant.lastTypingDate;
}
if (oldParticipant.source != participant.source) {
participantsBySources.remove(oldParticipant.source);
oldParticipant.source = participant.source;
@ -484,6 +513,13 @@ public class ChatObject {
checkOnlineParticipants();
}
public void saveActiveDates() {
for (int a = 0, N = sortedParticipants.size(); a < N; a++) {
TLRPC.TL_groupCallParticipant p = sortedParticipants.get(a);
p.lastActiveDate = p.active_date;
}
}
private void checkOnlineParticipants() {
if (typingUpdateRunnableScheduled) {
AndroidUtilities.cancelRunOnUIThread(typingUpdateRunnable);
@ -510,6 +546,10 @@ public class ChatObject {
}
}
public static int getParticipantVolume(TLRPC.TL_groupCallParticipant participant) {
return ((participant.flags & 128) != 0 ? participant.volume : 10000);
}
private static boolean isBannableAction(int action) {
switch (action) {
case ACTION_PIN:

View File

@ -0,0 +1,59 @@
package org.telegram.messenger;
import android.app.Activity;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.widget.RemoteViews;
import org.telegram.ui.FeedWidgetConfigActivity;
import org.telegram.ui.LaunchActivity;
public class FeedWidgetProvider extends AppWidgetProvider {
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int i = 0; i < appWidgetIds.length; i++) {
int appWidgetId = appWidgetIds[i];
updateWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
for (int a = 0; a < appWidgetIds.length; a++) {
SharedPreferences preferences = context.getSharedPreferences("feed_widget", Activity.MODE_PRIVATE);
preferences.edit().remove("account" + appWidgetIds[a]).remove("dialogId" + appWidgetIds[a]).commit();
}
}
public static void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
Intent intent2 = new Intent(context, FeedWidgetService.class);
intent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent2.setData(Uri.parse(intent2.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.feed_widget_layout);
rv.setRemoteAdapter(appWidgetId, R.id.list_view, intent2);
rv.setEmptyView(R.id.list_view, R.id.empty_view);
Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setPendingIntentTemplate(R.id.list_view, contentIntent);
appWidgetManager.updateAppWidget(appWidgetId, rv);
}
}

View File

@ -0,0 +1,169 @@
package org.telegram.messenger;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import androidx.core.content.FileProvider;
public class FeedWidgetService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new FeedRemoteViewsFactory(getApplicationContext(), intent);
}
}
class FeedRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory, NotificationCenter.NotificationCenterDelegate {
private ArrayList<MessageObject> messages = new ArrayList<>();
private Context mContext;
private int appWidgetId;
private long dialogId;
private int classGuid;
private AccountInstance accountInstance;
private CountDownLatch countDownLatch = new CountDownLatch(1);
public FeedRemoteViewsFactory(Context context, Intent intent) {
mContext = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
SharedPreferences preferences = context.getSharedPreferences("feed_widget", Activity.MODE_PRIVATE);
int accountId = preferences.getInt("account" + appWidgetId, -1);
if (accountId >= 0) {
dialogId = preferences.getLong("dialogId" + appWidgetId, 0);
accountInstance = AccountInstance.getInstance(accountId);
}
}
public void onCreate() {
ApplicationLoader.postInitApplication();
}
public void onDestroy() {
}
public int getCount() {
return messages.size();
}
protected void grantUriAccessToWidget(Context context, Uri uri) {
Intent intent= new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
public RemoteViews getViewAt(int position) {
MessageObject messageObject = messages.get(position);
String name;
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.feed_widget_item);
if (messageObject.type == 0) {
rv.setTextViewText(R.id.feed_widget_item_text, messageObject.messageText);
rv.setViewVisibility(R.id.feed_widget_item_text, View.VISIBLE);
} else {
if (TextUtils.isEmpty(messageObject.caption)) {
rv.setViewVisibility(R.id.feed_widget_item_text, View.GONE);
} else {
rv.setTextViewText(R.id.feed_widget_item_text, messageObject.caption);
rv.setViewVisibility(R.id.feed_widget_item_text, View.VISIBLE);
}
}
if (messageObject.photoThumbs == null || messageObject.photoThumbs.isEmpty()) {
rv.setViewVisibility(R.id.feed_widget_item_image, View.GONE);
} else {
TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize());
File f = FileLoader.getPathToAttach(size);
if (f.exists()) {
rv.setViewVisibility(R.id.feed_widget_item_image, View.VISIBLE);
Uri uri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".provider", f);
grantUriAccessToWidget(mContext, uri);
rv.setImageViewUri(R.id.feed_widget_item_image, uri);
} else {
rv.setViewVisibility(R.id.feed_widget_item_image, View.GONE);
}
}
Bundle extras = new Bundle();
extras.putInt("chatId", (int) -messageObject.getDialogId());
extras.putInt("message_id", messageObject.getId());
extras.putInt("currentAccount", accountInstance.getCurrentAccount());
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
rv.setOnClickFillInIntent(R.id.shortcut_widget_item, fillInIntent);
return rv;
}
public RemoteViews getLoadingView() {
return null;
}
public int getViewTypeCount() {
return 1;
}
public long getItemId(int position) {
return position;
}
public boolean hasStableIds() {
return true;
}
public void onDataSetChanged() {
if (accountInstance == null || !accountInstance.getUserConfig().isClientActivated()) {
messages.clear();
return;
}
AndroidUtilities.runOnUIThread(() -> {
accountInstance.getNotificationCenter().addObserver(FeedRemoteViewsFactory.this, NotificationCenter.messagesDidLoad);
if (classGuid == 0) {
classGuid = ConnectionsManager.generateClassGuid();
}
accountInstance.getMessagesController().loadMessages(dialogId, 0, false, 20, 0, 0, true, 0, classGuid, 0, 0, true, 0, 0, 0, 1);
});
try {
countDownLatch.await();
} catch (Exception e) {
FileLog.e(e);
}
}
@SuppressWarnings("unchecked")
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.messagesDidLoad) {
int guid = (Integer) args[10];
if (guid == classGuid) {
messages.clear();
ArrayList<MessageObject> messArr = (ArrayList<MessageObject>) args[2];
messages.addAll(messArr);
countDownLatch.countDown();
}
}
}
}

View File

@ -97,6 +97,8 @@ public class FileLoadOperation {
private boolean nextPartWasPreloaded;
protected long lastProgressUpdateTime;
private ArrayList<Range> notLoadedBytesRanges;
private volatile ArrayList<Range> notLoadedBytesRangesCopy;
private ArrayList<Range> notRequestedBytesRanges;

View File

@ -28,12 +28,12 @@ import java.util.concurrent.CountDownLatch;
public class FileLoader extends BaseController {
public interface FileLoaderDelegate {
void fileUploadProgressChanged(String location, long uploadedSize, long totalSize, boolean isEncrypted);
void fileUploadProgressChanged(FileUploadOperation operation, String location, long uploadedSize, long totalSize, boolean isEncrypted);
void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv, long totalFileSize);
void fileDidFailedUpload(String location, boolean isEncrypted);
void fileDidLoaded(String location, File finalFile, int type);
void fileDidFailedLoad(String location, int state);
void fileLoadProgressChanged(String location, long uploadedSize, long totalSize);
void fileLoadProgressChanged(FileLoadOperation operation, String location, long uploadedSize, long totalSize);
}
public static final int MEDIA_DIR_IMAGE = 0;
@ -237,10 +237,10 @@ public class FileLoader extends BaseController {
}
public void uploadFile(final String location, final boolean encrypted, final boolean small, final int type) {
uploadFile(location, encrypted, small, 0, type);
uploadFile(location, encrypted, small, 0, type, false);
}
public void uploadFile(final String location, final boolean encrypted, final boolean small, final int estimatedSize, final int type) {
public void uploadFile(final String location, final boolean encrypted, final boolean small, final int estimatedSize, final int type, boolean forceSmallFile) {
if (location == null) {
return;
}
@ -262,15 +262,18 @@ public class FileLoader extends BaseController {
uploadSizes.remove(location);
}
}
if (delegate != null && estimatedSize != 0) {
delegate.fileUploadProgressChanged(location, 0, estimatedSize, encrypted);
}
FileUploadOperation operation = new FileUploadOperation(currentAccount, location, encrypted, esimated, type);
if (delegate != null && estimatedSize != 0) {
delegate.fileUploadProgressChanged(operation, location, 0, estimatedSize, encrypted);
}
if (encrypted) {
uploadOperationPathsEnc.put(location, operation);
} else {
uploadOperationPaths.put(location, operation);
}
if (forceSmallFile) {
operation.setForceSmallFile();
}
operation.setDelegate(new FileUploadOperation.FileUploadOperationDelegate() {
@Override
public void didFinishUploadingFile(final FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) {
@ -341,7 +344,7 @@ public class FileLoader extends BaseController {
@Override
public void didChangedUploadProgress(FileUploadOperation operation, long uploadedSize, long totalSize) {
if (delegate != null) {
delegate.fileUploadProgressChanged(location, uploadedSize, totalSize, encrypted);
delegate.fileUploadProgressChanged(operation, location, uploadedSize, totalSize, encrypted);
}
}
});
@ -715,7 +718,7 @@ public class FileLoader extends BaseController {
@Override
public void didChangedLoadProgress(FileLoadOperation operation, long uploadedSize, long totalSize) {
if (delegate != null) {
delegate.fileLoadProgressChanged(fileName, uploadedSize, totalSize);
delegate.fileLoadProgressChanged(operation, fileName, uploadedSize, totalSize);
}
}
};

View File

@ -67,6 +67,7 @@ public class FileUploadOperation {
private boolean isEncrypted;
private int fingerprint;
private boolean isBigFile;
private boolean forceSmallFile;
private String fileKey;
private int estimatedSize;
private int uploadStartTime;
@ -79,6 +80,7 @@ public class FileUploadOperation {
private long availableSize;
private boolean uploadFirstPartLater;
private SparseArray<UploadCachedResult> cachedResults = new SparseArray<>();
protected long lastProgressUpdateTime;
public interface FileUploadOperationDelegate {
void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv);
@ -236,6 +238,10 @@ public class FileUploadOperation {
}
}
public void setForceSmallFile() {
forceSmallFile = true;
}
private void startUploadRequest() {
if (state != 1) {
return;
@ -272,7 +278,7 @@ public class FileUploadOperation {
} else {
totalFileSize = cacheFile.length();
}
if (totalFileSize > 10 * 1024 * 1024) {
if (!forceSmallFile && totalFileSize > 10 * 1024 * 1024) {
isBigFile = true;
}
@ -628,7 +634,7 @@ public class FileUploadOperation {
if (currentUploadRequetsCount < maxRequestsCount) {
startUploadRequest();
}
}), 0, ConnectionsManager.DEFAULT_DATACENTER_ID, connectionType, true);
}), forceSmallFile ? ConnectionsManager.RequestFlagCanCompress : 0, ConnectionsManager.DEFAULT_DATACENTER_ID, connectionType, true);
requestTokens.put(requestNumFinal, requestToken);
}
}

View File

@ -24,6 +24,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.SparseArray;
@ -104,7 +105,6 @@ public class ImageLoader {
private volatile long lastCacheOutTime = 0;
private int lastImageNum = 0;
private long lastProgressUpdateTime = 0;
private File telegramPath = null;
@ -143,7 +143,7 @@ public class ImageLoader {
}
private void reportProgress(long uploadedSize, long totalSize) {
long currentTime = System.currentTimeMillis();
long currentTime = SystemClock.elapsedRealtime();
if (uploadedSize == totalSize || lastProgressTime == 0 || lastProgressTime < currentTime - 100) {
lastProgressTime = currentTime;
Utilities.stageQueue.postRunnable(() -> {
@ -441,7 +441,7 @@ public class ImageLoader {
}
private void reportProgress(long uploadedSize, long totalSize) {
long currentTime = System.currentTimeMillis();
long currentTime = SystemClock.elapsedRealtime();
if (uploadedSize == totalSize || lastProgressTime == 0 || lastProgressTime < currentTime - 100) {
lastProgressTime = currentTime;
Utilities.stageQueue.postRunnable(() -> {
@ -1074,7 +1074,7 @@ public class ImageLoader {
if (cacheImage.type == ImageReceiver.TYPE_THUMB) {
try {
lastCacheOutTime = System.currentTimeMillis();
lastCacheOutTime = SystemClock.elapsedRealtime();
synchronized (sync) {
if (isCancelled) {
return;
@ -1179,10 +1179,10 @@ public class ImageLoader {
if (mediaId != null) {
delay = 0;
}
if (delay != 0 && lastCacheOutTime != 0 && lastCacheOutTime > System.currentTimeMillis() - delay && Build.VERSION.SDK_INT < 21) {
if (delay != 0 && lastCacheOutTime != 0 && lastCacheOutTime > SystemClock.elapsedRealtime() - delay && Build.VERSION.SDK_INT < 21) {
Thread.sleep(delay);
}
lastCacheOutTime = System.currentTimeMillis();
lastCacheOutTime = SystemClock.elapsedRealtime();
synchronized (sync) {
if (isCancelled) {
return;
@ -1674,11 +1674,11 @@ public class ImageLoader {
final int currentAccount = a;
FileLoader.getInstance(a).setDelegate(new FileLoader.FileLoaderDelegate() {
@Override
public void fileUploadProgressChanged(final String location, long uploadedSize, long totalSize, final boolean isEncrypted) {
public void fileUploadProgressChanged(FileUploadOperation operation, final String location, long uploadedSize, long totalSize, final boolean isEncrypted) {
fileProgresses.put(location, new long[]{uploadedSize, totalSize});
long currentTime = System.currentTimeMillis();
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500) {
lastProgressUpdateTime = currentTime;
long currentTime = SystemClock.elapsedRealtime();
if (operation.lastProgressUpdateTime == 0 || operation.lastProgressUpdateTime < currentTime - 100 || uploadedSize == totalSize) {
operation.lastProgressUpdateTime = currentTime;
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.FileUploadProgressChanged, location, uploadedSize, totalSize, isEncrypted));
}
@ -1724,11 +1724,11 @@ public class ImageLoader {
}
@Override
public void fileLoadProgressChanged(final String location, long uploadedSize, long totalSize) {
public void fileLoadProgressChanged(FileLoadOperation operation, final String location, long uploadedSize, long totalSize) {
fileProgresses.put(location, new long[]{uploadedSize, totalSize});
long currentTime = System.currentTimeMillis();
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500 || uploadedSize == 0) {
lastProgressUpdateTime = currentTime;
long currentTime = SystemClock.elapsedRealtime();
if (operation.lastProgressUpdateTime == 0 || operation.lastProgressUpdateTime < currentTime - 500 || uploadedSize == 0) {
operation.lastProgressUpdateTime = currentTime;
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.FileLoadProgressChanged, location, uploadedSize, totalSize));
}
}

View File

@ -0,0 +1,90 @@
/*
* This is the source code of Telegram for Android v. 5.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2018.
*/
package org.telegram.messenger;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
public class ImportingService extends Service implements NotificationCenter.NotificationCenterDelegate {
private NotificationCompat.Builder builder;
public ImportingService() {
super();
for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.historyImportProgressChanged);
}
}
public IBinder onBind(Intent arg2) {
return null;
}
public void onDestroy() {
super.onDestroy();
try {
stopForeground(true);
} catch (Throwable ignore) {
}
NotificationManagerCompat.from(ApplicationLoader.applicationContext).cancel(5);
for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.historyImportProgressChanged);
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("destroy import service");
}
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.historyImportProgressChanged) {
if (!hasImports()) {
stopSelf();
}
}
}
private boolean hasImports() {
for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
if (SendMessagesHelper.getInstance(a).isImportingHistory()) {
return true;
}
}
return false;
}
public int onStartCommand(Intent intent, int flags, int startId) {
if (!hasImports()) {
stopSelf();
return Service.START_NOT_STICKY;
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("start import service");
}
if (builder == null) {
NotificationsController.checkOtherNotificationsChannel();
builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext);
builder.setSmallIcon(android.R.drawable.stat_sys_upload);
builder.setWhen(System.currentTimeMillis());
builder.setChannelId(NotificationsController.OTHER_NOTIFICATIONS_CHANNEL);
builder.setContentTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setTicker(LocaleController.getString("ImporImportingService", R.string.ImporImportingService));
builder.setContentText(LocaleController.getString("ImporImportingService", R.string.ImporImportingService));
}
builder.setProgress(100, 0, true);
startForeground(5, builder.build());
NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(5, builder.build());
return Service.START_NOT_STICKY;
}
}

View File

@ -1694,6 +1694,17 @@ public class LocaleController {
return "LOC_ERR";
}
public static String formatImportedDate(long date) {
try {
date *= 1000;
Date dt = new Date(date);
return String.format("%1$s, %2$s", getInstance().formatterYear.format(dt), getInstance().formatterDay.format(dt));
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatUserStatus(int currentAccount, TLRPC.User user, boolean[] isOnline) {
if (user != null && user.status != null && user.status.expires == 0) {
if (user.status instanceof TLRPC.TL_userStatusRecently) {

View File

@ -1064,7 +1064,7 @@ public class LocationController extends BaseController implements NotificationCe
arg = address.getThoroughfare();
if (!TextUtils.isEmpty(arg)) {
if (nameBuilder.length() > 0) {
nameBuilder.append(", ");
nameBuilder.append(" ");
}
nameBuilder.append(arg);
hasAny = true;

View File

@ -9,6 +9,9 @@
package org.telegram.messenger;
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DownloadManager;
@ -103,6 +106,13 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
public native byte[] getWaveform(String path);
public native byte[] getWaveform2(short[] array, int length);
public boolean isBuffering() {
if (audioPlayer != null) {
return audioPlayer.isBuffering();
}
return false;
}
private static class AudioBuffer {
public AudioBuffer(int capacity) {
buffer = ByteBuffer.allocateDirect(capacity);
@ -647,6 +657,16 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
};
private float audioVolume;
private ValueAnimator audioVolumeAnimator;
private final ValueAnimator.AnimatorUpdateListener audioVolumeUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
audioVolume = (float) valueAnimator.getAnimatedValue();
setPlayerVolume();
}
};
private class InternalObserver extends ContentObserver {
public InternalObserver() {
super(null);
@ -992,7 +1012,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
volume = VOLUME_DUCK;
}
if (audioPlayer != null) {
audioPlayer.setVolume(volume);
audioPlayer.setVolume(volume * audioVolume);
} else if (videoPlayer != null) {
videoPlayer.setVolume(volume);
}
@ -1769,10 +1789,41 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
public void cleanupPlayer(boolean notify, boolean stopService, boolean byVoiceEnd, boolean transferPlayerToPhotoViewer) {
if (audioPlayer != null) {
try {
audioPlayer.releasePlayer(true);
} catch (Exception e) {
FileLog.e(e);
if (audioVolumeAnimator != null) {
audioVolumeAnimator.removeAllUpdateListeners();
audioVolumeAnimator.cancel();
}
if (audioPlayer.isPlaying() && playingMessageObject != null && !playingMessageObject.isVoice()) {
VideoPlayer playerFinal = audioPlayer;
ValueAnimator valueAnimator = ValueAnimator.ofFloat(audioVolume, 0);
valueAnimator.addUpdateListener(valueAnimator1 -> {
float volume;
if (audioFocus != AUDIO_NO_FOCUS_CAN_DUCK) {
volume = VOLUME_NORMAL;
} else {
volume = VOLUME_DUCK;
}
playerFinal.setVolume(volume * (float) valueAnimator1.getAnimatedValue());
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
try {
playerFinal.releasePlayer(true);
} catch (Exception e) {
FileLog.e(e);
}
}
});
valueAnimator.setDuration(300);
valueAnimator.start();
} else {
try {
audioPlayer.releasePlayer(true);
} catch (Exception e) {
FileLog.e(e);
}
}
audioPlayer = null;
Theme.unrefAudioVisualizeDrawable(playingMessageObject);
@ -1910,6 +1961,12 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return true;
}
public long getDuration() {
if (audioPlayer == null) {
return 0;
}
return audioPlayer.getDuration();
}
public MessageObject getPlayingMessageObject() {
return playingMessageObject;
}
@ -2431,6 +2488,19 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
public void setPlaybackSpeed(boolean music, float speed) {
if (music) {
if (currentMusicPlaybackSpeed >= 6 && speed == 1f && playingMessageObject != null) {
audioPlayer.pause();
float p = playingMessageObject.audioProgress;
final MessageObject currentMessage = playingMessageObject;
AndroidUtilities.runOnUIThread(() -> {
if (audioPlayer != null && playingMessageObject != null && !isPaused) {
if (isSamePlayingMessage(currentMessage )) {
seekToProgress(playingMessageObject, p);
}
audioPlayer.play();
}
}, 50);
}
currentMusicPlaybackSpeed = speed;
} else {
currentPlaybackSpeed = speed;
@ -3058,6 +3128,19 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
audioPlayer.setStreamType(useFrontSpeaker ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC);
audioPlayer.play();
if (!messageObject.isVoice()) {
if (audioVolumeAnimator != null) {
audioVolumeAnimator.removeAllListeners();
audioVolumeAnimator.cancel();
}
audioVolumeAnimator = ValueAnimator.ofFloat(audioVolume, 1f);
audioVolumeAnimator.addUpdateListener(audioVolumeUpdateListener);
audioVolumeAnimator.setDuration(300);
audioVolumeAnimator.start();
} else {
audioVolume = 1f;
setPlayerVolume();
}
} catch (Exception e) {
FileLog.e(e);
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingPlayStateChanged, playingMessageObject != null ? playingMessageObject.getId() : 0);
@ -3181,7 +3264,26 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
stopProgressTimer();
try {
if (audioPlayer != null) {
audioPlayer.pause();
if (!playingMessageObject.isVoice()) {
if (audioVolumeAnimator != null) {
audioVolumeAnimator.removeAllUpdateListeners();
audioVolumeAnimator.cancel();
}
audioVolumeAnimator = ValueAnimator.ofFloat(1f, 0);
audioVolumeAnimator.addUpdateListener(audioVolumeUpdateListener);
audioVolumeAnimator.setDuration(300);
audioVolumeAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (audioPlayer != null) {
audioPlayer.pause();
}
}
});
audioVolumeAnimator.start();
} else {
audioPlayer.pause();
}
} else if (videoPlayer != null) {
videoPlayer.pause();
}
@ -3202,6 +3304,19 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
try {
startProgressTimer(playingMessageObject);
if (audioVolumeAnimator != null) {
audioVolumeAnimator.removeAllListeners();
audioVolumeAnimator.cancel();
}
if (!messageObject.isVoice()) {
audioVolumeAnimator = ValueAnimator.ofFloat(audioVolume, 1f);
audioVolumeAnimator.addUpdateListener(audioVolumeUpdateListener);
audioVolumeAnimator.setDuration(300);
audioVolumeAnimator.start();
} else {
audioVolume = 1f;
setPlayerVolume();
}
if (audioPlayer != null) {
audioPlayer.play();
} else if (videoPlayer != null) {
@ -4400,6 +4515,25 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
});
}
public void pauseByRewind() {
if (audioPlayer != null) {
audioPlayer.pause();
}
}
public void resumeByRewind() {
if (audioPlayer != null && playingMessageObject != null && !isPaused) {
if (audioPlayer.isBuffering()) {
MessageObject currentMessageObject = playingMessageObject;
cleanupPlayer(false, false);
playMessage(currentMessageObject);
} else {
audioPlayer.play();
}
}
}
private static class VideoConvertRunnable implements Runnable {
private VideoConvertMessage convertMessage;

View File

@ -2153,6 +2153,10 @@ public class MediaDataController extends BaseController {
messagesSearchEndReached[1] = res.messages.isEmpty();
messagesSearchCount[1] = res instanceof TLRPC.TL_messages_messagesSlice ? res.count : res.messages.size();
searchMessagesInChat(req.q, dialogId, mergeDialogId, guid, direction, replyMessageId, true, user, chat, jumpToMessage);
} else {
messagesSearchEndReached[1] = true;
messagesSearchCount[1] = 0;
searchMessagesInChat(req.q, dialogId, mergeDialogId, guid, direction, replyMessageId, true, user, chat, jumpToMessage);
}
}
}), ConnectionsManager.RequestFlagFailOnServerErrors);

View File

@ -5315,7 +5315,7 @@ public class MessageObject {
}
public boolean needDrawForwarded() {
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_FWD) != 0 && messageOwner.fwd_from != null && (messageOwner.fwd_from.saved_from_peer == null || messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel && messageOwner.fwd_from.saved_from_peer.channel_id != messageOwner.fwd_from.from_id.channel_id) && UserConfig.getInstance(currentAccount).getClientUserId() != getDialogId();
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_FWD) != 0 && messageOwner.fwd_from != null && !messageOwner.fwd_from.imported && (messageOwner.fwd_from.saved_from_peer == null || messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel && messageOwner.fwd_from.saved_from_peer.channel_id != messageOwner.fwd_from.from_id.channel_id) && UserConfig.getInstance(currentAccount).getClientUserId() != getDialogId();
}
public static boolean isForwardedMessage(TLRPC.Message message) {
@ -5551,6 +5551,10 @@ public class MessageObject {
return messageOwner.fwd_from != null && !TextUtils.isEmpty(messageOwner.fwd_from.from_name);
}
public boolean isImportedForward() {
return messageOwner.fwd_from != null && messageOwner.fwd_from.imported;
}
public int getSenderId() {
if (messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null) {
if (messageOwner.fwd_from.saved_from_peer.user_id != 0) {

View File

@ -65,7 +65,7 @@ public class MessagesController extends BaseController implements NotificationCe
private ArrayList<Integer> joiningToChannels = new ArrayList<>();
private SparseArray<TLRPC.ExportedChatInvite> exportedChats = new SparseArray<>();
private SparseArray<TLRPC.TL_chatInviteExported> exportedChats = new SparseArray<>();
public ArrayList<TLRPC.RecentMeUrl> hintDialogs = new ArrayList<>();
private SparseArray<ArrayList<TLRPC.Dialog>> dialogsByFolder = new SparseArray<>();
@ -287,7 +287,11 @@ public class MessagesController extends BaseController implements NotificationCe
public boolean saveGifsWithStickers;
private String installReferer;
public Set<String> pendingSuggestions;
public Set<String> exportUri;
public Set<String> exportGroupUri;
public Set<String> exportPrivateUri;
public boolean autoarchiveAvailable;
public boolean suggestStickersApiOnly;
public ArrayList<String> gifSearchEmojies = new ArrayList<>();
public HashSet<String> diceEmojies;
public HashMap<String, DiceFrameSuccess> diceSuccess = new HashMap<>();
@ -717,6 +721,8 @@ public class MessagesController extends BaseController implements NotificationCe
filtersEnabled = mainPreferences.getBoolean("filtersEnabled", false);
showFiltersTooltip = mainPreferences.getBoolean("showFiltersTooltip", false);
autoarchiveAvailable = mainPreferences.getBoolean("autoarchiveAvailable", false);
suggestStickersApiOnly = mainPreferences.getBoolean("suggestStickersApiOnly", false);
pendingSuggestions = mainPreferences.getStringSet("pendingSuggestions", null);
if (pendingSuggestions != null) {
pendingSuggestions = new HashSet<>(pendingSuggestions);
@ -724,6 +730,30 @@ public class MessagesController extends BaseController implements NotificationCe
pendingSuggestions = new HashSet<>();
}
exportUri = mainPreferences.getStringSet("exportUri", null);
if (exportUri != null) {
exportUri = new HashSet<>(exportUri);
} else {
exportUri = new HashSet<>();
exportUri.add("content://com.whatsapp.provider.media/export_chat/");
}
exportGroupUri = mainPreferences.getStringSet("exportGroupUri", null);
if (exportGroupUri != null) {
exportGroupUri = new HashSet<>(exportGroupUri);
} else {
exportGroupUri = new HashSet<>();
exportGroupUri.add("@g.us/");
}
exportPrivateUri = mainPreferences.getStringSet("exportPrivateUri", null);
if (exportPrivateUri != null) {
exportPrivateUri = new HashSet<>(exportPrivateUri);
} else {
exportPrivateUri = new HashSet<>();
exportPrivateUri.add("@s.whatsapp.net/");
}
Set<String> emojies = mainPreferences.getStringSet("diceEmojies", null);
if (emojies == null) {
diceEmojies = new HashSet<>();
@ -1452,6 +1482,74 @@ public class MessagesController extends BaseController implements NotificationCe
}
break;
}
case "stickers_emoji_suggest_only_api": {
if (value.value instanceof TLRPC.TL_jsonBool) {
TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value;
if (bool.value != suggestStickersApiOnly) {
suggestStickersApiOnly = bool.value;
editor.putBoolean("suggestStickersApiOnly", suggestStickersApiOnly);
changed = true;
}
}
break;
}
case "export_urls": {
HashSet<String> newExport = new HashSet<>();
if (value.value instanceof TLRPC.TL_jsonArray) {
TLRPC.TL_jsonArray array = (TLRPC.TL_jsonArray) value.value;
for (int b = 0, N2 = array.value.size(); b < N2; b++) {
TLRPC.JSONValue val = array.value.get(b);
if (val instanceof TLRPC.TL_jsonString) {
TLRPC.TL_jsonString string = (TLRPC.TL_jsonString) val;
newExport.add(string.value);
}
}
}
if (!exportUri.equals(newExport)) {
exportUri = newExport;
editor.putStringSet("exportUri", exportUri);
changed = true;
}
break;
}
case "export_group_urls": {
HashSet<String> newExport = new HashSet<>();
if (value.value instanceof TLRPC.TL_jsonArray) {
TLRPC.TL_jsonArray array = (TLRPC.TL_jsonArray) value.value;
for (int b = 0, N2 = array.value.size(); b < N2; b++) {
TLRPC.JSONValue val = array.value.get(b);
if (val instanceof TLRPC.TL_jsonString) {
TLRPC.TL_jsonString string = (TLRPC.TL_jsonString) val;
newExport.add(string.value);
}
}
}
if (!exportGroupUri.equals(newExport)) {
exportGroupUri = newExport;
editor.putStringSet("exportGroupUri", exportGroupUri);
changed = true;
}
break;
}
case "export_private_urls": {
HashSet<String> newExport = new HashSet<>();
if (value.value instanceof TLRPC.TL_jsonArray) {
TLRPC.TL_jsonArray array = (TLRPC.TL_jsonArray) value.value;
for (int b = 0, N2 = array.value.size(); b < N2; b++) {
TLRPC.JSONValue val = array.value.get(b);
if (val instanceof TLRPC.TL_jsonString) {
TLRPC.TL_jsonString string = (TLRPC.TL_jsonString) val;
newExport.add(string.value);
}
}
}
if (!exportPrivateUri.equals(newExport)) {
exportPrivateUri = newExport;
editor.putStringSet("exportPrivateUri", exportPrivateUri);
changed = true;
}
break;
}
case "pending_suggestions": {
HashSet<String> newSuggestions = new HashSet<>();
if (value.value instanceof TLRPC.TL_jsonArray) {
@ -2430,7 +2528,7 @@ public class MessagesController extends BaseController implements NotificationCe
});
}
public TLRPC.ExportedChatInvite getExportedInvite(int chat_id) {
public TLRPC.TL_chatInviteExported getExportedInvite(int chat_id) {
return exportedChats.get(chat_id);
}
@ -2461,12 +2559,14 @@ public class MessagesController extends BaseController implements NotificationCe
oldUser.username = null;
}
}
if (user.photo != null) {
oldUser.photo = user.photo;
oldUser.flags |= 32;
} else {
oldUser.flags = oldUser.flags &~ 32;
oldUser.photo = null;
if (user.apply_min_photo) {
if (user.photo != null) {
oldUser.photo = user.photo;
oldUser.flags |= 32;
} else {
oldUser.flags = oldUser.flags & ~32;
oldUser.photo = null;
}
}
}
} else {
@ -2485,7 +2585,6 @@ public class MessagesController extends BaseController implements NotificationCe
} else if (oldUser == null) {
users.put(user.id, user);
} else if (oldUser.min) {
user.min = false;
if (oldUser.bot) {
if (oldUser.username != null) {
user.username = oldUser.username;
@ -2495,12 +2594,14 @@ public class MessagesController extends BaseController implements NotificationCe
user.username = null;
}
}
if (oldUser.photo != null) {
user.photo = oldUser.photo;
user.flags |= 32;
} else {
user.flags = user.flags &~ 32;
user.photo = null;
if (oldUser.apply_min_photo) {
if (oldUser.photo != null) {
user.photo = oldUser.photo;
user.flags |= 32;
} else {
user.flags = user.flags & ~32;
user.photo = null;
}
}
users.put(user.id, user);
}
@ -2616,7 +2717,6 @@ public class MessagesController extends BaseController implements NotificationCe
} else if (oldChat == null) {
chats.put(chat.id, chat);
} else if (oldChat.min) {
chat.min = false;
chat.title = oldChat.title;
chat.photo = oldChat.photo;
chat.broadcast = oldChat.broadcast;
@ -2786,12 +2886,6 @@ public class MessagesController extends BaseController implements NotificationCe
ArrayList<TLRPC.Update> arrayList = new ArrayList<>();
for (int a = 0; a < res.dialogs.size(); a++) {
TLRPC.Dialog dialog = res.dialogs.get(a);
if (dialog.read_inbox_max_id == 0) {
dialog.read_inbox_max_id = 1;
}
if (dialog.read_outbox_max_id == 0) {
dialog.read_outbox_max_id = 1;
}
DialogObject.initDialog(dialog);
Integer value = dialogs_read_inbox_max.get(dialog.id);
@ -3066,7 +3160,7 @@ public class MessagesController extends BaseController implements NotificationCe
users.add(userFull.user);
putUsers(users, false);
getMessagesStorage().putUsersAndChats(users, null, false, true);
if (names != null && !names.equals(userFull.user.first_name + userFull.user.last_name + userFull.user.username)) {
if (!names.equals(userFull.user.first_name + userFull.user.last_name + userFull.user.username)) {
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_NAME);
}
if (userFull.bot_info instanceof TLRPC.TL_botInfo) {
@ -3200,12 +3294,13 @@ public class MessagesController extends BaseController implements NotificationCe
}
SharedPreferences.Editor editor = notificationsPreferences.edit();
editor.putInt("dialog_bar_vis3" + dialogId, 3);
editor.remove("dialog_bar_invite" + dialogId);
editor.commit();
if ((int) dialogId != 0) {
TLRPC.TL_messages_hidePeerSettingsBar req = new TLRPC.TL_messages_hidePeerSettingsBar();
if (currentUser != null) {
req.peer = getInputPeer(currentUser.id);
} else if (currentChat != null) {
} else {
req.peer = getInputPeer(-currentChat.id);
}
getConnectionsManager().sendRequest(req, (response, error) -> {
@ -3263,9 +3358,9 @@ public class MessagesController extends BaseController implements NotificationCe
return;
}
SharedPreferences.Editor editor = notificationsPreferences.edit();
boolean bar_hidden = !settings.report_spam && !settings.add_contact && !settings.block_contact && !settings.share_contact && !settings.report_geo;
boolean bar_hidden = !settings.report_spam && !settings.add_contact && !settings.block_contact && !settings.share_contact && !settings.report_geo && !settings.invite_members;
if (BuildVars.LOGS_ENABLED) {
FileLog.d("peer settings loaded for " + dialogId + " add = " + settings.add_contact + " block = " + settings.block_contact + " spam = " + settings.report_spam + " share = " + settings.share_contact + " geo = " + settings.report_geo + " hide = " + bar_hidden + " distance = " + settings.geo_distance);
FileLog.d("peer settings loaded for " + dialogId + " add = " + settings.add_contact + " block = " + settings.block_contact + " spam = " + settings.report_spam + " share = " + settings.share_contact + " geo = " + settings.report_geo + " hide = " + bar_hidden + " distance = " + settings.geo_distance + " invite = " + settings.invite_members);
}
editor.putInt("dialog_bar_vis3" + dialogId, bar_hidden ? 1 : 2);
editor.putBoolean("dialog_bar_share" + dialogId, settings.share_contact);
@ -3275,6 +3370,7 @@ public class MessagesController extends BaseController implements NotificationCe
editor.putBoolean("dialog_bar_exception" + dialogId, settings.need_contacts_exception);
editor.putBoolean("dialog_bar_location" + dialogId, settings.report_geo);
editor.putBoolean("dialog_bar_archived" + dialogId, settings.autoarchived);
editor.putBoolean("dialog_bar_invite" + dialogId, settings.invite_members);
if (notificationsPreferences.getInt("dialog_bar_distance" + dialogId, -1) != -2) {
if ((settings.flags & 64) != 0) {
editor.putInt("dialog_bar_distance" + dialogId, settings.geo_distance);
@ -3313,7 +3409,7 @@ public class MessagesController extends BaseController implements NotificationCe
TLRPC.TL_messages_getPeerSettings req = new TLRPC.TL_messages_getPeerSettings();
if (currentUser != null) {
req.peer = getInputPeer(currentUser.id);
} else if (currentChat != null) {
} else {
req.peer = getInputPeer(-currentChat.id);
}
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
@ -3368,7 +3464,7 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
protected void processNewDifferenceParams(int seq, int pts, int date, int pts_count) {
public void processNewDifferenceParams(int seq, int pts, int date, int pts_count) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("processNewDifferenceParams seq = " + seq + " pts = " + pts + " date = " + date + " pts_count = " + pts_count);
}
@ -4338,7 +4434,10 @@ public class MessagesController extends BaseController implements NotificationCe
}
if (first == 1 && max_id == 0) {
TLRPC.InputPeer peerFinal = peer;
getMessagesStorage().getDialogMaxMessageId(did, (param) -> deleteDialog(did, 2, onlyHistory, Math.max(0, param), revoke, peerFinal, taskId));
getMessagesStorage().getDialogMaxMessageId(did, (param) -> {
deleteDialog(did, 2, onlyHistory, Math.max(0, param), revoke, peerFinal, taskId);
checkIfFolderEmpty(1);
});
return;
}
if (onlyHistory == 0 || onlyHistory == 3) {
@ -4351,6 +4450,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (first != 0) {
boolean isPromoDialog = false;
getMessagesStorage().deleteDialog(did, onlyHistory);
getNotificationCenter().postNotificationName(NotificationCenter.dialogDeleted, did);
TLRPC.Dialog dialog = dialogs_dict.get(did);
if (onlyHistory == 0 || onlyHistory == 3) {
getNotificationsController().deleteNotificationChannel(did);
@ -4545,7 +4645,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (onlyHistory == 1) {
getSecretChatHelper().sendClearHistoryMessage(getEncryptedChat(high_id), null);
} else {
getSecretChatHelper().declineSecretChat(high_id);
getSecretChatHelper().declineSecretChat(high_id, revoke);
}
}
}
@ -7097,7 +7197,7 @@ public class MessagesController extends BaseController implements NotificationCe
channelsPts.put(-(int) d.id, d.pts);
} else if ((int) d.id < 0) {
TLRPC.Chat chat = chatsDict.get(-(int) d.id);
if (chat != null && chat.migrated_to != null) {
if (chat != null && (chat.migrated_to != null || ChatObject.isNotInChat(chat))) {
continue;
}
}
@ -7676,7 +7776,7 @@ public class MessagesController extends BaseController implements NotificationCe
}
} else if (message.peer_id.chat_id != 0) {
TLRPC.Chat chat = chatsDict.get(message.peer_id.chat_id);
if (chat != null && chat.migrated_to != null) {
if (chat != null && (chat.migrated_to != null || ChatObject.isNotInChat(chat))) {
continue;
}
}
@ -7695,7 +7795,7 @@ public class MessagesController extends BaseController implements NotificationCe
}
} else if ((int) d.id < 0) {
TLRPC.Chat chat = chatsDict.get(-(int) d.id);
if (chat != null && chat.migrated_to != null) {
if (chat != null && (chat.migrated_to != null || ChatObject.isNotInChat(chat))) {
continue;
}
}
@ -8315,8 +8415,8 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
public int createChat(String title, ArrayList<Integer> selectedContacts, final String about, int type, Location location, String locationAddress, final BaseFragment fragment) {
if (type == ChatObject.CHAT_TYPE_CHAT) {
public int createChat(String title, ArrayList<Integer> selectedContacts, final String about, int type, boolean forImport, Location location, String locationAddress, final BaseFragment fragment) {
if (type == ChatObject.CHAT_TYPE_CHAT && !forImport) {
final TLRPC.TL_messages_createChat req = new TLRPC.TL_messages_createChat();
req.title = title;
for (int a = 0; a < selectedContacts.size(); a++) {
@ -8346,11 +8446,12 @@ public class MessagesController extends BaseController implements NotificationCe
}
});
}, ConnectionsManager.RequestFlagFailOnServerErrors);
} else if (type == ChatObject.CHAT_TYPE_CHANNEL || type == ChatObject.CHAT_TYPE_MEGAGROUP) {
} else if (forImport || type == ChatObject.CHAT_TYPE_CHANNEL || type == ChatObject.CHAT_TYPE_MEGAGROUP) {
final TLRPC.TL_channels_createChannel req = new TLRPC.TL_channels_createChannel();
req.title = title;
req.about = about != null ? about : "";
if (type == ChatObject.CHAT_TYPE_MEGAGROUP) {
req.for_import = forImport;
if (forImport || type == ChatObject.CHAT_TYPE_MEGAGROUP) {
req.megagroup = true;
} else {
req.broadcast = true;
@ -8389,18 +8490,20 @@ public class MessagesController extends BaseController implements NotificationCe
public void convertToMegaGroup(final Context context, int chat_id, BaseFragment fragment, MessagesStorage.IntCallback convertRunnable) {
TLRPC.TL_messages_migrateChat req = new TLRPC.TL_messages_migrateChat();
req.chat_id = chat_id;
final AlertDialog progressDialog = new AlertDialog(context, 3);
final AlertDialog progressDialog = context != null ? new AlertDialog(context, 3) : null;
final int reqId = getConnectionsManager().sendRequest(req, (response, error) -> {
if (error == null) {
AndroidUtilities.runOnUIThread(() -> {
if (!((Activity) context).isFinishing()) {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e(e);
if (context != null) {
AndroidUtilities.runOnUIThread(() -> {
if (!((Activity) context).isFinishing()) {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e(e);
}
}
}
});
});
}
TLRPC.Updates updates = (TLRPC.Updates) response;
processUpdates((TLRPC.Updates) response, false);
AndroidUtilities.runOnUIThread(() -> {
@ -8419,22 +8522,26 @@ public class MessagesController extends BaseController implements NotificationCe
if (convertRunnable != null) {
convertRunnable.run(0);
}
if (!((Activity) context).isFinishing()) {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e(e);
if (context != null) {
if (!((Activity) context).isFinishing()) {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e(e);
}
AlertsCreator.processError(currentAccount, error, fragment, req, false);
}
AlertsCreator.processError(currentAccount, error, fragment, req, false);
}
});
}
});
progressDialog.setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(reqId, true));
try {
progressDialog.show();
} catch (Exception e) {
//don't promt
if (progressDialog != null) {
progressDialog.setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(reqId, true));
try {
progressDialog.show();
} catch (Exception e) {
//don't promt
}
}
}
@ -8635,84 +8742,68 @@ public class MessagesController extends BaseController implements NotificationCe
if (user == null) {
return;
}
if (chat_id > 0) {
final TLRPC.InputUser inputUser = getInputUser(user);
TLObject request;
TLRPC.Chat chat = getChat(chat_id);
final boolean isChannel = ChatObject.isChannel(chat);
if (isChannel) {
if (inputUser instanceof TLRPC.TL_inputUserSelf) {
if (chat.creator && forceDelete) {
TLRPC.TL_channels_deleteChannel req = new TLRPC.TL_channels_deleteChannel();
req.channel = getInputChannel(chat);
request = req;
} else {
TLRPC.TL_channels_leaveChannel req = new TLRPC.TL_channels_leaveChannel();
req.channel = getInputChannel(chat);
request = req;
}
} else {
TLRPC.TL_channels_editBanned req = new TLRPC.TL_channels_editBanned();
final TLRPC.InputUser inputUser = getInputUser(user);
TLObject request;
TLRPC.Chat chat = getChat(chat_id);
final boolean isChannel = ChatObject.isChannel(chat);
if (isChannel) {
if (inputUser instanceof TLRPC.TL_inputUserSelf) {
if (chat.creator && forceDelete) {
TLRPC.TL_channels_deleteChannel req = new TLRPC.TL_channels_deleteChannel();
req.channel = getInputChannel(chat);
request = req;
} else {
TLRPC.TL_channels_leaveChannel req = new TLRPC.TL_channels_leaveChannel();
req.channel = getInputChannel(chat);
req.user_id = inputUser;
req.banned_rights = new TLRPC.TL_chatBannedRights();
req.banned_rights.view_messages = true;
req.banned_rights.send_media = true;
req.banned_rights.send_messages = true;
req.banned_rights.send_stickers = true;
req.banned_rights.send_gifs = true;
req.banned_rights.send_games = true;
req.banned_rights.send_inline = true;
req.banned_rights.embed_links = true;
req.banned_rights.pin_messages = true;
req.banned_rights.send_polls = true;
req.banned_rights.invite_users = true;
req.banned_rights.change_info = true;
request = req;
}
} else {
TLRPC.TL_messages_deleteChatUser req = new TLRPC.TL_messages_deleteChatUser();
req.chat_id = chat_id;
req.user_id = getInputUser(user);
TLRPC.TL_channels_editBanned req = new TLRPC.TL_channels_editBanned();
req.channel = getInputChannel(chat);
req.user_id = inputUser;
req.banned_rights = new TLRPC.TL_chatBannedRights();
req.banned_rights.view_messages = true;
req.banned_rights.send_media = true;
req.banned_rights.send_messages = true;
req.banned_rights.send_stickers = true;
req.banned_rights.send_gifs = true;
req.banned_rights.send_games = true;
req.banned_rights.send_inline = true;
req.banned_rights.embed_links = true;
req.banned_rights.pin_messages = true;
req.banned_rights.send_polls = true;
req.banned_rights.invite_users = true;
req.banned_rights.change_info = true;
request = req;
}
if (user.id == getUserConfig().getClientUserId()) {
deleteDialog(-chat_id, 0, revoke);
}
getConnectionsManager().sendRequest(request, (response, error) -> {
if (error != null) {
return;
}
final TLRPC.Updates updates = (TLRPC.Updates) response;
processUpdates(updates, false);
if (isChannel && !(inputUser instanceof TLRPC.TL_inputUserSelf)) {
AndroidUtilities.runOnUIThread(() -> loadFullChat(chat_id, 0, true), 1000);
}
}, ConnectionsManager.RequestFlagInvokeAfter);
} else {
if (info instanceof TLRPC.TL_chatFull) {
TLRPC.Chat chat = getChat(chat_id);
chat.participants_count--;
ArrayList<TLRPC.Chat> chatArrayList = new ArrayList<>();
chatArrayList.add(chat);
getMessagesStorage().putUsersAndChats(null, chatArrayList, true, true);
if (forceDelete) {
TLRPC.TL_messages_deleteChat req = new TLRPC.TL_messages_deleteChat();
req.chat_id = chat_id;
getConnectionsManager().sendRequest(req, (response, error) -> {
boolean changed = false;
for (int a = 0; a < info.participants.participants.size(); a++) {
TLRPC.ChatParticipant p = info.participants.participants.get(a);
if (p.user_id == user.id) {
info.participants.participants.remove(a);
changed = true;
break;
}
}
if (changed) {
getMessagesStorage().updateChatInfo(info, true);
getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false);
}
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_CHAT_MEMBERS);
});
return;
}
TLRPC.TL_messages_deleteChatUser req = new TLRPC.TL_messages_deleteChatUser();
req.chat_id = chat_id;
req.user_id = getInputUser(user);
req.revoke_history = true;
request = req;
}
if (user.id == getUserConfig().getClientUserId()) {
deleteDialog(-chat_id, 0, revoke);
}
getConnectionsManager().sendRequest(request, (response, error) -> {
if (error != null) {
return;
}
final TLRPC.Updates updates = (TLRPC.Updates) response;
processUpdates(updates, false);
if (isChannel && !(inputUser instanceof TLRPC.TL_inputUserSelf)) {
AndroidUtilities.runOnUIThread(() -> loadFullChat(chat_id, 0, true), 1000);
}
}, ConnectionsManager.RequestFlagInvokeAfter);
}
public void changeChatTitle(int chat_id, String title) {
@ -10987,6 +11078,7 @@ public class MessagesController extends BaseController implements NotificationCe
SparseArray<ArrayList<Integer>> deletedMessages = null;
SparseArray<ArrayList<Integer>> scheduledDeletedMessages = null;
SparseArray<ArrayList<Integer>> groupSpeakingActions = null;
LongSparseArray<Integer> importingActions = null;
SparseIntArray clearHistoryMessages = null;
ArrayList<TLRPC.ChatParticipants> chatInfoToUpdate = null;
ArrayList<TLRPC.Update> updatesOnMainThread = null;
@ -11338,11 +11430,17 @@ public class MessagesController extends BaseController implements NotificationCe
action = update.action;
threadId = 0;
}
if (userId != getUserConfig().getClientUserId()) {
long uid = -chatId;
if (uid == 0) {
uid = userId;
long uid = -chatId;
if (uid == 0) {
uid = userId;
}
if (action instanceof TLRPC.TL_sendMessageHistoryImportAction) {
if (importingActions == null) {
importingActions = new LongSparseArray<>();
}
TLRPC.TL_sendMessageHistoryImportAction importAction = (TLRPC.TL_sendMessageHistoryImportAction) action;
importingActions.put(uid, importAction.progress);
} else if (userId != getUserConfig().getClientUserId()) {
if (action instanceof TLRPC.TL_speakingInGroupCallAction) {
if (chatId != 0) {
if (groupSpeakingActions == null) {
@ -12099,6 +12197,7 @@ public class MessagesController extends BaseController implements NotificationCe
final ArrayList<ImageLoader.MessageThumb> updateMessageThumbs = messageThumbs;
final ArrayList<TLRPC.TL_updateFolderPeers> folderUpdatesFinal = folderUpdates;
final SparseArray<ArrayList<Integer>> groupSpeakingActionsFinal = groupSpeakingActions;
final LongSparseArray<Integer> importingActionsFinal = importingActions;
AndroidUtilities.runOnUIThread(() -> {
int updateMask = interfaceUpdateMaskFinal;
@ -12358,7 +12457,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (chat != null) {
if (dialog == null && chat instanceof TLRPC.TL_channel && !chat.left) {
Utilities.stageQueue.postRunnable(() -> getChannelDifference(update.channel_id, 1, 0, null));
} else if (chat.left && dialog != null && (promoDialog == null || promoDialog.id != dialog.id)) {
} else if (ChatObject.isNotInChat(chat) && dialog != null && (promoDialog == null || promoDialog.id != dialog.id)) {
deleteDialog(dialog.id, 0);
}
if (chat instanceof TLRPC.TL_channelForbidden || chat.kicked) {
@ -12394,6 +12493,10 @@ public class MessagesController extends BaseController implements NotificationCe
VoIPService.getSharedInstance().onGroupCallUpdated(updateGroupCall.call);
}
}
TLRPC.Dialog dialog = dialogs_dict.get(-chat.id);
if (dialog != null) {
deleteDialog(dialog.id, 0);
}
}
updateMask |= UPDATE_MASK_CHAT;
loadFullChat(update.chat_id, 0, true);
@ -12647,6 +12750,16 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
}
if (importingActionsFinal != null) {
for (int a = 0, N = importingActionsFinal.size(); a < N; a++) {
long did = importingActionsFinal.keyAt(a);
SendMessagesHelper.ImportingHistory importingHistory = getSendMessagesHelper().getImportingHistory(did);
if (importingHistory == null) {
continue;
}
importingHistory.setImportProgress(importingActionsFinal.valueAt(a));
}
}
if (webPagesFinal != null) {
getNotificationCenter().postNotificationName(NotificationCenter.didReceivedWebpagesInUpdates, webPagesFinal);
for (int i = 0; i < 2; i++) {
@ -13076,7 +13189,7 @@ public class MessagesController extends BaseController implements NotificationCe
}
if (message.messageOwner.action instanceof TLRPC.TL_messageActionGroupCall) {
TLRPC.ChatFull chatFull = getChatFull(message.messageOwner.peer_id.channel_id);
if (chatFull != null && (chatFull.call == null || chatFull.call != null && chatFull.call.id != message.messageOwner.action.call.id)) {
if (chatFull != null && (chatFull.call == null || chatFull.call.id != message.messageOwner.action.call.id)) {
loadFullChat(message.messageOwner.peer_id.channel_id, 0, true);
}
}

View File

@ -8,6 +8,7 @@
package org.telegram.messenger;
import android.appwidget.AppWidgetManager;
import android.content.SharedPreferences;
import android.os.SystemClock;
import android.text.SpannableStringBuilder;
@ -87,7 +88,7 @@ public class MessagesStorage extends BaseController {
private CountDownLatch openSync = new CountDownLatch(1);
private static volatile MessagesStorage[] Instance = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT];
private final static int LAST_DB_VERSION = 74;
private final static int LAST_DB_VERSION = 76;
public static MessagesStorage getInstance(int num) {
MessagesStorage localInstance = Instance[num];
@ -332,7 +333,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE TABLE bot_keyboard(uid INTEGER PRIMARY KEY, mid INTEGER, info BLOB)").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS bot_keyboard_idx_mid ON bot_keyboard(mid);").stepThis().dispose();
database.executeFast("CREATE TABLE chat_settings_v2(uid INTEGER PRIMARY KEY, info BLOB, pinned INTEGER, online INTEGER, inviter INTEGER)").stepThis().dispose();
database.executeFast("CREATE TABLE chat_settings_v2(uid INTEGER PRIMARY KEY, info BLOB, pinned INTEGER, online INTEGER, inviter INTEGER, links INTEGER)").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS chat_settings_pinned_idx ON chat_settings_v2(uid, pinned) WHERE pinned != 0;").stepThis().dispose();
database.executeFast("CREATE TABLE user_settings(uid INTEGER PRIMARY KEY, info BLOB, pinned INTEGER)").stepThis().dispose();
@ -371,6 +372,9 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE TABLE requested_holes(uid INTEGER, seq_out_start INTEGER, seq_out_end INTEGER, PRIMARY KEY (uid, seq_out_start, seq_out_end));").stepThis().dispose();
database.executeFast("CREATE TABLE sharing_locations(uid INTEGER PRIMARY KEY, mid INTEGER, date INTEGER, period INTEGER, message BLOB, proximity INTEGER);").stepThis().dispose();
database.executeFast("CREATE TABLE shortcut_widget(id INTEGER, did INTEGER, ord INTEGER, PRIMARY KEY (id, did));").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS shortcut_widget_did ON shortcut_widget(did);").stepThis().dispose();
database.executeFast("CREATE TABLE emoji_keywords_v2(lang TEXT, keyword TEXT, emoji TEXT, PRIMARY KEY(lang, keyword, emoji));").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS emoji_keywords_v2_keyword ON emoji_keywords_v2(keyword);").stepThis().dispose();
database.executeFast("CREATE TABLE emoji_keywords_info_v2(lang TEXT PRIMARY KEY, alias TEXT, version INTEGER, date INTEGER);").stepThis().dispose();
@ -625,7 +629,7 @@ public class MessagesStorage extends BaseController {
chatFull.id = chat_id;
chatFull.chat_photo = new TLRPC.TL_photoEmpty();
chatFull.notify_settings = new TLRPC.TL_peerNotifySettingsEmpty_layer77();
chatFull.exported_invite = new TLRPC.TL_chatInviteEmpty();
chatFull.exported_invite = null;
chatFull.participants = participants;
NativeByteBuffer data2 = new NativeByteBuffer(chatFull.getObjectSize());
chatFull.serializeToStream(data2);
@ -924,6 +928,17 @@ public class MessagesStorage extends BaseController {
version = 74;
}
if (version == 74) {
database.executeFast("CREATE TABLE IF NOT EXISTS shortcut_widget(id INTEGER, did INTEGER, ord INTEGER, PRIMARY KEY (id, did));").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS shortcut_widget_did ON shortcut_widget(did);").stepThis().dispose();
database.executeFast("PRAGMA user_version = 75").stepThis().dispose();
version = 75;
}
if (version == 75) {
executeNoException("ALTER TABLE chat_settings_v2 ADD COLUMN links INTEGER default 0");
database.executeFast("PRAGMA user_version = 76").stepThis().dispose();
version = 76;
}
if (version == 76) {
}
} catch (Exception e) {
@ -3111,6 +3126,7 @@ public class MessagesStorage extends BaseController {
}
state5.dispose();
state6.dispose();
updateWidgets(did);
}
cursor.dispose();
return;
@ -3126,6 +3142,7 @@ public class MessagesStorage extends BaseController {
getMediaDataController().clearBotKeyboard(did, null);
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.needReloadRecentDialogsSearch));
resetAllUnreadCounters(false);
updateWidgets(did);
} catch (Exception e) {
FileLog.e(e);
}
@ -4506,6 +4523,7 @@ public class MessagesStorage extends BaseController {
if (dialogsToUpdate.size() > 0 || dialogsToUpdateMentions.size() > 0) {
database.beginTransaction();
if (dialogsToUpdate.size() > 0) {
ArrayList<Long> dids = new ArrayList<>();
SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET unread_count = ? WHERE did = ?");
for (int a = 0; a < dialogsToUpdate.size(); a++) {
long did = dialogsToUpdate.keyAt(a);
@ -4526,8 +4544,10 @@ public class MessagesStorage extends BaseController {
state.bindInteger(1, newCount);
state.bindLong(2, did);
state.step();
dids.add(did);
}
state.dispose();
updateWidgets(dids);
}
if (dialogsToUpdateMentions.size() > 0) {
SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET unread_count_i = ? WHERE did = ?");
@ -4868,15 +4888,32 @@ public class MessagesStorage extends BaseController {
});
}
public void saveChatLinksCount(int chatId, int linksCount) {
storageQueue.postRunnable(() -> {
try {
SQLitePreparedStatement state = database.executeFast("UPDATE chat_settings_v2 SET links = ? WHERE uid = ?");
state.requery();
state.bindInteger(1, linksCount);
state.bindInteger(2, chatId);
state.step();
state.dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
public void updateChatInfo(final TLRPC.ChatFull info, final boolean ifExist) {
storageQueue.postRunnable(() -> {
try {
int currentOnline = -1;
int inviter = 0;
SQLiteCursor cursor = database.queryFinalized("SELECT online, inviter FROM chat_settings_v2 WHERE uid = " + info.id);
int links = 0;
SQLiteCursor cursor = database.queryFinalized("SELECT online, inviter, links FROM chat_settings_v2 WHERE uid = " + info.id);
if (cursor.next()) {
currentOnline = cursor.intValue(0);
info.inviterId = cursor.intValue(1);
links = cursor.intValue(2);
}
cursor.dispose();
if (ifExist && currentOnline == -1) {
@ -4887,7 +4924,11 @@ public class MessagesStorage extends BaseController {
info.online_count = currentOnline;
}
SQLitePreparedStatement state = database.executeFast("REPLACE INTO chat_settings_v2 VALUES(?, ?, ?, ?, ?)");
if (links >= 0) {
info.invitesCount = links;
}
SQLitePreparedStatement state = database.executeFast("REPLACE INTO chat_settings_v2 VALUES(?, ?, ?, ?, ?, ?)");
NativeByteBuffer data = new NativeByteBuffer(info.getObjectSize());
info.serializeToStream(data);
state.bindInteger(1, info.id);
@ -4895,6 +4936,7 @@ public class MessagesStorage extends BaseController {
state.bindInteger(3, info.pinned_msg_id);
state.bindInteger(4, info.online_count);
state.bindInteger(5, info.inviterId);
state.bindInteger(6, info.invitesCount);
state.step();
state.dispose();
data.reuse();
@ -5231,7 +5273,7 @@ public class MessagesStorage extends BaseController {
boolean pinnedEndReached = false;
try {
SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned, online, inviter FROM chat_settings_v2 WHERE uid = " + chatId);
SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned, online, inviter, links FROM chat_settings_v2 WHERE uid = " + chatId);
if (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
@ -5240,6 +5282,7 @@ public class MessagesStorage extends BaseController {
info.pinned_msg_id = cursor.intValue(1);
info.online_count = cursor.intValue(2);
info.inviterId = cursor.intValue(3);
info.invitesCount = cursor.intValue(4);
}
}
cursor.dispose();
@ -5465,6 +5508,7 @@ public class MessagesStorage extends BaseController {
dialogsToUpdate.put(dialog_id, unreadCount);
updateFiltersReadCounter(dialogsToUpdate, null, true);
}
updateWidgets(dialog_id);
} catch (Exception e) {
FileLog.e(e);
}
@ -6110,7 +6154,7 @@ public class MessagesStorage extends BaseController {
if (load_type == 3 && minDate == 0) {
cursor = database.queryFinalized("SELECT inbox_max, unread_count, date, unread_count_i FROM dialogs WHERE did = " + dialogId);
if (cursor.next()) {
min_unread_id = cursor.intValue(0) + 1;
min_unread_id = Math.max(1, cursor.intValue(0)) + 1;
count_unread = cursor.intValue(1);
max_unread_date = cursor.intValue(2);
mentions_unread = cursor.intValue(3);
@ -6120,7 +6164,7 @@ public class MessagesStorage extends BaseController {
if (load_type == 2) {
cursor = database.queryFinalized("SELECT inbox_max, unread_count, date, unread_count_i FROM dialogs WHERE did = " + dialogId);
if (cursor.next()) {
messageMaxId = max_id_query = min_unread_id = cursor.intValue(0);
messageMaxId = max_id_query = min_unread_id = Math.max(1, cursor.intValue(0));
count_unread = cursor.intValue(1);
max_unread_date = cursor.intValue(2);
mentions_unread = cursor.intValue(3);
@ -6793,6 +6837,122 @@ public class MessagesStorage extends BaseController {
return result[0] != null ? result : null;
}
private void updateWidgets(long did) {
ArrayList<Long> dids = new ArrayList<>();
dids.add(did);
updateWidgets(dids);
}
private void updateWidgets(ArrayList<Long> dids) {
try {
AppWidgetManager appWidgetManager = null;
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT DISTINCT id FROM shortcut_widget WHERE did IN(%s)", TextUtils.join(",", dids)));
while (cursor.next()) {
if (appWidgetManager == null) {
appWidgetManager = AppWidgetManager.getInstance(ApplicationLoader.applicationContext);
}
appWidgetManager.notifyAppWidgetViewDataChanged(cursor.intValue(0), R.id.list_view);
}
cursor.dispose();
} catch (Exception e) {
FileLog.e(e);
}
}
public void putWidgetDialogs(int widgetId, ArrayList<Long> dids) {
storageQueue.postRunnable(() -> {
try {
SQLitePreparedStatement state = database.executeFast("REPLACE INTO shortcut_widget VALUES(?, ?, ?)");
for (int a = 0, N = dids.size(); a < N; a++) {
long did = dids.get(a);
state.requery();
state.bindInteger(1, widgetId);
state.bindInteger(2, (int) did);
state.bindInteger(3, a);
state.step();
}
state.dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
public void clearWidgetDialogs(int widgetId) {
storageQueue.postRunnable(() -> {
try {
database.executeFast("DELETE FROM shortcut_widget WHERE id = " + widgetId).stepThis().dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
public void getWidgetDialogs(int widgetId, ArrayList<Integer> dids, LongSparseArray<TLRPC.Dialog> dialogs, LongSparseArray<TLRPC.Message> messages, ArrayList<TLRPC.User> users, ArrayList<TLRPC.Chat> chats) {
final CountDownLatch countDownLatch = new CountDownLatch(1);
storageQueue.postRunnable(() -> {
try {
ArrayList<Integer> usersToLoad = new ArrayList<>();
ArrayList<Integer> chatsToLoad = new ArrayList<>();
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT did FROM shortcut_widget WHERE id = %d ORDER BY ord ASC", widgetId));
while (cursor.next()) {
int id = cursor.intValue(0);
dids.add(id);
if (id > 0) {
usersToLoad.add(id);
} else {
chatsToLoad.add(-id);
}
}
cursor.dispose();
cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, m.date FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid WHERE d.did IN(%s)", TextUtils.join(",", dids)));
while (cursor.next()) {
long dialogId = cursor.longValue(0);
TLRPC.Dialog dialog = new TLRPC.TL_dialog();
dialog.id = dialogId;
dialog.top_message = cursor.intValue(1);
dialog.unread_count = cursor.intValue(2);
dialog.last_message_date = cursor.intValue(3);
dialogs.put(dialog.id, dialog);
NativeByteBuffer data = cursor.byteBufferValue(4);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
message.readAttachPath(data, getUserConfig().clientUserId);
data.reuse();
MessageObject.setUnreadFlags(message, cursor.intValue(5));
message.id = cursor.intValue(6);
message.send_state = cursor.intValue(7);
int date = cursor.intValue(8);
if (date != 0) {
dialog.last_message_date = date;
}
message.dialog_id = dialog.id;
messages.put(dialog.id, message);
addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad);
}
}
cursor.dispose();
if (!chatsToLoad.isEmpty()) {
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
}
if (!usersToLoad.isEmpty()) {
getUsersInternal(TextUtils.join(",", usersToLoad), users);
}
} catch (Exception e) {
FileLog.e(e);
} finally {
countDownLatch.countDown();
}
});
try {
countDownLatch.await();
} catch (Exception e) {
FileLog.e(e);
}
}
public void putSentFile(final String path, final TLObject file, final int type, String parent) {
if (path == null || file == null || parent == null) {
return;
@ -7158,12 +7318,14 @@ public class MessagesStorage extends BaseController {
oldUser.username = null;
oldUser.flags = oldUser.flags & ~8;
}
if (user.photo != null) {
oldUser.photo = user.photo;
oldUser.flags |= 32;
} else {
oldUser.photo = null;
oldUser.flags = oldUser.flags & ~32;
if (user.apply_min_photo) {
if (user.photo != null) {
oldUser.photo = user.photo;
oldUser.flags |= 32;
} else {
oldUser.photo = null;
oldUser.flags = oldUser.flags & ~32;
}
}
user = oldUser;
}
@ -8338,6 +8500,7 @@ public class MessagesStorage extends BaseController {
SQLitePreparedStatement state_dialogs_replace = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
SQLitePreparedStatement state_dialogs_update = database.executeFast("UPDATE dialogs SET date = ?, unread_count = ?, last_mid = ?, unread_count_i = ? WHERE did = ?");
ArrayList<Long> dids = new ArrayList<>();
for (int a = 0; a < messagesMap.size(); a++) {
long key = messagesMap.keyAt(a);
if (key == 0) {
@ -8395,6 +8558,7 @@ public class MessagesStorage extends BaseController {
newMentionsCounts.put(key, mentions_count);
}
dids.add(key);
if (exists) {
state_dialogs_update.requery();
state_dialogs_update.bindInteger(1, message != null && (!doNotUpdateDialogDate || dialog_date == 0) ? message.date : dialog_date);
@ -8465,6 +8629,7 @@ public class MessagesStorage extends BaseController {
final int downloadMediaMaskFinal = downloadMediaMask;
AndroidUtilities.runOnUIThread(() -> getDownloadController().newDownloadObjectsAvailable(downloadMediaMaskFinal));
}
updateWidgets(dids);
}
} catch (Exception e) {
FileLog.e(e);
@ -9164,6 +9329,7 @@ public class MessagesStorage extends BaseController {
if (dialogsToUpdate.size() != 0) {
resetAllUnreadCounters(false);
}
updateWidgets(dialogsIds);
}
return dialogsIds;
} catch (Exception e) {
@ -9440,6 +9606,7 @@ public class MessagesStorage extends BaseController {
database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE uid = %d AND mid <= %d", -channelId, maxMessageId)).stepThis().dispose();
database.executeFast(String.format(Locale.US, "DELETE FROM media_v2 WHERE uid = %d AND mid <= %d", -channelId, maxMessageId)).stepThis().dispose();
database.executeFast(String.format(Locale.US, "UPDATE media_counts_v2 SET old = 1 WHERE uid = %d", -channelId)).stepThis().dispose();
updateWidgets(dialogsIds);
return dialogsIds;
} catch (Exception e) {
FileLog.e(e);
@ -10790,11 +10957,27 @@ public class MessagesStorage extends BaseController {
private void checkIfFolderEmptyInternal(int folderId) {
try {
SQLiteCursor cursor = database.queryFinalized("SELECT did FROM dialogs WHERE folder_id = ?", folderId);
if (!cursor.next()) {
boolean isEmpty = true;
while (cursor.next()) {
long did = cursor.longValue(0);
int lowerId = (int) did;
int highId = (int) (did >> 32);
if (lowerId > 0 || highId != 0 && lowerId == 0) {
isEmpty = false;
break;
} else {
TLRPC.Chat chat = getChat(-lowerId);
if (!ChatObject.isNotInChat(chat) && chat.migrated_to == null) {
isEmpty = false;
break;
}
}
}
cursor.dispose();
if (isEmpty) {
AndroidUtilities.runOnUIThread(() -> getMessagesController().onFolderEmpty(folderId));
database.executeFast("DELETE FROM dialogs WHERE did = " + DialogObject.makeFolderDialogId(folderId)).stepThis().dispose();
}
cursor.dispose();
} catch (Exception e) {
FileLog.e(e);
}

View File

@ -113,6 +113,8 @@ public class NotificationCenter {
public static final int newSuggestionsAvailable = totalEvents++;
public static final int didLoadChatInviter = totalEvents++;
public static final int didLoadChatAdmins = totalEvents++;
public static final int historyImportProgressChanged = totalEvents++;
public static final int dialogDeleted = totalEvents++;
public static final int walletPendingTransactionsChanged = totalEvents++;
public static final int walletSyncProgressChanged = totalEvents++;
@ -152,6 +154,7 @@ public class NotificationCenter {
public static final int didStartedCall = totalEvents++;
public static final int groupCallUpdated = totalEvents++;
public static final int applyGroupCallVisibleParticipants = totalEvents++;
public static final int groupCallTypingsUpdated = totalEvents++;
public static final int didEndCall = totalEvents++;
public static final int closeInCallActivity = totalEvents++;

View File

@ -594,8 +594,6 @@ public class NotificationsController extends BaseController {
if (lower_id != 0) {
if (preferences.getBoolean("custom_" + dialog_id, false)) {
popup = preferences.getInt("popup_" + dialog_id, 0);
} else {
popup = 0;
}
if (popup == 0) {
if (isChannel) {
@ -2082,7 +2080,7 @@ public class NotificationsController extends BaseController {
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionScreenshotTaken) {
msg = messageObject.messageText.toString();
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) {
if (chat != null && (!ChatObject.isChannel(chat) || chat.megagroup)) {
if (!ChatObject.isChannel(chat) || chat.megagroup) {
if (messageObject.replyMessageObject == null) {
msg = LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title);
} else {
@ -2154,7 +2152,7 @@ public class NotificationsController extends BaseController {
msg = LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title);
}
}
} else if (chat != null) {
} else {
if (messageObject.replyMessageObject == null) {
msg = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title);
} else {
@ -2226,78 +2224,6 @@ public class NotificationsController extends BaseController {
msg = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title);
}
}
} else {
if (messageObject.replyMessageObject == null) {
msg = LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name);
} else {
MessageObject object = messageObject.replyMessageObject;
if (object.isMusic()) {
msg = LocaleController.formatString("NotificationActionPinnedMusicUser", R.string.NotificationActionPinnedMusicUser, name);
} else if (object.isVideo()) {
if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) {
String message = "\uD83D\uDCF9 " + object.messageOwner.message;
msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message);
} else {
msg = LocaleController.formatString("NotificationActionPinnedVideoUser", R.string.NotificationActionPinnedVideoUser, name);
}
} else if (object.isGif()) {
if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) {
String message = "\uD83C\uDFAC " + object.messageOwner.message;
msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message);
} else {
msg = LocaleController.formatString("NotificationActionPinnedGifUser", R.string.NotificationActionPinnedGifUser, name);
}
} else if (object.isVoice()) {
msg = LocaleController.formatString("NotificationActionPinnedVoiceUser", R.string.NotificationActionPinnedVoiceUser, name);
} else if (object.isRoundVideo()) {
msg = LocaleController.formatString("NotificationActionPinnedRoundUser", R.string.NotificationActionPinnedRoundUser, name);
} else if (object.isSticker() || object.isAnimatedSticker()) {
String emoji = object.getStickerEmoji();
if (emoji != null) {
msg = LocaleController.formatString("NotificationActionPinnedStickerEmojiUser", R.string.NotificationActionPinnedStickerEmojiUser, name, emoji);
} else {
msg = LocaleController.formatString("NotificationActionPinnedStickerUser", R.string.NotificationActionPinnedStickerUser, name);
}
} else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) {
String message = "\uD83D\uDCCE " + object.messageOwner.message;
msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message);
} else {
msg = LocaleController.formatString("NotificationActionPinnedFileUser", R.string.NotificationActionPinnedFileUser, name);
}
} else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) {
msg = LocaleController.formatString("NotificationActionPinnedGeoUser", R.string.NotificationActionPinnedGeoUser, name);
} else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) {
msg = LocaleController.formatString("NotificationActionPinnedGeoLiveUser", R.string.NotificationActionPinnedGeoLiveUser, name);
} else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) {
TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media;
msg = LocaleController.formatString("NotificationActionPinnedContactUser", R.string.NotificationActionPinnedContactUser, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name));
} else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) {
TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media;
if (mediaPoll.poll.quiz) {
msg = LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question);
} else {
msg = LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question);
}
} else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) {
String message = "\uD83D\uDDBC " + object.messageOwner.message;
msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message);
} else {
msg = LocaleController.formatString("NotificationActionPinnedPhotoUser", R.string.NotificationActionPinnedPhotoUser, name);
}
} else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
msg = LocaleController.formatString("NotificationActionPinnedGameUser", R.string.NotificationActionPinnedGameUser, name);
} else if (object.messageText != null && object.messageText.length() > 0) {
CharSequence message = object.messageText;
if (message.length() > 20) {
message = message.subSequence(0, 20) + "...";
}
msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message);
} else {
msg = LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name);
}
}
}
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) {
msg = messageObject.messageText.toString();
@ -2637,85 +2563,95 @@ public class NotificationsController extends BaseController {
deleteNotificationChannel(dialogId, -1);
}
private void deleteNotificationChannelInternal(long dialogId, int what) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
try {
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
SharedPreferences.Editor editor = preferences.edit();
if (what == 0 || what == -1) {
String key = "org.telegram.key" + dialogId;
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
if (what == 1 || what == -1) {
String key = "org.telegram.keyia" + dialogId;
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
editor.commit();
} catch (Exception e) {
FileLog.e(e);
}
}
public void deleteNotificationChannel(long dialogId, int what) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
notificationsQueue.postRunnable(() -> {
try {
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
SharedPreferences.Editor editor = preferences.edit();
if (what == 0 || what == -1) {
String key = "org.telegram.key" + dialogId;
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
if (what == 1 || what == -1) {
String key = "org.telegram.keyia" + dialogId;
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
editor.commit();
} catch (Exception e) {
FileLog.e(e);
}
});
notificationsQueue.postRunnable(() -> deleteNotificationChannelInternal(dialogId, what));
}
public void deleteNotificationChannelGlobal(int type) {
deleteNotificationChannelGlobal(type, -1);
}
public void deleteNotificationChannelGlobalInternal(int type, int what) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
try {
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
SharedPreferences.Editor editor = preferences.edit();
if (what == 0 || what == -1) {
String key;
if (type == TYPE_CHANNEL) {
key = "channels";
} else if (type == TYPE_GROUP) {
key = "groups";
} else {
key = "private";
}
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
if (what == 1 || what == -1) {
String key;
if (type == TYPE_CHANNEL) {
key = "channels_ia";
} else if (type == TYPE_GROUP) {
key = "groups_ia";
} else {
key = "private_ia";
}
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
editor.commit();
} catch (Exception e) {
FileLog.e(e);
}
}
public void deleteNotificationChannelGlobal(int type, int what) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
notificationsQueue.postRunnable(() -> {
try {
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
SharedPreferences.Editor editor = preferences.edit();
if (what == 0 || what == -1) {
String key;
if (type == TYPE_CHANNEL) {
key = "channels";
} else if (type == TYPE_GROUP) {
key = "groups";
} else {
key = "private";
}
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
if (what == 1 || what == -1) {
String key;
if (type == TYPE_CHANNEL) {
key = "channels_ia";
} else if (type == TYPE_GROUP) {
key = "groups_ia";
} else {
key = "private_ia";
}
String channelId = preferences.getString(key, null);
if (channelId != null) {
editor.remove(key).remove(key + "_s");
systemNotificationManager.deleteNotificationChannel(channelId);
}
}
editor.commit();
} catch (Exception e) {
FileLog.e(e);
}
});
notificationsQueue.postRunnable(() -> deleteNotificationChannelGlobalInternal(type, what));
}
public void deleteAllNotificationChannels() {
@ -2748,9 +2684,9 @@ public class NotificationsController extends BaseController {
}
@SuppressLint("RestrictedApi")
private void createNotificationShortcut(NotificationCompat.Builder builder, int did, String name, TLRPC.User user, TLRPC.Chat chat, Person person) {
private String createNotificationShortcut(NotificationCompat.Builder builder, int did, String name, TLRPC.User user, TLRPC.Chat chat, Person person) {
if (unsupportedNotificationShortcut() || ChatObject.isChannel(chat) && !chat.megagroup) {
return;
return null;
}
try {
String id = "ndid_" + did;
@ -2782,7 +2718,7 @@ public class NotificationsController extends BaseController {
}
intent.putExtra("currentAccount", currentAccount);
bubbleBuilder.setIntent(PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
bubbleBuilder.setSuppressNotification(true);
bubbleBuilder.setSuppressNotification(opened_dialog_id == did);
bubbleBuilder.setAutoExpandBubble(false);
bubbleBuilder.setDesiredHeight(AndroidUtilities.dp(640));
if (avatar != null) {
@ -2795,9 +2731,11 @@ public class NotificationsController extends BaseController {
}
}
builder.setBubbleMetadata(bubbleBuilder.build());
return id;
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
@TargetApi(26)
@ -3650,10 +3588,7 @@ public class NotificationsController extends BaseController {
mBuilder.addAction(R.drawable.ic_ab_reply, LocaleController.getString("Reply", R.string.Reply), PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 2, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT));
}
}
if (Build.VERSION.SDK_INT >= 26) {
mBuilder.setChannelId(validateChannelId(dialog_id, chatName, vibrationPattern, ledColor, sound, configImportance, isDefault, isInApp, notifyDisabled, chatType));
}
showExtraNotifications(mBuilder, detailText);
showExtraNotifications(mBuilder, detailText, dialog_id, chatName, vibrationPattern, ledColor, sound, configImportance, isDefault, isInApp, notifyDisabled, chatType);
scheduleNotificationRepeat();
} catch (Exception e) {
FileLog.e(e);
@ -3669,8 +3604,47 @@ public class NotificationsController extends BaseController {
}
}
private void resetNotificationSound(NotificationCompat.Builder notificationBuilder, long dialogId, String chatName, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int chatType) {
Uri defaultSound = Settings.System.DEFAULT_RINGTONE_URI;
if (defaultSound != null && sound != null && !TextUtils.equals(defaultSound.toString(), sound.toString())) {
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
SharedPreferences.Editor editor = preferences.edit();
String newSound = defaultSound.toString();
String ringtoneName = LocaleController.getString("DefaultRingtone", R.string.DefaultRingtone);
if (isDefault) {
if (chatType == TYPE_CHANNEL) {
editor.putString("ChannelSound", ringtoneName);
} else if (chatType == TYPE_GROUP) {
editor.putString("GroupSound", ringtoneName);
} else {
editor.putString("GlobalSound", ringtoneName);
}
if (chatType == TYPE_CHANNEL) {
editor.putString("ChannelSoundPath", newSound);
} else if (chatType == TYPE_GROUP) {
editor.putString("GroupSoundPath", newSound);
} else {
editor.putString("GlobalSoundPath", newSound);
}
getNotificationsController().deleteNotificationChannelGlobalInternal(chatType, -1);
} else {
editor.putString("sound_" + dialogId, ringtoneName);
editor.putString("sound_path_" + dialogId, newSound);
deleteNotificationChannelInternal(dialogId, -1);
}
editor.commit();
sound = Settings.System.DEFAULT_RINGTONE_URI;
notificationBuilder.setChannelId(validateChannelId(dialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType));
notificationManager.notify(notificationId, notificationBuilder.build());
}
}
@SuppressLint("InlinedApi")
private void showExtraNotifications(NotificationCompat.Builder notificationBuilder, String summary) {
private void showExtraNotifications(NotificationCompat.Builder notificationBuilder, String summary, long dialogId, String chatName, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int chatType) {
if (Build.VERSION.SDK_INT >= 26) {
notificationBuilder.setChannelId(validateChannelId(dialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType));
}
Notification mainNotification = notificationBuilder.build();
if (Build.VERSION.SDK_INT < 18) {
notificationManager.notify(notificationId, mainNotification);
@ -3696,7 +3670,7 @@ public class NotificationsController extends BaseController {
if (arrayList == null) {
arrayList = new ArrayList<>();
messagesByDialogs.put(dialog_id, arrayList);
sortedDialogs.add(0, dialog_id);
sortedDialogs.add(dialog_id);
}
arrayList.add(messageObject);
}
@ -3706,18 +3680,31 @@ public class NotificationsController extends BaseController {
class NotificationHolder {
int id;
Notification notification;
int lowerId;
String name;
TLRPC.User user;
TLRPC.Chat chat;
NotificationCompat.Builder notification;
NotificationHolder(int i, Notification n) {
NotificationHolder(int i, int li, String n, TLRPC.User u, TLRPC.Chat c, NotificationCompat.Builder builder) {
id = i;
notification = n;
name = n;
user = u;
chat = c;
notification = builder;
lowerId = li;
}
void call() {
if (BuildVars.LOGS_ENABLED) {
FileLog.w("show dialog notification with id " + id);
}
notificationManager.notify(id, notification);
try {
notificationManager.notify(id, notification.build());
} catch (SecurityException e) {
FileLog.e(e);
resetNotificationSound(notification, dialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType);
}
}
}
@ -3727,7 +3714,7 @@ public class NotificationsController extends BaseController {
serializedNotifications = new JSONArray();
}
boolean useSummaryNotification = Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1 || Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1 && sortedDialogs.size() > 1;
boolean useSummaryNotification = Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1 || sortedDialogs.size() > 1;
if (useSummaryNotification && Build.VERSION.SDK_INT >= 26) {
checkOtherNotificationsChannel();
}
@ -3735,12 +3722,8 @@ public class NotificationsController extends BaseController {
int selfUserId = getUserConfig().getClientUserId();
boolean waitingForPasscode = AndroidUtilities.needShowPasscode() || SharedConfig.isWaitingForPasscodeEnter;
int maxCount;
if (UserConfig.getActivatedAccountsCount() >= 3) {
maxCount = 7;
} else {
maxCount = 10;
}
int maxCount = 7;
LongSparseArray<Person> personCache = new LongSparseArray<>();
for (int b = 0, size = sortedDialogs.size(); b < size; b++) {
if (holders.size() >= maxCount) {
break;
@ -3782,7 +3765,6 @@ public class NotificationsController extends BaseController {
Bitmap avatarBitmap = null;
File avatalFile = null;
boolean canReply;
LongSparseArray<Person> personCache = new LongSparseArray<>();
if (lowerId != 0) {
canReply = lowerId != 777000;
@ -4021,7 +4003,7 @@ public class NotificationsController extends BaseController {
File avatar = null;
if (lowerId > 0 || isChannel) {
avatar = avatalFile;
} else if (lowerId < 0) {
} else {
int fromId = messageObject.getSenderId();
TLRPC.User sender = getMessagesController().getUser(fromId);
if (sender == null) {
@ -4199,7 +4181,7 @@ public class NotificationsController extends BaseController {
.setStyle(messagingStyle)
.setContentIntent(contentIntent)
.extend(wearableExtender)
.setSortKey("" + (Long.MAX_VALUE - date))
.setSortKey(String.valueOf(Long.MAX_VALUE - date))
.setCategory(NotificationCompat.CATEGORY_MESSAGE);
Intent dismissIntent = new Intent(ApplicationLoader.applicationContext, NotificationDismissReceiver.class);
@ -4248,11 +4230,6 @@ public class NotificationsController extends BaseController {
}
}
}
if (Build.VERSION.SDK_INT >= 29) {
if (lowerId != 0) {
createNotificationShortcut(builder, lowerId, name, user, chat, personCache.get(lowerId));
}
}
}
if (chat == null && user != null && user.phone != null && user.phone.length() > 0) {
@ -4262,7 +4239,7 @@ public class NotificationsController extends BaseController {
if (Build.VERSION.SDK_INT >= 26) {
setNotificationChannel(mainNotification, builder, useSummaryNotification);
}
holders.add(new NotificationHolder(internalId, builder.build()));
holders.add(new NotificationHolder(internalId, lowerId, name, user, chat, builder));
wearNotificationsIds.put(dialog_id, internalId);
if (lowerId != 0) {
@ -4281,7 +4258,7 @@ public class NotificationsController extends BaseController {
}
if (lowerId > 0) {
serializedChat.put("type", "user");
} else if (lowerId < 0) {
} else {
if (isChannel || isSupergroup) {
serializedChat.put("type", "channel");
} else {
@ -4299,27 +4276,17 @@ public class NotificationsController extends BaseController {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("show summary with id " + notificationId);
}
notificationManager.notify(notificationId, mainNotification);
try {
notificationManager.notify(notificationId, mainNotification);
} catch (SecurityException e) {
FileLog.e(e);
resetNotificationSound(notificationBuilder, dialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType);
}
} else {
if (openedInBubbleDialogs.isEmpty()) {
notificationManager.cancel(notificationId);
}
}
ArrayList<String> ids = new ArrayList<>(holders.size());
for (int a = 0, size = holders.size(); a < size; a++) {
NotificationHolder holder = holders.get(a);
holder.call();
if (!unsupportedNotificationShortcut()) {
ids.add(holder.notification.getShortcutId());
}
}
if (!unsupportedNotificationShortcut()) {
try {
ShortcutManagerCompat.removeDynamicShortcuts(ApplicationLoader.applicationContext, ids);
} catch (Exception e) {
FileLog.e(e);
}
}
for (int a = 0; a < oldIdsWear.size(); a++) {
long did = oldIdsWear.keyAt(a);
@ -4332,6 +4299,23 @@ public class NotificationsController extends BaseController {
}
notificationManager.cancel(id);
}
ArrayList<String> ids = new ArrayList<>(holders.size());
for (int a = 0, size = holders.size(); a < size; a++) {
NotificationHolder holder = holders.get(a);
ids.clear();
if (Build.VERSION.SDK_INT >= 29 && holder.lowerId != 0) {
String shortcutId = createNotificationShortcut(holder.notification, holder.lowerId, holder.name, holder.user, holder.chat, personCache.get(holder.lowerId));
if (shortcutId != null) {
ids.add(shortcutId);
}
}
holder.call();
if (!unsupportedNotificationShortcut() && !ids.isEmpty()) {
ShortcutManagerCompat.removeDynamicShortcuts(ApplicationLoader.applicationContext, ids);
}
}
if (serializedNotifications != null) {
try {
JSONObject s = new JSONObject();

View File

@ -244,6 +244,9 @@ public class SecretChatHelper extends BaseController {
getNotificationCenter().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat);
});
}
if (newChat instanceof TLRPC.TL_encryptedChatDiscarded && newChat.history_deleted) {
AndroidUtilities.runOnUIThread(() -> getMessagesController().deleteDialog(dialog_id, 0));
}
}
public void sendMessagesDeleteMessage(TLRPC.EncryptedChat encryptedChat, ArrayList<Long> random_ids, TLRPC.Message resendMessage) {
@ -1659,7 +1662,7 @@ public class SecretChatHelper extends BaseController {
getMessagesStorage().updateEncryptedChat(newChat);
getNotificationCenter().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat);
});
declineSecretChat(chat.id);
declineSecretChat(chat.id, false);
return null;
}
@ -1733,7 +1736,7 @@ public class SecretChatHelper extends BaseController {
BigInteger i_authKey = new BigInteger(1, encryptedChat.g_a_or_b);
if (!Utilities.isGoodGaAndGb(i_authKey, p)) {
declineSecretChat(encryptedChat.id);
declineSecretChat(encryptedChat.id, false);
return;
}
@ -1789,13 +1792,14 @@ public class SecretChatHelper extends BaseController {
getMessagesController().putEncryptedChat(newChat, false);
getNotificationCenter().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat);
});
declineSecretChat(encryptedChat.id);
declineSecretChat(encryptedChat.id, false);
}
}
public void declineSecretChat(int chat_id) {
public void declineSecretChat(int chat_id, boolean revoke) {
TLRPC.TL_messages_discardEncryption req = new TLRPC.TL_messages_discardEncryption();
req.chat_id = chat_id;
req.delete_history = revoke;
getConnectionsManager().sendRequest(req, (response, error) -> {
});
@ -1815,7 +1819,7 @@ public class SecretChatHelper extends BaseController {
if (response instanceof TLRPC.TL_messages_dhConfig) {
if (!Utilities.isGoodPrime(res.p, res.g)) {
acceptingChats.remove(encryptedChat.id);
declineSecretChat(encryptedChat.id);
declineSecretChat(encryptedChat.id, false);
return;
}
@ -1838,7 +1842,7 @@ public class SecretChatHelper extends BaseController {
if (!Utilities.isGoodGaAndGb(g_a, p)) {
acceptingChats.remove(encryptedChat.id);
declineSecretChat(encryptedChat.id);
declineSecretChat(encryptedChat.id, false);
return;
}

View File

@ -10,6 +10,7 @@ package org.telegram.messenger;
import android.content.ClipDescription;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PorterDuff;
@ -67,10 +68,12 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
@ -90,6 +93,169 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
private HashMap<String, Boolean> waitingForCallback = new HashMap<>();
private HashMap<String, byte[]> waitingForVote = new HashMap<>();
private LongSparseArray<Long> voteSendTime = new LongSparseArray();
private HashMap<String, ImportingHistory> importingHistoryFiles = new HashMap<>();
private LongSparseArray<ImportingHistory> importingHistoryMap = new LongSparseArray<>();
public class ImportingHistory {
public String historyPath;
public ArrayList<Uri> mediaPaths = new ArrayList<>();
public HashMap<String, TLRPC.InputFile> uploadedMedias = new HashMap<>();
public HashSet<String> uploadSet = new HashSet<>();
public HashMap<String, Float> uploadProgresses = new HashMap<>();
public HashMap<String, Long> uploadSize = new HashMap<>();
public ArrayList<String> uploadMedia = new ArrayList<>();
public TLRPC.InputPeer peer;
public long totalSize;
public long uploadedSize;
public long dialogId;
public long importId;
public int uploadProgress;
public double estimatedUploadSpeed;
private long lastUploadTime;
private long lastUploadSize;
public int timeUntilFinish = Integer.MAX_VALUE;
private void initImport(TLRPC.InputFile inputFile) {
TLRPC.TL_messages_initHistoryImport req = new TLRPC.TL_messages_initHistoryImport();
req.file = inputFile;
req.media_count = mediaPaths.size();
req.peer = peer;
getConnectionsManager().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(() -> {
if (response instanceof TLRPC.TL_messages_historyImport) {
importId = ((TLRPC.TL_messages_historyImport) response).id;
uploadSet.remove(historyPath);
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId);
if (uploadSet.isEmpty()) {
startImport();
}
lastUploadTime = SystemClock.elapsedRealtime();
for (int a = 0, N = uploadMedia.size(); a < N; a++) {
getFileLoader().uploadFile(uploadMedia.get(a), false, true, ConnectionsManager.FileTypeFile);
}
} else {
importingHistoryMap.remove(dialogId);
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId, req, error);
}
});
}
});
}
public long getUploadedCount() {
return uploadedSize;
}
public long getTotalCount() {
return totalSize;
}
private void addUploadProgress(String path, long sz, float progress) {
uploadProgresses.put(path, progress);
uploadSize.put(path, sz);
uploadedSize = 0;
for (HashMap.Entry<String, Long> entry : uploadSize.entrySet()) {
uploadedSize += entry.getValue();
}
long newTime = SystemClock.elapsedRealtime();
if (!path.equals(historyPath) && uploadedSize != lastUploadSize && newTime != lastUploadTime) {
double dt = (newTime - lastUploadTime) / 1000.0;
double uploadSpeed = (uploadedSize - lastUploadSize) / dt;
if (estimatedUploadSpeed == 0) {
estimatedUploadSpeed = uploadSpeed;
} else {
double coef = 0.01;
estimatedUploadSpeed = coef * uploadSpeed + (1 - coef) * estimatedUploadSpeed;
}
timeUntilFinish = (int) ((totalSize - uploadedSize) * 1000 / (double) estimatedUploadSpeed);
lastUploadSize = uploadedSize;
lastUploadTime = newTime;
}
float pr = getUploadedCount() / (float) getTotalCount();
int newProgress = (int) (pr * 100);
if (uploadProgress != newProgress) {
uploadProgress = newProgress;
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId);
}
}
private void onMediaImport(String path, long size, TLRPC.InputFile inputFile) {
addUploadProgress(path, size, 1.0f);
uploadedMedias.put(path, inputFile);
TLRPC.TL_messages_uploadImportedMedia req = new TLRPC.TL_messages_uploadImportedMedia();
req.peer = peer;
req.import_id = importId;
req.file_name = new File(path).getName();
MimeTypeMap myMime = MimeTypeMap.getSingleton();
String ext = "txt";
int idx = req.file_name.lastIndexOf('.');
if (idx != -1) {
ext = req.file_name.substring(idx + 1).toLowerCase();
}
String mimeType = myMime.getMimeTypeFromExtension(ext);
if (mimeType == null) {
if ("opus".equals(ext)) {
mimeType = "audio/opus";
} else if ("webp".equals(ext)) {
mimeType = "image/webp";
} else {
mimeType = "text/plain";
}
}
if (mimeType.equals("image/jpg") || mimeType.equals("image/jpeg")) {
TLRPC.TL_inputMediaUploadedPhoto inputMediaUploadedPhoto = new TLRPC.TL_inputMediaUploadedPhoto();
inputMediaUploadedPhoto.file = inputFile;
req.media = inputMediaUploadedPhoto;
} else {
TLRPC.TL_inputMediaUploadedDocument inputMediaDocument = new TLRPC.TL_inputMediaUploadedDocument();
inputMediaDocument.file = inputFile;
inputMediaDocument.mime_type = mimeType;
req.media = inputMediaDocument;
}
getConnectionsManager().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(() -> {
uploadSet.remove(path);
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId);
if (uploadSet.isEmpty()) {
startImport();
}
});
}
});
}
private void startImport() {
TLRPC.TL_messages_startHistoryImport req = new TLRPC.TL_messages_startHistoryImport();
req.peer = peer;
req.import_id = importId;
getConnectionsManager().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(() -> {
importingHistoryMap.remove(dialogId);
if (error == null) {
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId);
} else {
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId, req, error);
}
});
}
});
}
public void setImportProgress(int value) {
if (value == 100) {
importingHistoryMap.remove(dialogId);
}
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId);
}
}
private static DispatchQueue mediaSendQueue = new DispatchQueue("mediaSendQueue");
private static ThreadPoolExecutor mediaSendThreadPool;
@ -421,6 +587,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
AndroidUtilities.runOnUIThread(() -> {
getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.FileDidUpload);
getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.FileUploadProgressChanged);
getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.FileDidFailUpload);
getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.filePreparingStarted);
getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.fileNewChunkAvailable);
@ -443,15 +610,35 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
waitingForLocation.clear();
waitingForCallback.clear();
waitingForVote.clear();
importingHistoryFiles.clear();
importingHistoryMap.clear();
locationProvider.stop();
}
@Override
public void didReceivedNotification(int id, int account, final Object... args) {
if (id == NotificationCenter.FileDidUpload) {
if (id == NotificationCenter.FileUploadProgressChanged) {
String fileName = (String) args[0];
ImportingHistory importingHistory = importingHistoryFiles.get(fileName);
if (importingHistory != null) {
Long loadedSize = (Long) args[1];
Long totalSize = (Long) args[2];
importingHistory.addUploadProgress(fileName, loadedSize, loadedSize / (float) totalSize);
}
} else if (id == NotificationCenter.FileDidUpload) {
final String location = (String) args[0];
final TLRPC.InputFile file = (TLRPC.InputFile) args[1];
final TLRPC.InputEncryptedFile encryptedFile = (TLRPC.InputEncryptedFile) args[2];
ImportingHistory importingHistory = importingHistoryFiles.get(location);
if (importingHistory != null) {
if (location.equals(importingHistory.historyPath)) {
importingHistory.initImport(file);
} else {
importingHistory.onMediaImport(location, (Long) args[5], file);
}
}
ArrayList<DelayedMessage> arr = delayedMessages.get(location);
if (arr != null) {
for (int a = 0; a < arr.size(); a++) {
@ -4007,7 +4194,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
}
putToDelayedMessages(location, message);
if (message.obj.videoEditedInfo != null && message.obj.videoEditedInfo.needConvert()) {
getFileLoader().uploadFile(location, false, false, document.size, ConnectionsManager.FileTypeVideo);
getFileLoader().uploadFile(location, false, false, document.size, ConnectionsManager.FileTypeVideo, false);
} else {
getFileLoader().uploadFile(location, false, false, ConnectionsManager.FileTypeVideo);
}
@ -4034,7 +4221,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
}
putToDelayedMessages(location, message);
if (message.obj.videoEditedInfo != null && message.obj.videoEditedInfo.needConvert()) {
getFileLoader().uploadFile(location, true, false, document.size, ConnectionsManager.FileTypeVideo);
getFileLoader().uploadFile(location, true, false, document.size, ConnectionsManager.FileTypeVideo, false);
} else {
getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo);
}
@ -4126,7 +4313,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
message.extraHashMap.put(documentLocation + "_t", message.photoSize);
}
if (messageObject.videoEditedInfo != null && messageObject.videoEditedInfo.needConvert()) {
getFileLoader().uploadFile(documentLocation, false, false, document.size, ConnectionsManager.FileTypeVideo);
getFileLoader().uploadFile(documentLocation, false, false, document.size, ConnectionsManager.FileTypeVideo, false);
} else {
getFileLoader().uploadFile(documentLocation, false, false, ConnectionsManager.FileTypeVideo);
}
@ -4150,7 +4337,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
message.extraHashMap.put(documentLocation + "_t", message.photoSize);
}
if (messageObject.videoEditedInfo != null && messageObject.videoEditedInfo.needConvert()) {
getFileLoader().uploadFile(documentLocation, true, false, document.size, ConnectionsManager.FileTypeVideo);
getFileLoader().uploadFile(documentLocation, true, false, document.size, ConnectionsManager.FileTypeVideo, false);
} else {
getFileLoader().uploadFile(documentLocation, true, false, ConnectionsManager.FileTypeVideo);
}
@ -5231,6 +5418,95 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
});
}
public ImportingHistory getImportingHistory(long dialogId) {
return importingHistoryMap.get(dialogId);
}
public boolean isImportingHistory() {
return importingHistoryMap.size() != 0;
}
public void prepareImportHistory(long dialogId, Uri uri, ArrayList<Uri> mediaUris, MessagesStorage.IntCallback onStartImport) {
if (importingHistoryMap.get(dialogId) != null) {
onStartImport.run(0);
return;
}
int lowerId = (int) dialogId;
if (lowerId < 0) {
TLRPC.Chat chat = getMessagesController().getChat(-lowerId);
if (chat != null && !chat.megagroup) {
getMessagesController().convertToMegaGroup(null, -lowerId, null, (chatId) -> {
if (chatId != 0) {
prepareImportHistory(-chatId, uri, mediaUris, onStartImport);
} else {
onStartImport.run(0);
}
});
return;
}
}
new Thread(() -> {
ArrayList<Uri> uris = mediaUris != null ? mediaUris : new ArrayList<>();
ImportingHistory importingHistory = new ImportingHistory();
importingHistory.mediaPaths = uris;
importingHistory.dialogId = dialogId;
importingHistory.peer = getMessagesController().getInputPeer((int) dialogId);
HashMap<String, ImportingHistory> files = new HashMap<>();
for (int a = 0, N = uris.size(); a < N + 1; a++) {
Uri mediaUri;
if (a == 0) {
mediaUri = uri;
} else {
mediaUri = uris.get(a - 1);
}
if (mediaUri == null || AndroidUtilities.isInternalUri(mediaUri)) {
if (a == 0) {
AndroidUtilities.runOnUIThread(() -> {
onStartImport.run(0);
});
return;
}
continue;
}
String path = MediaController.copyFileToCache(mediaUri, "txt");
final File f = new File(path);
long size;
if (!f.exists() || (size = f.length()) == 0) {
if (a == 0) {
AndroidUtilities.runOnUIThread(() -> {
onStartImport.run(0);
});
return;
}
continue;
}
importingHistory.totalSize += size;
if (a == 0) {
importingHistory.historyPath = path;
} else {
importingHistory.uploadMedia.add(path);
}
importingHistory.uploadSet.add(path);
files.put(path, importingHistory);
}
AndroidUtilities.runOnUIThread(() -> {
importingHistoryFiles.putAll(files);
importingHistoryMap.put(dialogId, importingHistory);
getFileLoader().uploadFile(importingHistory.historyPath, false, true, 0, ConnectionsManager.FileTypeFile, true);
getNotificationCenter().postNotificationName(NotificationCenter.historyImportProgressChanged, dialogId);
onStartImport.run((int) dialogId);
Intent intent = new Intent(ApplicationLoader.applicationContext, ImportingService.class);
try {
ApplicationLoader.applicationContext.startService(intent);
} catch (Throwable e) {
FileLog.e(e);
}
});
}).start();
}
public TLRPC.TL_photo generatePhotoSizes(String path, Uri imageUri) {
return generatePhotoSizes(null, path, imageUri);
}
@ -5501,9 +5777,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
params.put("parentObject", parentFinal);
}
Integer prevType = 0;
boolean isSticker = false;
if (docType != null) {
prevType = docType[0];
if (document.mime_type != null && (document.mime_type.toLowerCase().startsWith("image/") || document.mime_type.toLowerCase().startsWith("video/mp4")) || MessageObject.canPreviewDocument(document)) {
if (document.mime_type != null && document.mime_type.toLowerCase().startsWith("image/webp")) {
docType[0] = -1;
isSticker = true;
} else if (document.mime_type != null && (document.mime_type.toLowerCase().startsWith("image/") || document.mime_type.toLowerCase().startsWith("video/mp4")) || MessageObject.canPreviewDocument(document)) {
docType[0] = 1;
} else if (attributeAudio != null) {
docType[0] = 2;
@ -5516,9 +5796,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
finishGroup(accountInstance, groupId[0], scheduleDate);
groupId[0] = Utilities.random.nextLong();
}
params.put("groupId", "" + groupId[0]);
if (isGroupFinal) {
params.put("final", "1");
if (!isSticker) {
params.put("groupId", "" + groupId[0]);
if (isGroupFinal) {
params.put("final", "1");
}
}
}
@ -5685,7 +5967,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
if (!prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, inputContent == null, notify, scheduleDate, docType)) {
error = true;
}
if (prevGroupId != groupId[0]) {
if (prevGroupId != groupId[0] || groupId[0] == -1) {
mediaCount = 1;
}
}
@ -5708,7 +5990,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
if (!prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, inputContent == null, notify, scheduleDate, docType)) {
error = true;
}
if (prevGroupId != groupId[0]) {
if (prevGroupId != groupId[0] || groupId[0] == -1) {
mediaCount = 1;
}
}

View File

@ -0,0 +1,62 @@
package org.telegram.messenger;
import android.app.Activity;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.widget.RemoteViews;
import org.telegram.ui.LaunchActivity;
public class ShortcutWidgetProvider extends AppWidgetProvider {
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int i = 0; i < appWidgetIds.length; i++) {
int appWidgetId = appWidgetIds[i];
updateWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
for (int a = 0; a < appWidgetIds.length; a++) {
SharedPreferences preferences = context.getSharedPreferences("shortcut_widget", Activity.MODE_PRIVATE);
int accountId = preferences.getInt("account" + appWidgetIds[a], -1);
if (accountId >= 0) {
AccountInstance accountInstance = AccountInstance.getInstance(accountId);
accountInstance.getMessagesStorage().clearWidgetDialogs(appWidgetIds[a]);
}
}
}
public static void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
Intent intent2 = new Intent(context, ShortcutWidgetService.class);
intent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent2.setData(Uri.parse(intent2.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.shortcut_widget_layout);
rv.setRemoteAdapter(appWidgetId, R.id.list_view, intent2);
rv.setEmptyView(R.id.list_view, R.id.empty_view);
Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setPendingIntentTemplate(R.id.list_view, contentIntent);
appWidgetManager.updateAppWidget(appWidgetId, rv);
}
}

View File

@ -0,0 +1,353 @@
package org.telegram.messenger;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.util.LongSparseArray;
import android.util.SparseArray;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.ForegroundColorSpanThemable;
import java.io.File;
import java.util.ArrayList;
public class ShortcutWidgetService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new ShortcutRemoteViewsFactory(getApplicationContext(), intent);
}
}
class ShortcutRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private ArrayList<Integer> dids = new ArrayList<>();
private Context mContext;
private int appWidgetId;
private AccountInstance accountInstance;
private Paint roundPaint;
private RectF bitmapRect;
private LongSparseArray<TLRPC.Dialog> dialogs = new LongSparseArray<>();
private LongSparseArray<MessageObject> messageObjects = new LongSparseArray<>();
public ShortcutRemoteViewsFactory(Context context, Intent intent) {
mContext = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
SharedPreferences preferences = context.getSharedPreferences("shortcut_widget", Activity.MODE_PRIVATE);
int accountId = preferences.getInt("account" + appWidgetId, -1);
if (accountId >= 0) {
accountInstance = AccountInstance.getInstance(accountId);
}
}
public void onCreate() {
ApplicationLoader.postInitApplication();
}
public void onDestroy() {
}
public int getCount() {
return dids.size();
}
public RemoteViews getViewAt(int position) {
Integer id = dids.get(position);
String name;
TLRPC.FileLocation photoPath = null;
TLRPC.User user = null;
TLRPC.Chat chat = null;
if (id > 0) {
user = accountInstance.getMessagesController().getUser(id);
if (UserObject.isUserSelf(user)) {
name = LocaleController.getString("SavedMessages", R.string.SavedMessages);
} else if (UserObject.isReplyUser(user)) {
name = LocaleController.getString("RepliesTitle", R.string.RepliesTitle);
} else {
name = ContactsController.formatName(user.first_name, user.last_name);
}
if (!UserObject.isReplyUser(user) && !UserObject.isUserSelf(user) && user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) {
photoPath = user.photo.photo_small;
}
} else {
chat = accountInstance.getMessagesController().getChat(-id);
name = chat.title;
if (chat.photo != null && chat.photo.photo_small != null && chat.photo.photo_small.volume_id != 0 && chat.photo.photo_small.local_id != 0) {
photoPath = chat.photo.photo_small;
}
}
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.shortcut_widget_item);
rv.setTextViewText(R.id.shortcut_widget_item_text, name);
try {
Bitmap bitmap = null;
if (photoPath != null) {
File path = FileLoader.getPathToAttach(photoPath, true);
bitmap = BitmapFactory.decodeFile(path.toString());
}
int size = AndroidUtilities.dp(48);
Bitmap result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
result.eraseColor(Color.TRANSPARENT);
Canvas canvas = new Canvas(result);
if (bitmap == null) {
AvatarDrawable avatarDrawable;
if (user != null) {
avatarDrawable = new AvatarDrawable(user);
if (UserObject.isReplyUser(user)) {
avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_REPLIES);
} else if (UserObject.isUserSelf(user)) {
avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED);
}
} else {
avatarDrawable = new AvatarDrawable(chat);
}
avatarDrawable.setBounds(0, 0, size, size);
avatarDrawable.draw(canvas);
} else {
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
if (roundPaint == null) {
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmapRect = new RectF();
}
float scale = size / (float) bitmap.getWidth();
canvas.save();
canvas.scale(scale, scale);
roundPaint.setShader(shader);
bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawRoundRect(bitmapRect, bitmap.getWidth(), bitmap.getHeight(), roundPaint);
canvas.restore();
}
canvas.setBitmap(null);
rv.setImageViewBitmap(R.id.shortcut_widget_item_avatar, result);
} catch (Throwable e) {
FileLog.e(e);
}
MessageObject message = messageObjects.get(id);
TLRPC.Dialog dialog = dialogs.get(id);
if (message != null) {
TLRPC.User fromUser = null;
TLRPC.Chat fromChat = null;
int fromId = message.getFromChatId();
if (fromId > 0) {
fromUser = accountInstance.getMessagesController().getUser(fromId);
} else {
fromChat = accountInstance.getMessagesController().getChat(-fromId);
}
CharSequence messageString;
CharSequence messageNameString;
int textColor = 0xff212121;
if (message.messageOwner instanceof TLRPC.TL_messageService) {
if (ChatObject.isChannel(chat) && (message.messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear ||
message.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom)) {
messageString = "";
} else {
messageString = message.messageText;
}
textColor = 0xff3c7eb0;
} else {
boolean needEmoji = true;
if (chat != null && chat.id > 0 && fromChat == null && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat))) {
if (message.isOutOwner()) {
messageNameString = LocaleController.getString("FromYou", R.string.FromYou);
} else if (fromUser != null) {
messageNameString = UserObject.getFirstName(fromUser).replace("\n", "");
} else {
messageNameString = "DELETED";
}
SpannableStringBuilder stringBuilder;
String messageFormat = "%2$s: \u2068%1$s\u2069";
if (message.caption != null) {
String mess = message.caption.toString();
if (mess.length() > 150) {
mess = mess.substring(0, 150);
}
String emoji;
if (message.isVideo()) {
emoji = "\uD83D\uDCF9 ";
} else if (message.isVoice()) {
emoji = "\uD83C\uDFA4 ";
} else if (message.isMusic()) {
emoji = "\uD83C\uDFA7 ";
} else if (message.isPhoto()) {
emoji = "\uD83D\uDDBC ";
} else {
emoji = "\uD83D\uDCCE ";
}
stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, emoji + mess.replace('\n', ' '), messageNameString));
} else if (message.messageOwner.media != null && !message.isMediaEmpty()) {
textColor = 0xff3c7eb0;
String innerMessage;
if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) {
TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media;
if (Build.VERSION.SDK_INT >= 18) {
innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question);
} else {
innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question);
}
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
if (Build.VERSION.SDK_INT >= 18) {
innerMessage = String.format("\uD83C\uDFAE \u2068%s\u2069", message.messageOwner.media.game.title);
} else {
innerMessage = String.format("\uD83C\uDFAE %s", message.messageOwner.media.game.title);
}
} else if (message.type == 14) {
if (Build.VERSION.SDK_INT >= 18) {
innerMessage = String.format("\uD83C\uDFA7 \u2068%s - %s\u2069", message.getMusicAuthor(), message.getMusicTitle());
} else {
innerMessage = String.format("\uD83C\uDFA7 %s - %s", message.getMusicAuthor(), message.getMusicTitle());
}
} else {
innerMessage = message.messageText.toString();
}
innerMessage = innerMessage.replace('\n', ' ');
stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, innerMessage, messageNameString));
try {
stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_attachMessage), messageNameString.length() + 2, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
FileLog.e(e);
}
} else if (message.messageOwner.message != null) {
String mess = message.messageOwner.message;
if (mess.length() > 150) {
mess = mess.substring(0, 150);
}
mess = mess.replace('\n', ' ').trim();
stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess, messageNameString));
} else {
stringBuilder = SpannableStringBuilder.valueOf("");
}
try {
stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_nameMessage), 0, messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
FileLog.e(e);
}
messageString = stringBuilder;//Emoji.replaceEmoji(stringBuilder, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt(), AndroidUtilities.dp(20), false);
} else {
if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && message.messageOwner.media.photo instanceof TLRPC.TL_photoEmpty && message.messageOwner.media.ttl_seconds != 0) {
messageString = LocaleController.getString("AttachPhotoExpired", R.string.AttachPhotoExpired);
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaDocument && message.messageOwner.media.document instanceof TLRPC.TL_documentEmpty && message.messageOwner.media.ttl_seconds != 0) {
messageString = LocaleController.getString("AttachVideoExpired", R.string.AttachVideoExpired);
} else if (message.caption != null) {
String emoji;
if (message.isVideo()) {
emoji = "\uD83D\uDCF9 ";
} else if (message.isVoice()) {
emoji = "\uD83C\uDFA4 ";
} else if (message.isMusic()) {
emoji = "\uD83C\uDFA7 ";
} else if (message.isPhoto()) {
emoji = "\uD83D\uDDBC ";
} else {
emoji = "\uD83D\uDCCE ";
}
messageString = emoji + message.caption;
} else {
if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) {
TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media;
messageString = "\uD83D\uDCCA " + mediaPoll.poll.question;
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title;
} else if (message.type == 14) {
messageString = String.format("\uD83C\uDFA7 %s - %s", message.getMusicAuthor(), message.getMusicTitle());
} else {
messageString = message.messageText;
AndroidUtilities.highlightText(messageString, message.highlightedWords);
}
if (message.messageOwner.media != null && !message.isMediaEmpty()) {
textColor = 0xff3c7eb0;
}
}
}
}
rv.setTextViewText(R.id.shortcut_widget_item_time, LocaleController.stringForMessageListDate(message.messageOwner.date));
rv.setTextViewText(R.id.shortcut_widget_item_message, messageString);
rv.setTextColor(R.id.shortcut_widget_item_message, textColor);
} else {
if (dialog != null) {
rv.setTextViewText(R.id.shortcut_widget_item_time, LocaleController.stringForMessageListDate(dialog.last_message_date));
}
}
if (dialog != null && dialog.unread_count > 0) {
rv.setTextViewText(R.id.shortcut_widget_item_badge, String.format("%d", dialog.unread_count));
rv.setViewVisibility(R.id.shortcut_widget_item_badge, View.VISIBLE);
} else {
rv.setViewVisibility(R.id.shortcut_widget_item_badge, View.GONE);
}
Bundle extras = new Bundle();
if (id > 0) {
extras.putInt("userId", id);
} else {
extras.putInt("chatId", -id);
}
extras.putInt("currentAccount", accountInstance.getCurrentAccount());
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
rv.setOnClickFillInIntent(R.id.shortcut_widget_item, fillInIntent);
rv.setViewVisibility(R.id.shortcut_widget_item_divider, position == getCount() ? View.GONE : View.VISIBLE);
return rv;
}
public RemoteViews getLoadingView() {
return null;
}
public int getViewTypeCount() {
return 1;
}
public long getItemId(int position) {
return position;
}
public boolean hasStableIds() {
return true;
}
public void onDataSetChanged() {
dids.clear();
messageObjects.clear();
if (accountInstance == null || !accountInstance.getUserConfig().isClientActivated()) {
return;
}
ArrayList<TLRPC.User> users = new ArrayList<>();
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
LongSparseArray<TLRPC.Message> messages = new LongSparseArray<>();
accountInstance.getMessagesStorage().getWidgetDialogs(appWidgetId, dids, dialogs, messages, users, chats);
accountInstance.getMessagesController().putUsers(users, true);
accountInstance.getMessagesController().putChats(chats, true);
messageObjects.clear();
for (int a = 0, N = messages.size(); a < N; a++) {
MessageObject messageObject = new MessageObject(accountInstance.getCurrentAccount(), messages.valueAt(a), (SparseArray<TLRPC.User>) null, null, false, true);
messageObjects.put(messages.keyAt(a), messageObject);
}
}
}

View File

@ -95,11 +95,11 @@ public final class Instance {
instance = null;
}
public static NativeInstance makeInstance(String version, Config config, String persistentStateFilePath, Endpoint[] endpoints, Proxy proxy, int networkType, EncryptionKey encryptionKey, VideoSink remoteSink, long videoCapturer) {
public static NativeInstance makeInstance(String version, Config config, String persistentStateFilePath, Endpoint[] endpoints, Proxy proxy, int networkType, EncryptionKey encryptionKey, VideoSink remoteSink, long videoCapturer, NativeInstance.AudioLevelsCallback audioLevelsCallback) {
if (!"2.4.4".equals(version)) {
ContextUtils.initialize(ApplicationLoader.applicationContext);
}
instance = NativeInstance.make(version, config, persistentStateFilePath, endpoints, proxy, networkType, encryptionKey, remoteSink, videoCapturer);
instance = NativeInstance.make(version, config, persistentStateFilePath, endpoints, proxy, networkType, encryptionKey, remoteSink, videoCapturer, audioLevelsCallback);
setGlobalServerConfig(globalServerConfig.jsonObject.toString());
setBufferSize(bufferSize);
return instance;

View File

@ -35,12 +35,13 @@ public class NativeInstance {
void run(int[] uids, float[] levels, boolean[] voice);
}
public static NativeInstance make(String version, Instance.Config config, String path, Instance.Endpoint[] endpoints, Instance.Proxy proxy, int networkType, Instance.EncryptionKey encryptionKey, VideoSink remoteSink, long videoCapturer) {
public static NativeInstance make(String version, Instance.Config config, String path, Instance.Endpoint[] endpoints, Instance.Proxy proxy, int networkType, Instance.EncryptionKey encryptionKey, VideoSink remoteSink, long videoCapturer, AudioLevelsCallback audioLevelsCallback) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("create new tgvoip instance, version " + version);
}
NativeInstance instance = new NativeInstance();
instance.persistentStateFilePath = path;
instance.audioLevelsCallback = audioLevelsCallback;
float aspectRatio = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) / (float) Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y);
instance.nativePtr = makeNativeInstance(version, instance, config, path, endpoints, proxy, networkType, encryptionKey, remoteSink, videoCapturer, aspectRatio);
return instance;
@ -112,7 +113,7 @@ public class NativeInstance {
}
private void onAudioLevelsUpdated(int[] uids, float[] levels, boolean[] voice) {
if (uids.length == 0) {
if (isGroup && uids != null && uids.length == 0) {
return;
}
AndroidUtilities.runOnUIThread(() -> audioLevelsCallback.run(uids, levels, voice));
@ -178,6 +179,7 @@ public class NativeInstance {
public native String getVersion();
public native void setNetworkType(int networkType);
public native void setMuteMicrophone(boolean muteMicrophone);
public native void setVolume(int ssrc, double volume);
public native void setAudioOutputGainControlEnabled(boolean enabled);
public native void setEchoCancellationStrength(int strength);
public native String getLastError();

View File

@ -148,6 +148,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
protected PowerManager.WakeLock cpuWakelock;
protected boolean isProximityNear;
protected boolean isHeadsetPlugged;
protected int previousAudioOutput;
protected ArrayList<StateListener> stateListeners = new ArrayList<>();
protected MediaPlayer ringtonePlayer;
protected Vibrator vibrator;
@ -275,6 +276,22 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
if (isHeadsetPlugged && proximityWakelock != null && proximityWakelock.isHeld()) {
proximityWakelock.release();
}
if (isHeadsetPlugged) {
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
if (am.isSpeakerphoneOn()) {
previousAudioOutput = 0;
} else if (am.isBluetoothScoOn()) {
previousAudioOutput = 2;
} else {
previousAudioOutput = 1;
}
setAudioOutput(1);
} else {
if (previousAudioOutput >= 0) {
setAudioOutput(previousAudioOutput);
previousAudioOutput = -1;
}
}
isProximityNear = false;
updateOutputGainControlState();
} else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
@ -416,7 +433,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
}
}
if (send) {
editCallMember(UserConfig.getInstance(currentAccount).getCurrentUser(), mute);
editCallMember(UserConfig.getInstance(currentAccount).getCurrentUser(), mute, -1);
Utilities.globalQueue.postRunnable(updateNotificationRunnable = () -> {
if (updateNotificationRunnable == null) {
return;
@ -435,7 +452,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
}
}
public void editCallMember(TLObject object, boolean mute) {
public void editCallMember(TLObject object, boolean mute, int volume) {
if (groupCall == null) {
return;
}
@ -452,6 +469,10 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
}
}
req.muted = mute;
if (volume >= 0) {
req.volume = volume;
req.flags |= 2;
}
int account = currentAccount;
AccountInstance.getInstance(account).getConnectionsManager().sendRequest(req, (response, error) -> {
if (response != null) {
@ -1554,8 +1575,8 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
if (groupCall == null) {
Utilities.globalQueue.postRunnable(() -> soundPool.play(spEndId, 1, 1, 0, 0, 1));
} else {
Utilities.globalQueue.postRunnable(() -> soundPool.play(spVoiceChatEndId, 1.0f, 1.0f, 0, 0, 1));
delay = 400;
Utilities.globalQueue.postRunnable(() -> soundPool.play(spVoiceChatEndId, 1.0f, 1.0f, 0, 0, 1), 100);
delay = 500;
}
AndroidUtilities.runOnUIThread(afterSoundRunnable, delay);
}

View File

@ -1374,16 +1374,34 @@ public class VoIPService extends VoIPBaseService {
playedConnectedSound = true;
}
if (!wasConnected) {
if (!micMute) {
tgVoip.setMuteMicrophone(false);
}
wasConnected = true;
NativeInstance instance = tgVoip;
if (instance != null) {
if (!micMute) {
tgVoip.setMuteMicrophone(false);
}
for (int a = 0, N = groupCall.participants.size(); a < N; a++) {
TLRPC.TL_groupCallParticipant participant = groupCall.participants.valueAt(a);
if (participant.source == 0) {
continue;
}
if (participant.muted_by_you) {
instance.setVolume(participant.source, 0);
} else {
instance.setVolume(participant.source, ChatObject.getParticipantVolume(participant) / 10000.0);
}
}
}
}
}
});
dispatchStateChanged(STATE_WAIT_INIT);
}
public void setParticipantVolume(int ssrc, int volume) {
tgVoip.setVolume(ssrc, volume / 10000.0);
}
private void initiateActualEncryptedCall() {
if (timeoutRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(timeoutRunnable);
@ -1490,7 +1508,12 @@ public class VoIPService extends VoIPBaseService {
videoState = Instance.VIDEO_STATE_INACTIVE;
}
// init
tgVoip = Instance.makeInstance(privateCall.protocol.library_versions.get(0), config, persistentStateFilePath, endpoints, proxy, getNetworkType(), encryptionKey, remoteSink, videoCapturer);
tgVoip = Instance.makeInstance(privateCall.protocol.library_versions.get(0), config, persistentStateFilePath, endpoints, proxy, getNetworkType(), encryptionKey, remoteSink, videoCapturer, (uids, levels, voice) -> {
if (sharedInstance == null || privateCall == null) {
return;
}
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.webRtcMicAmplitudeEvent, levels[0]);
});
tgVoip.setOnStateUpdatedListener(this::onConnectionStateChanged);
tgVoip.setOnSignalBarsUpdatedListener(this::onSignalBarCountChanged);
tgVoip.setOnSignalDataListener(this::onSignalingData);

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,8 @@ import android.widget.LinearLayout;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.Adapters.FiltersView;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.RLottieImageView;
public class ActionBarMenu extends LinearLayout {
@ -86,7 +88,11 @@ public class ActionBarMenu extends LinearLayout {
addView(menuItem, layoutParams);
} else {
if (drawable != null) {
menuItem.iconView.setImageDrawable(drawable);
if (drawable instanceof RLottieDrawable) {
menuItem.iconView.setAnimation((RLottieDrawable) drawable);
} else {
menuItem.iconView.setImageDrawable(drawable);
}
} else if (icon != 0) {
menuItem.iconView.setImageResource(icon);
}

View File

@ -51,7 +51,6 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.core.graphics.ColorUtils;
import androidx.core.view.ViewCompat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ImageLocation;
@ -67,6 +66,8 @@ import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.EditTextBoldCursor;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.RLottieImageView;
import java.util.ArrayList;
@ -133,7 +134,7 @@ public class ActionBarMenuItem extends FrameLayout {
private ArrayList<SearchFilterView> searchFilterViews = new ArrayList<>();
private TextView searchFieldCaption;
private ImageView clearButton;
protected ImageView iconView;
protected RLottieImageView iconView;
protected TextView textView;
private FrameLayout searchContainer;
private boolean isSearchField;
@ -188,7 +189,7 @@ public class ActionBarMenuItem extends FrameLayout {
}
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT));
} else {
iconView = new ImageView(context);
iconView = new RLottieImageView(context);
iconView.setScaleType(ImageView.ScaleType.CENTER);
iconView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
addView(iconView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
@ -426,14 +427,18 @@ public class ActionBarMenuItem extends FrameLayout {
}
public ActionBarMenuSubItem addSubItem(int id, int icon, CharSequence text) {
return addSubItem(id, icon, text, false);
return addSubItem(id, icon, null, text, false);
}
public ActionBarMenuSubItem addSubItem(int id, int icon, CharSequence text, boolean needCheck) {
return addSubItem(id, icon, null, text, needCheck);
}
public ActionBarMenuSubItem addSubItem(int id, int icon, Drawable iconDrawable, CharSequence text, boolean needCheck) {
createPopupLayout();
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext(), needCheck, false, false);
cell.setTextAndIcon(text, icon);
cell.setTextAndIcon(text, icon, iconDrawable);
cell.setMinimumWidth(AndroidUtilities.dp(196));
cell.setTag(id);
popupLayout.addView(cell);
@ -839,10 +844,14 @@ public class ActionBarMenuItem extends FrameLayout {
if (iconView == null) {
return;
}
iconView.setImageDrawable(drawable);
if (drawable instanceof RLottieDrawable) {
iconView.setAnimation((RLottieDrawable) drawable);
} else {
iconView.setImageDrawable(drawable);
}
}
public ImageView getIconView() {
public RLottieImageView getIconView() {
return iconView;
}

View File

@ -3,6 +3,7 @@ package org.telegram.ui.ActionBar;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
@ -19,6 +20,7 @@ import org.telegram.ui.Components.LayoutHelper;
public class ActionBarMenuSubItem extends FrameLayout {
private TextView textView;
private TextView subtextView;
private ImageView imageView;
private ImageView checkView;
@ -82,9 +84,17 @@ public class ActionBarMenuSubItem extends FrameLayout {
}
public void setTextAndIcon(CharSequence text, int icon) {
setTextAndIcon(text, icon, null);
}
public void setTextAndIcon(CharSequence text, int icon, Drawable iconDrawable) {
textView.setText(text);
if (icon != 0 || checkView != null) {
imageView.setImageResource(icon);
if (icon != 0 || iconDrawable != null || checkView != null) {
if (iconDrawable != null) {
imageView.setImageDrawable(iconDrawable);
} else {
imageView.setImageResource(icon);
}
imageView.setVisibility(VISIBLE);
textView.setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(43), 0, LocaleController.isRTL ? AndroidUtilities.dp(43) : 0, 0);
} else {
@ -118,10 +128,38 @@ public class ActionBarMenuSubItem extends FrameLayout {
textView.setText(text);
}
public void setSubtext(String text) {
if (subtextView == null) {
subtextView = new TextView(getContext());
subtextView.setLines(1);
subtextView.setSingleLine(true);
subtextView.setGravity(Gravity.LEFT);
subtextView.setEllipsize(TextUtils.TruncateAt.END);
subtextView.setTextColor(0xff7C8286);
subtextView.setVisibility(GONE);
subtextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
subtextView.setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(43), 0, LocaleController.isRTL ? AndroidUtilities.dp(43) : 0, 0);
addView(subtextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, 0, 10, 0, 0));
}
boolean visible = !TextUtils.isEmpty(text);
boolean oldVisible = subtextView.getVisibility() == VISIBLE;
if (visible != oldVisible) {
subtextView.setVisibility(visible ? VISIBLE : GONE);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) textView.getLayoutParams();
layoutParams.bottomMargin = visible ? AndroidUtilities.dp(10) : 0;
textView.setLayoutParams(layoutParams);
}
subtextView.setText(text);
}
public TextView getTextView() {
return textView;
}
public ImageView getImageView() {
return imageView;
}
public void setSelectorColor(int selectorColor) {
if (this.selectorColor != selectorColor) {
this.selectorColor = selectorColor;

View File

@ -143,6 +143,8 @@ public class BottomSheet extends Dialog {
protected String navBarColorKey = Theme.key_windowBackgroundGray;
protected int navBarColor;
private OnDismissListener onHideListener;
public void setDisableScroll(boolean b) {
disableScroll = b;
}
@ -725,7 +727,11 @@ public class BottomSheet extends Dialog {
container.setOnApplyWindowInsetsListener((v, insets) -> {
lastInsets = insets;
v.requestLayout();
return insets.consumeSystemWindowInsets();
if (Build.VERSION.SDK_INT >= 30) {
return WindowInsets.CONSUMED;
} else {
return insets.consumeSystemWindowInsets();
}
});
container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
@ -738,6 +744,9 @@ public class BottomSheet extends Dialog {
super.onCreate(savedInstanceState);
Window window = getWindow();
/*if (Build.VERSION.SDK_INT >= 30) {
window.setDecorFitsSystemWindows(true);
}*/
window.setWindowAnimations(R.style.DialogNoAnimation);
setContentView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
@ -998,6 +1007,10 @@ public class BottomSheet extends Dialog {
}
}
public void setOnHideListener(OnDismissListener listener) {
onHideListener = listener;
}
private void startOpenAnimation() {
if (dismissed) {
return;
@ -1173,6 +1186,9 @@ public class BottomSheet extends Dialog {
return;
}
dismissed = true;
if (onHideListener != null) {
onHideListener.onDismiss(this);
}
cancelSheetAnimation();
if (!allowCustomAnimation || !onCustomCloseAnimation()) {
currentSheetAnimationType = 2;

View File

@ -119,7 +119,11 @@ public class DrawerLayoutContainer extends FrameLayout {
hasCutout = cutout != null && cutout.getBoundingRects().size() != 0;
}
invalidate();
return insets.consumeSystemWindowInsets();
if (Build.VERSION.SDK_INT >= 30) {
return WindowInsets.CONSUMED;
} else {
return insets.consumeSystemWindowInsets();
}
});
setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

View File

@ -2019,6 +2019,7 @@ public class Theme {
public static Drawable dialogs_muteDrawable;
public static Drawable dialogs_verifiedDrawable;
public static ScamDrawable dialogs_scamDrawable;
public static ScamDrawable dialogs_fakeDrawable;
public static Drawable dialogs_verifiedCheckDrawable;
public static Drawable dialogs_pinnedDrawable;
public static Drawable dialogs_mentionDrawable;
@ -5886,7 +5887,7 @@ public class Theme {
}
}
private static void applyDayNightThemeMaybe(boolean night) {
public static void applyDayNightThemeMaybe(boolean night) {
if (previousTheme != null) {
return;
}
@ -6907,7 +6908,8 @@ public class Theme {
dialogs_broadcastDrawable = resources.getDrawable(R.drawable.list_broadcast);
dialogs_muteDrawable = resources.getDrawable(R.drawable.list_mute).mutate();
dialogs_verifiedDrawable = resources.getDrawable(R.drawable.verified_area);
dialogs_scamDrawable = new ScamDrawable(11);
dialogs_scamDrawable = new ScamDrawable(11, 0);
dialogs_fakeDrawable = new ScamDrawable(11, 1);
dialogs_verifiedCheckDrawable = resources.getDrawable(R.drawable.verified_check);
dialogs_mentionDrawable = resources.getDrawable(R.drawable.mentionchatslist);
dialogs_botDrawable = resources.getDrawable(R.drawable.list_bot);
@ -6969,6 +6971,7 @@ public class Theme {
setDrawableColorByKey(dialogs_verifiedCheckDrawable, key_chats_verifiedCheck);
setDrawableColorByKey(dialogs_holidayDrawable, key_actionBarDefaultTitle);
setDrawableColorByKey(dialogs_scamDrawable, key_chats_draft);
setDrawableColorByKey(dialogs_fakeDrawable, key_chats_draft);
}
public static void destroyResources() {

View File

@ -30,6 +30,7 @@ import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.ui.Components.AudioPlayerAlert;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.ChatBigEmptyView;
@ -62,6 +63,8 @@ import java.util.HashMap;
import androidx.viewpager.widget.ViewPager;
import com.google.android.exoplayer2.util.Log;
public class ThemeDescription {
public static int FLAG_BACKGROUND = 0x00000001;
@ -533,6 +536,13 @@ public class ThemeDescription {
} else if ((changeFlags & FLAG_TEXTCOLOR) != 0) {
if (child instanceof TextView) {
((TextView) child).setTextColor(color);
} else if (child instanceof AudioPlayerAlert.ClippingTextViewSwitcher) {
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? ((AudioPlayerAlert.ClippingTextViewSwitcher) child).getTextView() : ((AudioPlayerAlert.ClippingTextViewSwitcher) child).getNextTextView();
if (textView != null) {
textView.setTextColor(color);
}
}
}
} else if ((changeFlags & FLAG_SERVICEBACKGROUND) != 0) {
Drawable background = child.getBackground();
@ -710,6 +720,32 @@ public class ThemeDescription {
} else {
((SeekBarView) object).setInnerColor(color);
}
} else if (object instanceof AudioPlayerAlert.ClippingTextViewSwitcher) {
if ((changeFlags & FLAG_FASTSCROLL) != 0) {
for (int k = 0; k < 2; k++) {
TextView textView = k == 0 ? ((AudioPlayerAlert.ClippingTextViewSwitcher) object).getTextView() : ((AudioPlayerAlert.ClippingTextViewSwitcher) object).getNextTextView();
if (textView != null) {
CharSequence text = textView.getText();
if (text instanceof SpannedString) {
TypefaceSpan[] spans = ((SpannedString) text).getSpans(0, text.length(), TypefaceSpan.class);
if (spans != null && spans.length > 0) {
for (int i = 0; i < spans.length; i++) {
spans[i].setColor(color);
}
}
}
}
}
} else if ((changeFlags & FLAG_TEXTCOLOR) != 0) {
if ((changeFlags & FLAG_CHECKTAG) == 0 || checkTag(currentKey, (View) object)) {
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? ((AudioPlayerAlert.ClippingTextViewSwitcher) object).getTextView() : ((AudioPlayerAlert.ClippingTextViewSwitcher) object).getNextTextView();
if (textView != null) {
textView.setTextColor(color);
}
}
}
}
}
}
}

View File

@ -10,6 +10,9 @@ package org.telegram.ui.Adapters;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
@ -27,13 +30,16 @@ import androidx.viewpager.widget.ViewPager;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.DownloadController;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
@ -44,10 +50,12 @@ import org.telegram.ui.Cells.DialogCell;
import org.telegram.ui.Cells.DialogMeUrlCell;
import org.telegram.ui.Cells.DialogsEmptyCell;
import org.telegram.ui.Cells.HeaderCell;
import org.telegram.ui.Cells.LoadingCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Cells.UserCell;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.FlickerLoadingView;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.PullForegroundDrawable;
import org.telegram.ui.Components.RecyclerListView;
@ -62,7 +70,9 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
private Context mContext;
private ArchiveHintCell archiveHintCell;
private ArrayList<TLRPC.TL_contact> onlineContacts;
private int dialogsCount;
private int prevContactsCount;
private int prevDialogsCount;
private int dialogsType;
private int folderId;
private long openedDialogId;
@ -77,10 +87,19 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
private long lastSortTime;
private PullForegroundDrawable pullForegroundDrawable;
private DialogsPreloader preloader;
private Drawable arrowDrawable;
public DialogsAdapter(Context context, int type, int folder, boolean onlySelect, ArrayList<Long> selected, int account) {
private ArrayList<TLRPC.Document> preloadedStickers = new ArrayList<>();
private boolean preloadingSticker;
private DialogsPreloader preloader;
private boolean forceShowEmptyCell;
private DialogsActivity parentFragment;
public DialogsAdapter(DialogsActivity fragment, Context context, int type, int folder, boolean onlySelect, ArrayList<Long> selected, int account) {
mContext = context;
parentFragment = fragment;
dialogsType = type;
folderId = folder;
isOnlySelect = onlySelect;
@ -114,6 +133,10 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
}
if (showArchiveHint) {
position -= 2;
} else if (dialogsType == 11 || dialogsType == 13) {
position -= 2;
} else if (dialogsType == 12) {
position -= 1;
}
return position;
}
@ -128,11 +151,37 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
notifyDataSetChanged();
}
private void preloadGreetingsSticker() {
if (preloadingSticker) {
return;
}
preloadingSticker = true;
TLRPC.TL_messages_getStickers req = new TLRPC.TL_messages_getStickers();
req.emoticon = "\uD83D\uDC4B" + Emoji.fixEmoji("");
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
if (response instanceof TLRPC.TL_messages_stickers) {
ArrayList<TLRPC.Document> list = ((TLRPC.TL_messages_stickers) response).stickers;
if (!list.isEmpty()) {
for (int a = 0; a < 5; a++) {
TLRPC.Document sticker = list.get(Math.abs(Utilities.random.nextInt() % list.size()));
AndroidUtilities.runOnUIThread(() -> FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(sticker), sticker, null, 0, 1));
preloadedStickers.add(sticker);
}
}
}
});
}
public TLRPC.Document getPreloadedSticker() {
return onlineContacts != null && !preloadedStickers.isEmpty() ? preloadedStickers.get(Utilities.random.nextInt(preloadedStickers.size())) : null;
}
@Override
public int getItemCount() {
ArrayList<TLRPC.Dialog> array = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen);
int dialogsCount = array.size();
if (dialogsType != 7 && dialogsType != 8 && dialogsCount == 0 && (folderId != 0 || MessagesController.getInstance(currentAccount).isLoadingDialogs(folderId) || !MessagesController.getInstance(currentAccount).isDialogsEndReached(folderId))) {
MessagesController messagesController = MessagesController.getInstance(currentAccount);
ArrayList<TLRPC.Dialog> array = parentFragment.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen);
dialogsCount = array.size();
if (!forceShowEmptyCell && dialogsType != 7 && dialogsType != 8 && dialogsType != 11 && dialogsCount == 0 && (folderId != 0 || messagesController.isLoadingDialogs(folderId) || !MessagesController.getInstance(currentAccount).isDialogsEndReached(folderId))) {
onlineContacts = null;
if (folderId == 1 && showArchiveHint) {
return (currentCount = 2);
@ -145,52 +194,76 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
count++;
}
} else {
if (!MessagesController.getInstance(currentAccount).isDialogsEndReached(folderId) || dialogsCount == 0) {
if (!messagesController.isDialogsEndReached(folderId) || dialogsCount == 0) {
count++;
}
}
boolean hasContacts = false;
if (hasHints) {
count += 2 + MessagesController.getInstance(currentAccount).hintDialogs.size();
} else if (dialogsType == 0 && dialogsCount == 0 && folderId == 0) {
count += 2 + messagesController.hintDialogs.size();
} else if (dialogsType == 0 && dialogsCount <= 10 && folderId == 0 && messagesController.isDialogsEndReached(folderId)) {
if (ContactsController.getInstance(currentAccount).contacts.isEmpty() && ContactsController.getInstance(currentAccount).isLoadingContacts()) {
onlineContacts = null;
return (currentCount = 0);
}
if (!ContactsController.getInstance(currentAccount).contacts.isEmpty()) {
if (onlineContacts == null || prevContactsCount != ContactsController.getInstance(currentAccount).contacts.size()) {
if (onlineContacts == null || prevDialogsCount != messagesController.dialogs_dict.size() || prevContactsCount != ContactsController.getInstance(currentAccount).contacts.size()) {
onlineContacts = new ArrayList<>(ContactsController.getInstance(currentAccount).contacts);
prevContactsCount = onlineContacts.size();
prevDialogsCount = messagesController.dialogs_dict.size();
int selfId = UserConfig.getInstance(currentAccount).clientUserId;
for (int a = 0, N = onlineContacts.size(); a < N; a++) {
if (onlineContacts.get(a).user_id == selfId) {
int userId = onlineContacts.get(a).user_id;
if (userId == selfId || messagesController.dialogs_dict.get(userId) != null) {
onlineContacts.remove(a);
break;
a--;
N--;
}
}
if (onlineContacts.isEmpty()) {
onlineContacts = null;
}
sortOnlineContacts(false);
}
count += onlineContacts.size() + 2;
hasContacts = true;
if (onlineContacts != null) {
count += onlineContacts.size() + 2;
hasContacts = true;
}
}
}
if (!hasContacts && onlineContacts != null) {
onlineContacts = null;
if (folderId == 0 && onlineContacts != null) {
if (!hasContacts) {
onlineContacts = null;
} else {
preloadGreetingsSticker();
}
}
if (folderId == 1 && showArchiveHint) {
count += 2;
}
if (folderId == 0 && dialogsCount != 0) {
count++;
if (dialogsCount > 10 && dialogsType == 0) {
count++;
}
}
if (dialogsType == 11 || dialogsType == 13) {
count += 2;
} else if (dialogsType == 12) {
count += 1;
}
currentCount = count;
return count;
}
public TLObject getItem(int i) {
if (onlineContacts != null) {
i -= 3;
if (onlineContacts != null && (dialogsCount == 0 || i >= dialogsCount)) {
if (dialogsCount == 0) {
i -= 3;
} else {
i -= dialogsCount + 2;
}
if (i < 0 || i >= onlineContacts.size()) {
return null;
}
@ -198,8 +271,12 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
}
if (showArchiveHint) {
i -= 2;
} else if (dialogsType == 11 || dialogsType == 13) {
i -= 2;
} else if (dialogsType == 12) {
i -= 1;
}
ArrayList<TLRPC.Dialog> arrayList = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen);
ArrayList<TLRPC.Dialog> arrayList = parentFragment.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen);
if (hasHints) {
int count = MessagesController.getInstance(currentAccount).hintDialogs.size();
if (i < 2 + count) {
@ -257,7 +334,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
return 0;
} else if (status1 < 0 && status2 > 0 || status1 == 0 && status2 != 0) {
return -1;
} else if (status2 < 0 && status1 > 0 || status2 == 0 && status1 != 0) {
} else if (status2 < 0 || status1 != 0) {
return 1;
}
return 0;
@ -299,7 +376,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
int viewType = holder.getItemViewType();
return viewType != 1 && viewType != 5 && viewType != 3 && viewType != 8 && viewType != 7 && viewType != 9 && viewType != 10;
return viewType != 1 && viewType != 5 && viewType != 3 && viewType != 8 && viewType != 7 && viewType != 9 && viewType != 10 && viewType != 11;
}
@Override
@ -307,13 +384,16 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
View view;
switch (viewType) {
case 0:
DialogCell dialogCell = new DialogCell(mContext, true, false, currentAccount);
DialogCell dialogCell = new DialogCell(parentFragment, mContext, true, false, currentAccount);
dialogCell.setArchivedPullAnimation(pullForegroundDrawable);
dialogCell.setPreloader(preloader);
view = dialogCell;
break;
case 1:
view = new LoadingCell(mContext);
FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext);
flickerLoadingView.setIsSingleCell(true);
flickerLoadingView.setViewType(FlickerLoadingView.DIALOG_CELL_TYPE);
view = flickerLoadingView;
break;
case 2: {
HeaderCell headerCell = new HeaderCell(mContext);
@ -359,17 +439,16 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
view = new UserCell(mContext, 8, 0, false);
break;
case 7:
HeaderCell headerCell = new HeaderCell(mContext);
headerCell.setText(LocaleController.getString("YourContacts", R.string.YourContacts));
view = headerCell;
view = new HeaderCell(mContext);
break;
case 8:
case 8: {
view = new ShadowSectionCell(mContext);
Drawable drawable = Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow);
CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), drawable);
combinedDrawable.setFullsize(true);
view.setBackgroundDrawable(combinedDrawable);
break;
}
case 9:
view = archiveHintCell;
if (archiveHintCell.getParent() != null) {
@ -377,12 +456,11 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
parent.removeView(archiveHintCell);
}
break;
case 10:
default: {
case 10: {
view = new View(mContext) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen).size();
int size = parentFragment.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen).size();
boolean hasArchive = dialogsType == 0 && MessagesController.getInstance(currentAccount).dialogs_dict.get(DialogObject.makeFolderDialogId(1)) != null;
View parent = (View) getParent();
int height;
@ -399,6 +477,9 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
}
int cellHeight = AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72);
int dialogsHeight = size * cellHeight + (size - 1);
if (onlineContacts != null) {
dialogsHeight += onlineContacts.size() * AndroidUtilities.dp(58) + (onlineContacts.size() - 1) + AndroidUtilities.dp(52);
}
int archiveHeight = (hasArchive ? cellHeight + 1 : 0);
if (dialogsHeight < height) {
height = height - dialogsHeight + archiveHeight;
@ -423,6 +504,65 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height);
}
};
break;
}
case 11: {
view = new TextInfoPrivacyCell(mContext) {
private int movement;
private float moveProgress;
private long lastUpdateTime;
private int x;
private int y;
@Override
protected void onTextDraw() {
if (arrowDrawable != null) {
Rect bounds = arrowDrawable.getBounds();
int dx = (int) (moveProgress * AndroidUtilities.dp(3));
arrowDrawable.setBounds(x + dx, y + AndroidUtilities.dp(1), x + dx + bounds.width(), y + AndroidUtilities.dp(1) + bounds.height());
long newUpdateTime = SystemClock.elapsedRealtime();
long dt = newUpdateTime - lastUpdateTime;
if (dt > 17) {
dt = 17;
}
lastUpdateTime = newUpdateTime;
if (movement == 0) {
moveProgress += dt / 664.0f;
if (moveProgress >= 1.0f) {
movement = 1;
moveProgress = 1.0f;
}
} else {
moveProgress -= dt / 664.0f;
if (moveProgress <= 0.0f) {
movement = 0;
moveProgress = 0.0f;
}
}
getTextView().invalidate();
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (arrowDrawable != null) {
x = arrowDrawable.getBounds().left;
y = arrowDrawable.getBounds().top;
}
}
};
Drawable drawable = Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow);
CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), drawable);
combinedDrawable.setFullsize(true);
view.setBackgroundDrawable(combinedDrawable);
break;
}
case 12:
default: {
view = new TextCell(mContext);
}
}
view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, viewType == 5 ? RecyclerView.LayoutParams.MATCH_PARENT : RecyclerView.LayoutParams.WRAP_CONTENT));
@ -436,11 +576,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
DialogCell cell = (DialogCell) holder.itemView;
TLRPC.Dialog dialog = (TLRPC.Dialog) getItem(i);
TLRPC.Dialog nextDialog = (TLRPC.Dialog) getItem(i + 1);
if (folderId == 0) {
cell.useSeparator = (i != getItemCount() - 2);
} else {
cell.useSeparator = (i != getItemCount() - 1);
}
cell.useSeparator = nextDialog != null;
cell.fullSeparator = dialog.pinned && nextDialog != null && !nextDialog.pinned;
if (dialogsType == 0) {
if (AndroidUtilities.isTablet()) {
@ -474,25 +610,76 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
}
case 6: {
UserCell cell = (UserCell) holder.itemView;
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(onlineContacts.get(i - 3).user_id);
int position;
if (dialogsCount == 0) {
position = i - 3;
} else {
position = i - dialogsCount - 2;
}
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(onlineContacts.get(position).user_id);
cell.setData(user, null, null, 0);
break;
}
case 7: {
HeaderCell cell = (HeaderCell) holder.itemView;
if (dialogsType == 11 || dialogsType == 12 || dialogsType == 13) {
if (i == 0) {
cell.setText(LocaleController.getString("ImportHeader", R.string.ImportHeader));
} else {
cell.setText(LocaleController.getString("ImportHeaderContacts", R.string.ImportHeaderContacts));
}
} else {
cell.setText(LocaleController.getString("YourContacts", R.string.YourContacts));
}
break;
}
case 11: {
TextInfoPrivacyCell cell = (TextInfoPrivacyCell) holder.itemView;
cell.setText(LocaleController.getString("TapOnThePencil", R.string.TapOnThePencil));
if (arrowDrawable == null) {
arrowDrawable = mContext.getResources().getDrawable(R.drawable.arrow_newchat);
arrowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4), PorterDuff.Mode.MULTIPLY));
}
TextView textView = cell.getTextView();
textView.setCompoundDrawablePadding(AndroidUtilities.dp(4));
textView.setCompoundDrawablesWithIntrinsicBounds(null, null, arrowDrawable, null);
textView.getLayoutParams().width = LayoutHelper.WRAP_CONTENT;
break;
}
case 12: {
TextCell cell = (TextCell) holder.itemView;
cell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4);
cell.setTextAndIcon(LocaleController.getString("CreateGroupForImport", R.string.CreateGroupForImport), R.drawable.groups_create, dialogsCount != 0);
cell.setIsInDialogs();
cell.setOffsetFromImage(75);
break;
}
}
}
@Override
public int getItemViewType(int i) {
if (onlineContacts != null) {
if (i == 0) {
return 5;
} else if (i == 1) {
return 8;
} else if (i == 2) {
return 7;
if (dialogsCount == 0) {
if (i == 0) {
return 5;
} else if (i == 1) {
return 8;
} else if (i == 2) {
return 7;
}
} else {
return 6;
if (i < dialogsCount) {
return 0;
} else if (i == dialogsCount) {
return 8;
} else if (i == dialogsCount + 1) {
return 7;
} else if (i == currentCount - 1) {
return 10;
}
}
return 6;
} else if (hasHints) {
int count = MessagesController.getInstance(currentAccount).hintDialogs.size();
if (i < 2 + count) {
@ -513,10 +700,27 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
} else {
i -= 2;
}
} else if (dialogsType == 11 || dialogsType == 13) {
if (i == 0) {
return 7;
} else if (i == 1) {
return 12;
} else {
i -= 2;
}
} else if (dialogsType == 12) {
if (i == 0) {
return 7;
} else {
i -= 1;
}
}
int size = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen).size();
if (folderId == 0 && dialogsCount > 10 && i == currentCount - 2 && dialogsType == 0) {
return 11;
}
int size = parentFragment.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen).size();
if (i == size) {
if (dialogsType != 7 && dialogsType != 8 && !MessagesController.getInstance(currentAccount).isDialogsEndReached(folderId)) {
if (!forceShowEmptyCell && dialogsType != 7 && dialogsType != 8 && !MessagesController.getInstance(currentAccount).isDialogsEndReached(folderId)) {
return 1;
} else if (size == 0) {
return 5;
@ -531,7 +735,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
@Override
public void notifyItemMoved(int fromPosition, int toPosition) {
ArrayList<TLRPC.Dialog> dialogs = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, false);
ArrayList<TLRPC.Dialog> dialogs = parentFragment.getDialogsArray(currentAccount, dialogsType, folderId, false);
int fromIndex = fixPosition(fromPosition);
int toIndex = fixPosition(toPosition);
TLRPC.Dialog fromDialog = dialogs.get(fromIndex);
@ -682,4 +886,12 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
resumed = false;
}
}
public int getCurrentCount() {
return currentCount;
}
public void setForceShowEmptyCell(boolean forceShowEmptyCell) {
this.forceShowEmptyCell = forceShowEmptyCell;
}
}

View File

@ -93,6 +93,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
private ArrayList<FiltersView.DateData> localTipDates = new ArrayList<>();
private FilteredSearchView.Delegate filtersDelegate;
private int folderId;
private int currentItemCount;
public boolean isSearching() {
return waitingResponseCount > 0;
@ -358,11 +359,11 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
}
public boolean hasRecentSearch() {
return dialogsType != 2 && dialogsType != 4 && dialogsType != 5 && dialogsType != 6 && (!recentSearchObjects.isEmpty() || !MediaDataController.getInstance(currentAccount).hints.isEmpty());
return dialogsType != 2 && dialogsType != 4 && dialogsType != 5 && dialogsType != 6 && dialogsType != 11 && (!recentSearchObjects.isEmpty() || !MediaDataController.getInstance(currentAccount).hints.isEmpty());
}
public boolean isRecentSearchDisplayed() {
return needMessagesSearch != 2 && !searchWas && (!recentSearchObjects.isEmpty() || !MediaDataController.getInstance(currentAccount).hints.isEmpty()) && dialogsType != 2 && dialogsType != 4 && dialogsType != 5 && dialogsType != 6;
return needMessagesSearch != 2 && !searchWas && (!recentSearchObjects.isEmpty() || !MediaDataController.getInstance(currentAccount).hints.isEmpty()) && dialogsType != 2 && dialogsType != 4 && dialogsType != 5 && dialogsType != 6 && dialogsType != 11;
}
public void loadRecentSearch() {
@ -646,7 +647,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
searchResultNames.clear();
searchResultHashtags.clear();
searchAdapterHelper.mergeResults(null);
searchAdapterHelper.queryServerSearch(null, true, true, true, true, dialogsType == 2, 0, dialogsType == 0, 0, 0);
searchAdapterHelper.queryServerSearch(null, true, true, dialogsType != 11, dialogsType != 11, dialogsType == 2 || dialogsType == 11, 0, dialogsType == 0, 0, 0);
searchWas = false;
lastSearchId = 0;
waitingResponseCount = 0;
@ -695,7 +696,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
return;
}
if (needMessagesSearch != 2) {
searchAdapterHelper.queryServerSearch(query, true, dialogsType != 4, true, dialogsType != 4, dialogsType == 2, 0, dialogsType == 0, 0, searchId);
searchAdapterHelper.queryServerSearch(query, true, dialogsType != 4, true, dialogsType != 4 && dialogsType != 11, dialogsType == 2 || dialogsType == 1, 0, dialogsType == 0, 0, searchId);
} else {
waitingResponseCount -= 2;
}
@ -737,7 +738,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
if (messagesCount != 0) {
count += messagesCount + 1 + (messagesSearchEndReached ? 0 : 1);
}
return count;
return currentItemCount = count;
}
public Object getItem(int i) {
@ -865,7 +866,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
view = new GraySectionCell(mContext);
break;
case 2:
view = new DialogCell(mContext, false, true);
view = new DialogCell(null, mContext, false, true);
break;
case 3:
FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext);
@ -1181,4 +1182,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
filtersDelegate.updateFiltersView(false, null, localTipDates);
}
}
public int getCurrentItemCount() {
return currentItemCount;
}
}

View File

@ -67,7 +67,7 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
View view = null;
switch (viewType) {
case 0:
view = new DialogCell(mContext, false, true);
view = new DialogCell(null, mContext, false, true);
break;
case 1:
view = new LoadingCell(mContext);

View File

@ -18,6 +18,7 @@ import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
@ -90,7 +91,7 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement
String fileName = (String) args[0];
stickersToLoad.remove(fileName);
if (stickersToLoad.isEmpty()) {
boolean show = stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty();
boolean show = stickers != null && !stickers.isEmpty();
if (show) {
keywordResults = null;
}
@ -269,73 +270,76 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement
ConnectionsManager.getInstance(currentAccount).cancelRequest(lastReqId, true);
lastReqId = 0;
}
boolean serverStickersOnly = MessagesController.getInstance(currentAccount).suggestStickersApiOnly;
delayLocalResults = false;
final ArrayList<TLRPC.Document> recentStickers = MediaDataController.getInstance(currentAccount).getRecentStickersNoCopy(MediaDataController.TYPE_IMAGE);
final ArrayList<TLRPC.Document> favsStickers = MediaDataController.getInstance(currentAccount).getRecentStickersNoCopy(MediaDataController.TYPE_FAVE);
int recentsAdded = 0;
for (int a = 0, size = Math.min(20, recentStickers.size()); a < size; a++) {
TLRPC.Document document = recentStickers.get(a);
if (isValidSticker(document, lastSticker)) {
addStickerToResult(document, "recent");
recentsAdded++;
if (recentsAdded >= 5) {
break;
if (!serverStickersOnly) {
final ArrayList<TLRPC.Document> recentStickers = MediaDataController.getInstance(currentAccount).getRecentStickersNoCopy(MediaDataController.TYPE_IMAGE);
final ArrayList<TLRPC.Document> favsStickers = MediaDataController.getInstance(currentAccount).getRecentStickersNoCopy(MediaDataController.TYPE_FAVE);
int recentsAdded = 0;
for (int a = 0, size = Math.min(20, recentStickers.size()); a < size; a++) {
TLRPC.Document document = recentStickers.get(a);
if (isValidSticker(document, lastSticker)) {
addStickerToResult(document, "recent");
recentsAdded++;
if (recentsAdded >= 5) {
break;
}
}
}
}
for (int a = 0, size = favsStickers.size(); a < size; a++) {
TLRPC.Document document = favsStickers.get(a);
if (isValidSticker(document, lastSticker)) {
addStickerToResult(document, "fav");
}
}
HashMap<String, ArrayList<TLRPC.Document>> allStickers = MediaDataController.getInstance(currentAccount).getAllStickers();
ArrayList<TLRPC.Document> newStickers = allStickers != null ? allStickers.get(lastSticker) : null;
if (newStickers != null && !newStickers.isEmpty()) {
addStickersToResult(newStickers, null);
}
if (stickers != null) {
Collections.sort(stickers, new Comparator<StickerResult>() {
private int getIndex(StickerResult result) {
for (int a = 0; a < favsStickers.size(); a++) {
if (favsStickers.get(a).id == result.sticker.id) {
return a + 2000000;
}
}
for (int a = 0; a < Math.min(20, recentStickers.size()); a++) {
if (recentStickers.get(a).id == result.sticker.id) {
return recentStickers.size() - a + 1000000;
}
}
return -1;
for (int a = 0, size = favsStickers.size(); a < size; a++) {
TLRPC.Document document = favsStickers.get(a);
if (isValidSticker(document, lastSticker)) {
addStickerToResult(document, "fav");
}
}
@Override
public int compare(StickerResult lhs, StickerResult rhs) {
boolean isAnimated1 = MessageObject.isAnimatedStickerDocument(lhs.sticker, true);
boolean isAnimated2 = MessageObject.isAnimatedStickerDocument(rhs.sticker, true);
if (isAnimated1 == isAnimated2) {
int idx1 = getIndex(lhs);
int idx2 = getIndex(rhs);
if (idx1 > idx2) {
return -1;
} else if (idx1 < idx2) {
return 1;
HashMap<String, ArrayList<TLRPC.Document>> allStickers = MediaDataController.getInstance(currentAccount).getAllStickers();
ArrayList<TLRPC.Document> newStickers = allStickers != null ? allStickers.get(lastSticker) : null;
if (newStickers != null && !newStickers.isEmpty()) {
addStickersToResult(newStickers, null);
}
if (stickers != null) {
Collections.sort(stickers, new Comparator<StickerResult>() {
private int getIndex(StickerResult result) {
for (int a = 0; a < favsStickers.size(); a++) {
if (favsStickers.get(a).id == result.sticker.id) {
return a + 2000000;
}
}
return 0;
} else {
if (isAnimated1 && !isAnimated2) {
return -1;
for (int a = 0; a < Math.min(20, recentStickers.size()); a++) {
if (recentStickers.get(a).id == result.sticker.id) {
return recentStickers.size() - a + 1000000;
}
}
return -1;
}
@Override
public int compare(StickerResult lhs, StickerResult rhs) {
boolean isAnimated1 = MessageObject.isAnimatedStickerDocument(lhs.sticker, true);
boolean isAnimated2 = MessageObject.isAnimatedStickerDocument(rhs.sticker, true);
if (isAnimated1 == isAnimated2) {
int idx1 = getIndex(lhs);
int idx2 = getIndex(rhs);
if (idx1 > idx2) {
return -1;
} else if (idx1 < idx2) {
return 1;
}
return 0;
} else {
return 1;
if (isAnimated1) {
return -1;
} else {
return 1;
}
}
}
}
});
});
}
}
if (SharedConfig.suggestStickers == 0) {
if (SharedConfig.suggestStickers == 0 || serverStickersOnly) {
searchServerStickers(lastSticker, originalEmoji);
}

View File

@ -155,28 +155,25 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
MediaDataController.getInstance(currentAccount).fetchNewEmojiKeywords(newLanguage);
}
delegate.setLastSearchKeyboardLanguage(newLanguage);
MediaDataController.getInstance(currentAccount).getEmojiSuggestions(delegate.getLastSearchKeyboardLanguage(), searchQuery, false, new MediaDataController.KeywordResultCallback() {
@Override
public void run(ArrayList<MediaDataController.KeywordResult> param, String alias) {
if (lastId != emojiSearchId) {
return;
}
boolean added = false;
for (int a = 0, size = param.size(); a < size; a++) {
String emoji = param.get(a).emoji;
ArrayList<TLRPC.Document> newStickers = allStickers != null ? allStickers.get(emoji) : null;
if (newStickers != null && !newStickers.isEmpty()) {
clear();
if (!emojiStickers.containsKey(newStickers)) {
emojiStickers.put(newStickers, emoji);
emojiArrays.add(newStickers);
added = true;
}
MediaDataController.getInstance(currentAccount).getEmojiSuggestions(delegate.getLastSearchKeyboardLanguage(), searchQuery, false, (param, alias) -> {
if (lastId != emojiSearchId) {
return;
}
boolean added = false;
for (int a = 0, size = param.size(); a < size; a++) {
String emoji = param.get(a).emoji;
ArrayList<TLRPC.Document> newStickers = allStickers != null ? allStickers.get(emoji) : null;
if (newStickers != null && !newStickers.isEmpty()) {
clear();
if (!emojiStickers.containsKey(newStickers)) {
emojiStickers.put(newStickers, emoji);
emojiArrays.add(newStickers);
added = true;
}
}
if (added) {
notifyDataSetChanged();
}
}
if (added) {
notifyDataSetChanged();
}
});
}
@ -400,7 +397,6 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
return new RecyclerListView.Holder(view);
}
@SuppressWarnings("unchecked")
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
@ -449,8 +445,6 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
if (holder.getItemViewType() == 3) {
bindFeaturedStickerSetInfoCell((FeaturedStickerSetInfoCell) holder.itemView, position, true);
}
} else {
super.onBindViewHolder(holder, position, payloads);
}
}
@ -545,7 +539,6 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
installing = false;
} else if (removing && !cell.isInstalled()) {
removingStickerSets.remove(stickerSetCovered.set.id);
removing = false;
}
}
cell.setAddDrawProgress(!forceInstalled && installing, animated);
@ -601,7 +594,7 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
}
}
int count = (int) Math.ceil(documentsCount / (float) delegate.getStickersPerRow());
for (int b = 0, N = count; b < N; b++) {
for (int b = 0; b < count; b++) {
rowStartPack.put(startRow + b, documentsCount);
}
totalItems += count * delegate.getStickersPerRow();

View File

@ -3033,7 +3033,13 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
//containerView.setFitsSystemWindows(true);
if (Build.VERSION.SDK_INT >= 21) {
windowView.setFitsSystemWindows(true);
containerView.setOnApplyWindowInsetsListener((v, insets) -> insets.consumeSystemWindowInsets());
containerView.setOnApplyWindowInsetsListener((v, insets) -> {
if (Build.VERSION.SDK_INT >= 30) {
return WindowInsets.CONSUMED;
} else {
return insets.consumeSystemWindowInsets();
}
});
}
fullscreenVideoContainer = new FrameLayout(activity);

View File

@ -299,6 +299,10 @@ public class BubbleActivity extends Activity implements ActionBarLayout.ActionBa
@Override
public void onBackPressed() {
if (mainFragmentsStack.size() == 1) {
super.onBackPressed();
return;
}
if (passcodeView.getVisibility() == View.VISIBLE) {
finish();
return;

View File

@ -1,9 +1,13 @@
package org.telegram.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.StateListAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.Outline;
import android.graphics.Paint;
@ -19,9 +23,11 @@ import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
@ -33,23 +39,29 @@ import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BackDrawable;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.CheckBoxCell;
import org.telegram.ui.Cells.LoadingCell;
import org.telegram.ui.Cells.LocationCell;
import org.telegram.ui.Cells.ProfileSearchCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.EmptyTextProgressView;
import org.telegram.ui.Components.FlickerLoadingView;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.NumberTextView;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.voip.VoIPHelper;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -61,12 +73,20 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
private LinearLayoutManager layoutManager;
private RecyclerListView listView;
private ImageView floatingButton;
private FlickerLoadingView flickerLoadingView;
private NumberTextView selectedDialogsCountTextView;
private ArrayList<View> actionModeViews = new ArrayList<>();
private ActionBarMenuItem otherItem;
private ArrayList<CallLogRow> calls = new ArrayList<>();
private boolean loading;
private boolean firstLoaded;
private boolean endReached;
private ArrayList<Integer> selectedIds = new ArrayList<>();
private int prevPosition;
private int prevTop;
private boolean scrollUpdated;
@ -79,10 +99,15 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
private ImageSpan iconOut, iconIn, iconMissed;
private TLRPC.User lastCallUser;
private boolean openTransitionStarted;
private static final int TYPE_OUT = 0;
private static final int TYPE_IN = 1;
private static final int TYPE_MISSED = 2;
private static final int delete_all_calls = 1;
private static final int delete = 2;
@Override
@SuppressWarnings("unchecked")
public void didReceivedNotification(int id, int account, Object... args) {
@ -119,6 +144,9 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
listViewAdapter.notifyItemInserted(0);
}
}
if (otherItem != null) {
otherItem.setVisibility(calls.isEmpty() ? View.GONE : View.VISIBLE);
}
} else if (id == NotificationCenter.messagesDeleted && firstLoaded) {
boolean scheduled = (Boolean) args[2];
if (scheduled) {
@ -140,8 +168,9 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
if (row.calls.size() == 0)
itrtr.remove();
}
if (didChange && listViewAdapter != null)
if (didChange && listViewAdapter != null) {
listViewAdapter.notifyDataSetChanged();
}
}
}
@ -149,6 +178,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
private ImageView imageView;
private ProfileSearchCell profileSearchCell;
private CheckBox2 checkBox;
public CustomCell(Context context) {
super(context);
@ -168,6 +198,19 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
imageView.setOnClickListener(callBtnClickListener);
imageView.setContentDescription(LocaleController.getString("Call", R.string.Call));
addView(imageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 8, 0, 8, 0));
checkBox = new CheckBox2(context, 21);
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
checkBox.setDrawUnchecked(false);
checkBox.setDrawBackgroundAsArc(3);
addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 42, 32, 42, 0));
}
public void setChecked(boolean checked, boolean animated) {
if (checkBox == null) {
return;
}
checkBox.setChecked(checked, animated);
}
}
@ -213,23 +256,40 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
redDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_calls_callReceivedRedIcon), PorterDuff.Mode.MULTIPLY));
iconMissed = new ImageSpan(redDrawable, ImageSpan.ALIGN_BOTTOM);
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setBackButtonDrawable(new BackDrawable(false));
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("Calls", R.string.Calls));
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@Override
public void onItemClick(int id) {
if (id == -1) {
finishFragment();
if (actionBar.isActionModeShowed()) {
hideActionMode(true);
} else {
finishFragment();
}
} else if (id == delete_all_calls) {
showDeleteAlert(true);
} else if (id == delete) {
showDeleteAlert(false);
}
}
});
ActionBarMenu menu = actionBar.createMenu();
otherItem = menu.addItem(10, R.drawable.ic_ab_other);
otherItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions));
otherItem.addSubItem(delete_all_calls, R.drawable.msg_delete, LocaleController.getString("DeleteAllCalls", R.string.DeleteAllCalls));
fragmentView = new FrameLayout(context);
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
FrameLayout frameLayout = (FrameLayout) fragmentView;
emptyView = new EmptyTextProgressView(context);
flickerLoadingView = new FlickerLoadingView(context);
flickerLoadingView.setViewType(FlickerLoadingView.CALL_LOG_TYPE);
flickerLoadingView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
flickerLoadingView.showDate(false);
emptyView = new EmptyTextProgressView(context, flickerLoadingView);
emptyView.setText(LocaleController.getString("NoCallLog", R.string.NoCallLog));
frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
@ -245,35 +305,21 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
return;
}
CallLogRow row = calls.get(position);
Bundle args = new Bundle();
args.putInt("user_id", row.user.id);
args.putInt("message_id", row.calls.get(0).id);
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats);
presentFragment(new ChatActivity(args), true);
if (actionBar.isActionModeShowed()) {
addOrRemoveSelectedDialog(row.calls, (CustomCell) view);
} else {
Bundle args = new Bundle();
args.putInt("user_id", row.user.id);
args.putInt("message_id", row.calls.get(0).id);
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats);
presentFragment(new ChatActivity(args), true);
}
});
listView.setOnItemLongClickListener((view, position) -> {
if (position < 0 || position >= calls.size()) {
return false;
}
final CallLogRow row = calls.get(position);
ArrayList<String> items = new ArrayList<>();
items.add(LocaleController.getString("Delete", R.string.Delete));
if (VoIPHelper.canRateCall((TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action)) {
items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem));
}
new AlertDialog.Builder(getParentActivity())
.setTitle(LocaleController.getString("Calls", R.string.Calls))
.setItems(items.toArray(new String[0]), (dialog, which) -> {
switch (which) {
case 0:
confirmAndDelete(row);
break;
case 1:
VoIPHelper.showRateAlert(getParentActivity(), (TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action);
break;
}
})
.show();
addOrRemoveSelectedDialog(calls.get(position).calls, (CustomCell) view);
return true;
});
listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@ -320,7 +366,6 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
emptyView.showTextView();
}
floatingButton = new ImageView(context);
floatingButton.setVisibility(View.VISIBLE);
floatingButton.setScaleType(ImageView.ScaleType.CENTER);
@ -368,6 +413,156 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
return fragmentView;
}
private void showDeleteAlert(boolean all) {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
if (all) {
builder.setTitle(LocaleController.getString("DeleteAllCalls", R.string.DeleteAllCalls));
builder.setMessage(LocaleController.getString("DeleteAllCallsText", R.string.DeleteAllCallsText));
} else {
builder.setTitle(LocaleController.getString("DeleteCalls", R.string.DeleteCalls));
builder.setMessage(LocaleController.getString("DeleteSelectedCallsText", R.string.DeleteSelectedCallsText));
}
final boolean[] checks = new boolean[]{false};
FrameLayout frameLayout = new FrameLayout(getParentActivity());
CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1);
cell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
cell.setText(LocaleController.getString("DeleteCallsForEveryone", R.string.DeleteCallsForEveryone), "", false, false);
cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(8) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(8), 0);
frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 8, 0, 8, 0));
cell.setOnClickListener(v -> {
CheckBoxCell cell1 = (CheckBoxCell) v;
checks[0] = !checks[0];
cell1.setChecked(checks[0], true);
});
builder.setView(frameLayout);
builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> {
if (all) {
deleteAllMessages(checks[0]);
calls.clear();
loading = false;
endReached = true;
otherItem.setVisibility(View.GONE);
listViewAdapter.notifyDataSetChanged();
} else {
getMessagesController().deleteMessages(new ArrayList<>(selectedIds), null, null, 0, 0, checks[0], false);
}
hideActionMode(false);
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
AlertDialog alertDialog = builder.create();
showDialog(alertDialog);
TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
if (button != null) {
button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2));
}
}
private void deleteAllMessages(boolean revoke) {
TLRPC.TL_messages_deletePhoneCallHistory req = new TLRPC.TL_messages_deletePhoneCallHistory();
req.revoke = revoke;
getConnectionsManager().sendRequest(req, (response, error) -> {
if (response != null) {
TLRPC.TL_messages_affectedFoundMessages res = (TLRPC.TL_messages_affectedFoundMessages) response;
TLRPC.TL_updateDeleteMessages updateDeleteMessages = new TLRPC.TL_updateDeleteMessages();
updateDeleteMessages.messages = res.messages;
updateDeleteMessages.pts = res.pts;
updateDeleteMessages.pts_count = res.pts_count;
final TLRPC.TL_updates updates = new TLRPC.TL_updates();
updates.updates.add(updateDeleteMessages);
getMessagesController().processUpdates(updates, false);
if (res.offset != 0) {
deleteAllMessages(revoke);
}
}
});
}
private void hideActionMode(boolean animated) {
actionBar.hideActionMode();
selectedIds.clear();
for (int a = 0, N = listView.getChildCount(); a < N; a++) {
CustomCell cell = (CustomCell) listView.getChildAt(a);
cell.setChecked(false, animated);
}
}
private boolean isSelected(ArrayList<TLRPC.Message> messages) {
for (int a = 0, N = messages.size(); a < N; a++) {
if (selectedIds.contains(messages.get(a).id)) {
return true;
}
}
return false;
}
private void createActionMode() {
if (actionBar.actionModeIsExist(null)) {
return;
}
final ActionBarMenu actionMode = actionBar.createActionMode();
selectedDialogsCountTextView = new NumberTextView(actionMode.getContext());
selectedDialogsCountTextView.setTextSize(18);
selectedDialogsCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
selectedDialogsCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon));
actionMode.addView(selectedDialogsCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0));
selectedDialogsCountTextView.setOnTouchListener((v, event) -> true);
actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete)));
}
private boolean addOrRemoveSelectedDialog(ArrayList<TLRPC.Message> messages, CustomCell cell) {
if (messages.isEmpty()) {
return false;
}
if (isSelected(messages)) {
for (int a = 0, N = messages.size(); a < N; a++) {
selectedIds.remove((Integer) messages.get(a).id);
}
cell.setChecked(false, true);
showOrUpdateActionMode();
return false;
} else {
for (int a = 0, N = messages.size(); a < N; a++) {
Integer id = messages.get(a).id;
if (!selectedIds.contains(id)) {
selectedIds.add(id);
}
}
cell.setChecked(true, true);
showOrUpdateActionMode();
return true;
}
}
private void showOrUpdateActionMode() {
boolean updateAnimated = false;
if (actionBar.isActionModeShowed()) {
if (selectedIds.isEmpty()) {
hideActionMode(true);
return;
}
updateAnimated = true;
} else {
createActionMode();
actionBar.showActionMode();
AnimatorSet animatorSet = new AnimatorSet();
ArrayList<Animator> animators = new ArrayList<>();
for (int a = 0; a < actionModeViews.size(); a++) {
View view = actionModeViews.get(a);
view.setPivotY(ActionBar.getCurrentActionBarHeight() / 2);
AndroidUtilities.clearDrawableAnimation(view);
animators.add(ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.1f, 1.0f));
}
animatorSet.playTogether(animators);
animatorSet.setDuration(200);
animatorSet.start();
}
selectedDialogsCountTextView.setNumber(selectedIds.size(), updateAnimated);
}
private void hideFloatingButton(boolean hide) {
if (floatingHidden == hide) {
return;
@ -397,6 +592,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
req.q = "";
req.offset_id = max_id;
int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
int oldCount = calls.size();
if (error == null) {
SparseArray<TLRPC.User> users = new SparseArray<>();
TLRPC.messages_Messages msgs = (TLRPC.messages_Messages) response;
@ -438,7 +634,12 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
endReached = true;
}
loading = false;
showItemsAnimated(oldCount);
if (!firstLoaded) {
resumeDelayedFragmentAnimation();
}
firstLoaded = true;
otherItem.setVisibility(calls.isEmpty() ? View.GONE : View.VISIBLE);
if (emptyView != null) {
emptyView.showTextView();
}
@ -449,25 +650,6 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid);
}
private void confirmAndDelete(final CallLogRow row) {
if (getParentActivity() == null) {
return;
}
new AlertDialog.Builder(getParentActivity())
.setTitle(LocaleController.getString("AppName", R.string.AppName))
.setMessage(LocaleController.getString("ConfirmDeleteCallLog", R.string.ConfirmDeleteCallLog))
.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialog, which) -> {
ArrayList<Integer> ids = new ArrayList<>();
for (TLRPC.Message msg : row.calls) {
ids.add(msg.id);
}
MessagesController.getInstance(currentAccount).deleteMessages(ids, null, null, 0, 0, false, false);
})
.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null)
.show()
.setCanceledOnTouchOutside(true);
}
@Override
public void onResume() {
super.onResume();
@ -529,7 +711,12 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
view.setTag(new ViewItem(cell.imageView, cell.profileSearchCell));
break;
case 1:
view = new LoadingCell(mContext);
FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext);
flickerLoadingView.setIsSingleCell(true);
flickerLoadingView.setViewType(FlickerLoadingView.CALL_LOG_TYPE);
flickerLoadingView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
flickerLoadingView.showDate(false);
view = flickerLoadingView;
break;
case 2:
default:
@ -540,6 +727,14 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
return new RecyclerListView.Holder(view);
}
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
if (holder.itemView instanceof CustomCell) {
CallLogRow row = calls.get(holder.getAdapterPosition());
((CustomCell) holder.itemView).setChecked(isSelected(row.calls), false);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == 0) {
@ -599,7 +794,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
private static class CallLogRow {
public TLRPC.User user;
public List<TLRPC.Message> calls;
public ArrayList<TLRPC.Message> calls;
public int type;
public boolean video;
}
@ -665,7 +860,81 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{View.class}, null, new Drawable[]{greenDrawable, greenDrawable2, Theme.calllog_msgCallUpRedDrawable, Theme.calllog_msgCallDownRedDrawable}, null, Theme.key_calls_callReceivedGreenIcon));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{View.class}, null, new Drawable[]{redDrawable, Theme.calllog_msgCallUpGreenDrawable, Theme.calllog_msgCallDownGreenDrawable}, null, Theme.key_calls_callReceivedRedIcon));
themeDescriptions.add(new ThemeDescription(flickerLoadingView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
return themeDescriptions;
}
@Override
protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
super.onTransitionAnimationStart(isOpen, backward);
if (isOpen) {
openTransitionStarted = true;
}
}
@Override
public boolean needDelayOpenAnimation() {
return true;
}
private void showItemsAnimated(int from) {
if (isPaused || !openTransitionStarted) {
return;
}
View progressView = null;
for (int i = 0; i < listView.getChildCount(); i++) {
View child = listView.getChildAt(i);
if (child instanceof FlickerLoadingView) {
progressView = child;
}
}
final View finalProgressView = progressView;
if (progressView != null) {
listView.removeView(progressView);
}
listView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
listView.getViewTreeObserver().removeOnPreDrawListener(this);
int n = listView.getChildCount();
AnimatorSet animatorSet = new AnimatorSet();
for (int i = 0; i < n; i++) {
View child = listView.getChildAt(i);
if (child == finalProgressView || listView.getChildAdapterPosition(child) < from) {
continue;
}
child.setAlpha(0);
int s = Math.min(listView.getMeasuredHeight(), Math.max(0, child.getTop()));
int delay = (int) ((s / (float) listView.getMeasuredHeight()) * 100);
ObjectAnimator a = ObjectAnimator.ofFloat(child, View.ALPHA, 0, 1f);
a.setStartDelay(delay);
a.setDuration(200);
animatorSet.playTogether(a);
}
if (finalProgressView != null && finalProgressView.getParent() == null) {
listView.addView(finalProgressView);
RecyclerView.LayoutManager layoutManager = listView.getLayoutManager();
if (layoutManager != null) {
layoutManager.ignoreView(finalProgressView);
Animator animator = ObjectAnimator.ofFloat(finalProgressView, View.ALPHA, finalProgressView.getAlpha(), 0);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
finalProgressView.setAlpha(1f);
layoutManager.stopIgnoringView(finalProgressView);
listView.removeView(finalProgressView);
}
});
animator.start();
}
}
animatorSet.start();
return true;
}
});
}
}

View File

@ -39,6 +39,7 @@ import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.DotDividerSpan;
import org.telegram.ui.Components.MediaActionDrawable;
import org.telegram.ui.Components.RadialProgress2;
import org.telegram.ui.FilteredSearchView;
@ -85,25 +86,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown
if (viewType == VIEW_TYPE_GLOBAL_SEARCH) {
dotSpan = new SpannableStringBuilder(".");
dotSpan.setSpan(new ReplacementSpan() {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
int color;
@Override
public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) {
return AndroidUtilities.dp(3);
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
if (color != paint.getColor()) {
p.setColor(paint.getColor());
}
float radius = AndroidUtilities.dpf2(3) / 2f;
canvas.drawCircle(x + radius, (bottom - top) / 2, radius, p);
}
}, 0, 1, 0);
dotSpan.setSpan(new DotDividerSpan(), 0, 1, 0);
}
}

View File

@ -182,6 +182,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
default void didPressOther(ChatMessageCell cell, float otherX, float otherY) {
}
default void didPressTime(ChatMessageCell cell) {
}
default void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) {
}
@ -458,6 +461,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
private String currentPhotoFilter;
private String currentPhotoFilterThumb;
private boolean timePressed;
private float timeAlpha = 1.0f;
private float controlsAlpha = 1.0f;
private long lastControlsAlphaChangeTime;
@ -673,6 +678,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
private int forwardNameY;
private float[] forwardNameOffsetX = new float[2];
private float drawTimeX;
private float drawTimeY;
private StaticLayout timeLayout;
private int timeWidth;
private int timeTextWidth;
@ -739,6 +746,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
private ValueAnimator statusDrawableAnimator;
private int overideShouldDrawTimeOnMedia;
private float toSeekBarProgress;
private Runnable invalidateRunnable = new Runnable() {
@Override
@ -1638,6 +1646,34 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
return result;
}
private boolean checkDateMotionEvent(MotionEvent event) {
if (!currentMessageObject.isImportedForward()) {
return false;
}
int x = (int) event.getX();
int y = (int) event.getY();
boolean result = false;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (x >= drawTimeX && x <= drawTimeX + timeWidth && y >= drawTimeY && y <= drawTimeY + AndroidUtilities.dp(20)) {
timePressed = true;
result = true;
invalidate();
}
} else {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (timePressed) {
timePressed = false;
playSoundEffect(SoundEffectConstants.CLICK);
delegate.didPressTime(this);
invalidate();
result = true;
}
}
}
return result;
}
private boolean checkPhotoImageMotionEvent(MotionEvent event) {
if (!drawPhotoImage && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT || currentMessageObject.isSending() && buttonState != 1) {
return false;
@ -1884,6 +1920,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
boolean result = checkTextBlockMotionEvent(event);
if (!result) {
result = checkDateMotionEvent(event);
}
if (!result) {
result = checkTextSelection(event);
}
@ -1929,6 +1968,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
otherPressed = false;
sideButtonPressed = false;
imagePressed = false;
timePressed = false;
gamePreviewPressed = false;
instantPressed = instantButtonPressed = commentButtonPressed = false;
if (Build.VERSION.SDK_INT >= 21) {
@ -2666,6 +2706,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
return (int) (forwardNameX + forwardNameCenterX);
}
public int getChecksX() {
return layoutWidth - AndroidUtilities.dp(SharedConfig.bubbleRadius >= 10 ? 27.3f : 25.3f);
}
public int getChecksY() {
if (currentMessageObject.shouldDrawWithoutBackground()) {
return (int) (drawTimeY - Theme.chat_msgStickerCheckDrawable.getIntrinsicHeight());
} else {
return (int) (drawTimeY - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight());
}
}
public TLRPC.User getCurrentUser() {
return currentUser;
}
@ -2798,6 +2850,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (getDelegate().getTextSelectionHelper() != null) {
getDelegate().getTextSelectionHelper().onChatMessageCellAttached(this);
}
if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) {
boolean showSeekbar = MediaController.getInstance().isPlayingMessage(currentMessageObject);
toSeekBarProgress = showSeekbar ? 1f : 0f;
}
}
private void setMessageContent(MessageObject messageObject, MessageObject.GroupedMessages groupedMessages, boolean bottomNear, boolean topNear) {
@ -3151,7 +3208,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else {
maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(80);
}
drawName = isPinnedChat || messageObject.messageOwner.peer_id.channel_id != 0 && (!messageObject.isOutOwner() || messageObject.isSupergroup());
drawName = isPinnedChat || messageObject.messageOwner.peer_id.channel_id != 0 && (!messageObject.isOutOwner() || messageObject.isSupergroup()) || messageObject.isImportedForward() && messageObject.messageOwner.fwd_from.from_id == null;
}
availableTimeWidth = maxWidth;
@ -4098,7 +4155,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
namesOffset -= AndroidUtilities.dp(1);
}
} else if (messageObject.type == 12) {
drawName = messageObject.isFromGroup() && messageObject.isSupergroup();
drawName = messageObject.isFromGroup() && messageObject.isSupergroup() || messageObject.isImportedForward() && messageObject.messageOwner.fwd_from.from_id == null;
drawForwardedName = !isRepliesChat;
drawPhotoImage = true;
photoImage.setRoundRadius(AndroidUtilities.dp(22));
@ -4181,7 +4238,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
} else if (messageObject.type == 2) {
drawForwardedName = !isRepliesChat;
drawName = messageObject.isFromGroup() && messageObject.isSupergroup();
drawName = messageObject.isFromGroup() && messageObject.isSupergroup() || messageObject.isImportedForward() && messageObject.messageOwner.fwd_from.from_id == null;
if (AndroidUtilities.isTablet()) {
backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(drawAvatar ? 102 : 50), AndroidUtilities.dp(270));
} else {
@ -4196,7 +4253,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
namesOffset -= AndroidUtilities.dp(1);
}
} else if (messageObject.type == 14) {
drawName = messageObject.isFromGroup() && messageObject.isSupergroup() && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0);
drawName = (messageObject.isFromGroup() && messageObject.isSupergroup() || messageObject.isImportedForward() && messageObject.messageOwner.fwd_from.from_id == null) && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0);
if (AndroidUtilities.isTablet()) {
backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(drawAvatar ? 102 : 50), AndroidUtilities.dp(270));
} else {
@ -4492,7 +4549,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else {
drawForwardedName = messageObject.messageOwner.fwd_from != null && !messageObject.isAnyKindOfSticker();
if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO) {
drawName = messageObject.isFromGroup() && messageObject.isSupergroup() && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0);
drawName = (messageObject.isFromGroup() && messageObject.isSupergroup() || messageObject.isImportedForward() && messageObject.messageOwner.fwd_from.from_id == null) && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0);
}
mediaBackground = isMedia = messageObject.type != 9;
drawImageButton = true;
@ -5747,6 +5804,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
transitionParams.lastStatusDrawableParams = -1;
statusDrawableAnimationInProgress = false;
if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) {
boolean showSeekbar = MediaController.getInstance().isPlayingMessage(currentMessageObject);
toSeekBarProgress = showSeekbar ? 1f : 0f;
}
}
updateWaveform();
updateButtonState(false, dataChanged && !messageObject.cancelEditing, true);
@ -5813,6 +5875,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
linkPreviewPressed = false;
sideButtonPressed = false;
imagePressed = false;
timePressed = false;
gamePreviewPressed = false;
if (pressedVoteButton != -1 || pollHintPressed || psaHintPressed || instantPressed || otherPressed || commentButtonPressed) {
@ -6006,6 +6069,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
currentMessageObject.audioProgress = progress;
MediaController.getInstance().seekToProgress(currentMessageObject, progress);
updatePlayingMessageProgress();
}
@Override
public void onSeekBarContinuousDrag(float progress) {
if (currentMessageObject == null) {
return;
}
currentMessageObject.audioProgress = progress;
currentMessageObject.audioProgressSec = (int) (currentMessageObject.getDuration() * progress);
updatePlayingMessageProgress();
}
public boolean isAnimatingPollAnswer() {
@ -7348,16 +7422,47 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
canvas.translate(timeAudioX + songX, AndroidUtilities.dp(13) + namesOffset + mediaOffsetY);
songLayout.draw(canvas);
canvas.restore();
canvas.save();
if (MediaController.getInstance().isPlayingMessage(currentMessageObject)) {
boolean showSeekbar = MediaController.getInstance().isPlayingMessage(currentMessageObject);
if (showSeekbar && toSeekBarProgress != 1f) {
toSeekBarProgress += 16f / 100f;
if (toSeekBarProgress > 1f) {
toSeekBarProgress = 1f;
}
invalidate();
} else if (!showSeekbar && toSeekBarProgress != 0){
toSeekBarProgress -= 16f / 100f;
if (toSeekBarProgress < 0) {
toSeekBarProgress = 0;
}
invalidate();
}
if (toSeekBarProgress > 0) {
if (toSeekBarProgress != 1f) {
canvas.saveLayerAlpha(seekBarX, seekBarY, seekBarX + seekBar.getWidth() + AndroidUtilities.dp(24), seekBarY + AndroidUtilities.dp(24), (int) (255 * (toSeekBarProgress)), Canvas.ALL_SAVE_FLAG);
} else {
canvas.save();
}
canvas.translate(seekBarX, seekBarY);
seekBar.draw(canvas);
} else {
canvas.translate(timeAudioX + performerX, AndroidUtilities.dp(35) + namesOffset + mediaOffsetY);
performerLayout.draw(canvas);
canvas.restore();
}
if (toSeekBarProgress < 1f) {
float x = timeAudioX + performerX;
float y = AndroidUtilities.dp(35) + namesOffset + mediaOffsetY;
if (toSeekBarProgress != 0) {
canvas.saveLayerAlpha(x, y, x + performerLayout.getWidth(), y + performerLayout.getHeight(), (int) (255 * (1f - toSeekBarProgress)), Canvas.ALL_SAVE_FLAG);
} else {
canvas.save();
}
if (toSeekBarProgress != 0) {
float s = 0.7f + 0.3f * (1f - toSeekBarProgress);
canvas.scale(s, s, x, y + performerLayout.getHeight() / 2f);
}
canvas.translate(x, y);
performerLayout.draw(canvas);
canvas.restore();
}
canvas.restore();
canvas.save();
canvas.translate(timeAudioX, AndroidUtilities.dp(57) + namesOffset + mediaOffsetY);
@ -7971,7 +8076,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
hasMiniProgress = fileExists ? 1 : 2;
fileExists = true;
}
if (currentMessageObject.isSendError() || TextUtils.isEmpty(fileName) && !currentMessageObject.isSending() && !currentMessageObject.isEditing()) {
if (currentMessageObject.isSendError() || TextUtils.isEmpty(fileName) && (currentMessageObject.isAnyKindOfSticker() || !currentMessageObject.isSending() && !currentMessageObject.isEditing())) {
radialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false);
radialProgress.setMiniIcon(MediaActionDrawable.ICON_NONE, ifSame, false);
videoRadialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false);
@ -8817,6 +8922,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
} else if (messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.post_author != null) {
signString = messageObject.messageOwner.fwd_from.post_author.replace("\n", "");
} else if (messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.imported) {
signString = LocaleController.formatImportedDate(messageObject.messageOwner.fwd_from.date) + " " + LocaleController.getString("ImportedMessage", R.string.ImportedMessage);
} else if (!messageObject.isOutOwner() && fromId > 0 && messageObject.messageOwner.post) {
TLRPC.User signUser = MessagesController.getInstance(currentAccount).getUser(fromId);
if (signUser != null) {
@ -8856,7 +8963,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
timeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
}
if (signString != null) {
currentTimeString = ", " + timeString;
if (messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.imported) {
currentTimeString = " " + timeString;
} else {
currentTimeString = ", " + timeString;
}
} else {
currentTimeString = timeString;
}
@ -8964,9 +9075,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
currentChat = messagesController.getChat(fwd_from.saved_from_peer.chat_id);
}
}
} else if (fwd_from != null && fwd_from.from_id instanceof TLRPC.TL_peerUser && currentMessageObject.getDialogId() == currentUserId) {
} else if (fwd_from != null && fwd_from.from_id instanceof TLRPC.TL_peerUser && (fwd_from.imported || currentMessageObject.getDialogId() == currentUserId)) {
currentUser = messagesController.getUser(fwd_from.from_id.user_id);
} else if (fwd_from != null && !TextUtils.isEmpty(fwd_from.from_name) && currentMessageObject.getDialogId() == currentUserId) {
} else if (fwd_from != null && !TextUtils.isEmpty(fwd_from.from_name) && (fwd_from.imported || currentMessageObject.getDialogId() == currentUserId)) {
currentUser = new TLRPC.TL_user();
currentUser.first_name = fwd_from.from_name;
} else {
@ -9026,13 +9137,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
CharSequence viaString = null;
if (messageObject.messageOwner.via_bot_id != 0) {
TLRPC.User botUser = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.via_bot_id);
if (botUser != null && botUser.username != null && botUser.username.length() > 0) {
if (botUser != null && !TextUtils.isEmpty(botUser.username)) {
viaUsername = "@" + botUser.username;
viaString = AndroidUtilities.replaceTags(String.format(" %s <b>%s</b>", LocaleController.getString("ViaBot", R.string.ViaBot), viaUsername));
viaWidth = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(viaString, 0, viaString.length()));
currentViaBotUser = botUser;
}
} else if (messageObject.messageOwner.via_bot_name != null && messageObject.messageOwner.via_bot_name.length() > 0) {
} else if (!TextUtils.isEmpty(messageObject.messageOwner.via_bot_name)) {
viaUsername = "@" + messageObject.messageOwner.via_bot_name;
viaString = AndroidUtilities.replaceTags(String.format(" %s <b>%s</b>", LocaleController.getString("ViaBot", R.string.ViaBot), viaUsername));
viaWidth = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(viaString, 0, viaString.length()));
@ -9074,7 +9185,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else {
currentNameString = "";
}
CharSequence nameStringFinal = TextUtils.ellipsize(currentNameString.replace('\n', ' '), Theme.chat_namePaint, nameWidth - (viaBot ? viaWidth : 0), TextUtils.TruncateAt.END);
CharSequence nameStringFinal = TextUtils.ellipsize(currentNameString.replace('\n', ' ').replace('\u200F', ' '), Theme.chat_namePaint, nameWidth - (viaBot ? viaWidth : 0), TextUtils.TruncateAt.END);
if (viaBot) {
viaNameWidth = (int) Math.ceil(Theme.chat_namePaint.measureText(nameStringFinal, 0, nameStringFinal.length()));
if (viaNameWidth != 0) {
@ -9414,7 +9525,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
private boolean isNeedAuthorName() {
return isPinnedChat && currentMessageObject.type == 0 || (!pinnedTop || ChatObject.isChannel(currentChat) && !currentChat.megagroup) && drawName && isChat && (!currentMessageObject.isOutOwner() || currentMessageObject.isSupergroup() && currentMessageObject.isFromGroup());
return isPinnedChat && currentMessageObject.type == 0 || (!pinnedTop || ChatObject.isChannel(currentChat) && !currentChat.megagroup) && drawName && isChat && (!currentMessageObject.isOutOwner() || currentMessageObject.isSupergroup() && currentMessageObject.isFromGroup()) || currentMessageObject.isImportedForward() && currentMessageObject.messageOwner.fwd_from.from_id == null;
}
private String getAuthorName() {
@ -10871,7 +10982,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (overideShouldDrawTimeOnMedia != 0) {
return overideShouldDrawTimeOnMedia == 1;
}
return mediaBackground && captionLayout == null || isMedia && drawCommentButton && !isRepliesChat;
return mediaBackground && captionLayout == null/* || isMedia && drawCommentButton && !isRepliesChat*/;
}
public void drawTime(Canvas canvas, float alpha, boolean fromParent) {
@ -11027,7 +11138,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
canvas.save();
canvas.translate(timeTitleTimeX + additionalX, timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight());
canvas.translate(drawTimeX = timeTitleTimeX + additionalX, drawTimeY = timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight());
timeLayout.draw(canvas);
canvas.restore();
Theme.chat_timePaint.setAlpha(255);
@ -11086,7 +11197,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
Theme.chat_timePaint.setAlpha(oldAlpha);
}
} else {
canvas.translate(timeTitleTimeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset);
canvas.translate(drawTimeX = timeTitleTimeX + additionalX, drawTimeY = layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset);
timeLayout.draw(canvas);
}
canvas.restore();
@ -12729,6 +12840,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
super.setTranslationX(translationX);
}
public SeekBar getSeekBar() {
return seekBar;
}
private class MessageAccessibilityNodeProvider extends AccessibilityNodeProvider {
private final int LINK_IDS_START = 2000;
@ -12738,6 +12853,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
private final int SHARE = 498;
private final int REPLY = 497;
private final int COMMENT = 496;
private final int POLL_HINT = 495;
private Path linkPath = new Path();
private RectF rectF = new RectF();
private Rect rect = new Rect();
@ -12900,6 +13016,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
info.addChild(ChatMessageCell.this, BOT_BUTTONS_START + i);
i++;
}
if (hintButtonVisible && pollHintX != -1 && currentMessageObject.isPoll()) {
info.addChild(ChatMessageCell.this, POLL_HINT);
}
i = 0;
for (PollButton button : pollButtons) {
info.addChild(ChatMessageCell.this, POLL_BUTTONS_START + i);
@ -12991,17 +13110,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
return null;
}
PollButton button = pollButtons.get(buttonIndex);
info.setText(button.title.getText());
StringBuilder sb = new StringBuilder(button.title.getText());
if (!pollVoted) {
info.setClassName("android.widget.Button");
} else {
info.setText(info.getText() + ", " + button.percent + "%");
info.setSelected(button.chosen);
sb.append(", ").append(button.percent).append("%");
if (lastPoll != null && lastPoll.quiz && button.correct) {
sb.append(", ").append(LocaleController.getString("AccDescrQuizCorrectAnswer", R.string.AccDescrQuizCorrectAnswer));
}
}
info.setText(sb);
info.setEnabled(true);
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
int width = backgroundWidth - AndroidUtilities.dp(76);
rect.set(button.x, button.y, button.x + width, button.y + button.height);
final int y = button.y + namesOffset;
final int w = backgroundWidth - AndroidUtilities.dp(76);
rect.set(button.x, y, button.x + w, y + button.height);
info.setBoundsInParent(rect);
if (accessibilityVirtualViewBounds.get(virtualViewId) == null) {
accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect));
@ -13009,6 +13134,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
rect.offset(pos[0], pos[1]);
info.setBoundsInScreen(rect);
info.setClickable(true);
} else if (virtualViewId == POLL_HINT) {
info.setClassName("android.widget.Button");
info.setEnabled(true);
info.setText(LocaleController.getString("AccDescrQuizExplanation", R.string.AccDescrQuizExplanation));
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
rect.set(pollHintX - AndroidUtilities.dp(8), pollHintY - AndroidUtilities.dp(8), pollHintX + AndroidUtilities.dp(32), pollHintY + AndroidUtilities.dp(32));
info.setBoundsInParent(rect);
if (accessibilityVirtualViewBounds.get(virtualViewId) == null || !accessibilityVirtualViewBounds.get(virtualViewId).equals(rect)) {
accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect));
}
rect.offset(pos[0], pos[1]);
info.setBoundsInScreen(rect);
info.setClickable(true);
} else if (virtualViewId == INSTANT_VIEW) {
info.setClassName("android.widget.Button");
@ -13128,6 +13266,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
delegate.didPressVoteButtons(ChatMessageCell.this, answers, -1, 0, 0);
}
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
} else if (virtualViewId == POLL_HINT) {
if (delegate != null) {
delegate.didPressHint(ChatMessageCell.this, 0);
}
} else if (virtualViewId == INSTANT_VIEW) {
if (delegate != null) {
delegate.didPressInstantButton(ChatMessageCell.this, drawInstantViewType);

View File

@ -253,7 +253,7 @@ public class DialogCell extends BaseCell {
private boolean drawVerified;
private boolean drawScam;
private int drawScam;
private boolean isSelected;
@ -269,6 +269,8 @@ public class DialogCell extends BaseCell {
long lastDialogChangedTime;
private int statusDrawableLeft;
private DialogsActivity parentFragment;
public static class BounceInterpolator implements Interpolator {
public float getInterpolation(float t) {
@ -286,13 +288,13 @@ public class DialogCell extends BaseCell {
}
}
public DialogCell(Context context, boolean needCheck, boolean forceThreeLines) {
this(context, needCheck, forceThreeLines, UserConfig.selectedAccount);
public DialogCell(DialogsActivity fragment, Context context, boolean needCheck, boolean forceThreeLines) {
this(fragment, context, needCheck, forceThreeLines, UserConfig.selectedAccount);
}
public DialogCell(Context context, boolean needCheck, boolean forceThreeLines, int account) {
public DialogCell(DialogsActivity fragment, Context context, boolean needCheck, boolean forceThreeLines, int account) {
super(context);
parentFragment = fragment;
Theme.createDialogsResources(context);
avatarImage.setRoundRadius(AndroidUtilities.dp(28));
thumbImage.setRoundRadius(AndroidUtilities.dp(2));
@ -564,7 +566,7 @@ public class DialogCell extends BaseCell {
drawNameLock = false;
drawNameBot = false;
drawVerified = false;
drawScam = false;
drawScam = 0;
drawPinBackground = false;
hasMessageThumb = false;
int offsetName = 0;
@ -744,8 +746,11 @@ public class DialogCell extends BaseCell {
if (currentDialogFolderId == 0) {
if (chat != null) {
if (chat.scam) {
drawScam = true;
drawScam = 1;
Theme.dialogs_scamDrawable.checkText();
} else if (chat.fake) {
drawScam = 2;
Theme.dialogs_fakeDrawable.checkText();
} else {
drawVerified = chat.verified;
}
@ -786,8 +791,11 @@ public class DialogCell extends BaseCell {
}
} else if (user != null) {
if (user.scam) {
drawScam = true;
drawScam = 1;
Theme.dialogs_scamDrawable.checkText();
} else if (user.fake) {
drawScam = 2;
Theme.dialogs_fakeDrawable.checkText();
} else {
drawVerified = user.verified;
}
@ -957,6 +965,8 @@ public class DialogCell extends BaseCell {
if (chat != null && chat.id > 0 && fromChat == null && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat))) {
if (message.isOutOwner()) {
messageNameString = LocaleController.getString("FromYou", R.string.FromYou);
} else if (message != null && message.messageOwner.fwd_from != null && message.messageOwner.fwd_from.from_name != null) {
messageNameString = message.messageOwner.fwd_from.from_name;
} else if (fromUser != null) {
if (useForceThreeLines || SharedConfig.useThreeLinesLayout) {
if (UserObject.isDeleted(fromUser)) {
@ -1368,7 +1378,7 @@ public class DialogCell extends BaseCell {
}
}
if (dialogMuted && !drawVerified && !drawScam) {
if (dialogMuted && !drawVerified && drawScam == 0) {
int w = AndroidUtilities.dp(6) + Theme.dialogs_muteDrawable.getIntrinsicWidth();
nameWidth -= w;
if (LocaleController.isRTL) {
@ -1380,8 +1390,8 @@ public class DialogCell extends BaseCell {
if (LocaleController.isRTL) {
nameLeft += w;
}
} else if (drawScam) {
int w = AndroidUtilities.dp(6) + Theme.dialogs_scamDrawable.getIntrinsicWidth();
} else if (drawScam != 0) {
int w = AndroidUtilities.dp(6) + (drawScam == 0 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth();
nameWidth -= w;
if (LocaleController.isRTL) {
nameLeft += w;
@ -1595,12 +1605,12 @@ public class DialogCell extends BaseCell {
if (nameLayout != null && nameLayout.getLineCount() > 0) {
left = nameLayout.getLineLeft(0);
widthpx = Math.ceil(nameLayout.getLineWidth(0));
if (dialogMuted && !drawVerified && !drawScam) {
if (dialogMuted && !drawVerified && drawScam == 0) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth());
} else if (drawVerified) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_verifiedDrawable.getIntrinsicWidth());
} else if (drawScam) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_scamDrawable.getIntrinsicWidth());
} else if (drawScam != 0) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - (drawScam == 0 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth());
}
if (left == 0) {
if (widthpx < nameWidth) {
@ -1645,7 +1655,7 @@ public class DialogCell extends BaseCell {
nameLeft -= (nameWidth - widthpx);
}
}
if (dialogMuted || drawVerified || drawScam) {
if (dialogMuted || drawVerified || drawScam != 0) {
nameMuteLeft = (int) (nameLeft + left + AndroidUtilities.dp(6));
}
}
@ -1775,7 +1785,10 @@ public class DialogCell extends BaseCell {
}
public void checkCurrentDialogIndex(boolean frozen) {
ArrayList<TLRPC.Dialog> dialogsArray = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, frozen);
if (parentFragment == null) {
return;
}
ArrayList<TLRPC.Dialog> dialogsArray = parentFragment.getDialogsArray(currentAccount, dialogsType, folderId, frozen);
if (index < dialogsArray.size()) {
TLRPC.Dialog dialog = dialogsArray.get(index);
TLRPC.Dialog nextDialog = index + 1 < dialogsArray.size() ? dialogsArray.get(index + 1) : null;
@ -1849,7 +1862,10 @@ public class DialogCell extends BaseCell {
}
private MessageObject findFolderTopMessage() {
ArrayList<TLRPC.Dialog> dialogs = DialogsActivity.getDialogsArray(currentAccount, dialogsType, currentDialogFolderId, false);
if (parentFragment == null) {
return null;
}
ArrayList<TLRPC.Dialog> dialogs = parentFragment.getDialogsArray(currentAccount, dialogsType, currentDialogFolderId, false);
MessageObject maxMessage = null;
if (!dialogs.isEmpty()) {
for (int a = 0, N = dialogs.size(); a < N; a++) {
@ -2165,7 +2181,7 @@ public class DialogCell extends BaseCell {
}
if (isSliding) {
boolean prevValue = drawRevealBackground;
drawRevealBackground = Math.abs(translationX) >= getMeasuredWidth() * 0.3f;
drawRevealBackground = Math.abs(translationX) >= getMeasuredWidth() * 0.45f;
if (prevValue != drawRevealBackground && archiveHidden == SharedConfig.archiveHidden) {
try {
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
@ -2483,7 +2499,7 @@ public class DialogCell extends BaseCell {
lastStatusDrawableParams = (this.drawClock ? 1 : 0) + (this.drawCheck1 ? 2 : 0) + (this.drawCheck2 ? 4 : 0);
}
if (dialogMuted && !drawVerified && !drawScam) {
if (dialogMuted && !drawVerified && drawScam == 0) {
setDrawableBounds(Theme.dialogs_muteDrawable, nameMuteLeft - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 0 : 1), AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 13.5f : 17.5f));
Theme.dialogs_muteDrawable.draw(canvas);
} else if (drawVerified) {
@ -2491,9 +2507,9 @@ public class DialogCell extends BaseCell {
setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, nameMuteLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 16.5f));
Theme.dialogs_verifiedDrawable.draw(canvas);
Theme.dialogs_verifiedCheckDrawable.draw(canvas);
} else if (drawScam) {
setDrawableBounds(Theme.dialogs_scamDrawable, nameMuteLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12 : 15));
Theme.dialogs_scamDrawable.draw(canvas);
} else if (drawScam != 0) {
setDrawableBounds((drawScam == 0 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable), nameMuteLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12 : 15));
(drawScam == 0 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).draw(canvas);
}
if (drawReorder || reorderIconProgress != 0) {
@ -2970,7 +2986,7 @@ public class DialogCell extends BaseCell {
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
if (currentDialogFolderId != 0 && archiveHidden) {
if (isFolderCell() && archivedChatsDrawable != null && archivedChatsDrawable.pullProgress == 0.0f) {
info.setVisibleToUser(false);
} else {
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
@ -3075,6 +3091,10 @@ public class DialogCell extends BaseCell {
archivedChatsDrawable = drawable;
}
public int getCurrentDialogFolderId() {
return currentDialogFolderId;
}
public MessageObject getMessage() {
return message;
}

View File

@ -67,6 +67,8 @@ public class FeaturedStickerSetInfoCell extends FrameLayout {
private CharSequence url;
private int urlSearchLength;
float unreadProgress;
public FeaturedStickerSetInfoCell(Context context, int left) {
this(context, left, false);
}
@ -184,6 +186,11 @@ public class FeaturedStickerSetInfoCell extends FrameLayout {
animatorSet.cancel();
animatorSet = null;
}
if (set != stickerSet) {
unreadProgress = unread ? 1f : 0;
invalidate();
}
set = stickerSet;
stickerSetNameSearchIndex = index;
stickerSetNameSearchLength = searchLength;
@ -299,9 +306,24 @@ public class FeaturedStickerSetInfoCell extends FrameLayout {
@Override
protected void onDraw(Canvas canvas) {
if (isUnread) {
if (isUnread || unreadProgress != 0f) {
if (isUnread && unreadProgress != 1f) {
unreadProgress += 16f / 100f;
if (unreadProgress > 1f) {
unreadProgress = 1f;
} else {
invalidate();
}
} else if (!isUnread && unreadProgress != 0) {
unreadProgress -= 16f / 100f;
if (unreadProgress < 0) {
unreadProgress = 0;
} else {
invalidate();
}
}
paint.setColor(Theme.getColor(Theme.key_featuredStickers_unread));
canvas.drawCircle(nameTextView.getRight() + AndroidUtilities.dp(12), AndroidUtilities.dp(20), AndroidUtilities.dp(4), paint);
canvas.drawCircle(nameTextView.getRight() + AndroidUtilities.dp(12), AndroidUtilities.dp(20), AndroidUtilities.dp(4) * unreadProgress, paint);
}
if (needDivider) {
canvas.drawLine(0, 0, getWidth(), 0, Theme.dividerPaint);

View File

@ -10,11 +10,11 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.os.SystemClock;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@ -50,7 +50,7 @@ public class GroupCallUserCell extends FrameLayout {
private BackupImageView avatarImageView;
private SimpleTextView nameTextView;
private SimpleTextView[] statusTextView = new SimpleTextView[2];
private SimpleTextView[] statusTextView = new SimpleTextView[3];
private RLottieImageView muteButton;
private RLottieDrawable muteDrawable;
@ -69,6 +69,7 @@ public class GroupCallUserCell extends FrameLayout {
private boolean needDivider;
private boolean currentIconGray;
private int currentStatus;
private String grayIconColor = Theme.key_voipgroup_mutedIcon;
@ -81,6 +82,8 @@ public class GroupCallUserCell extends FrameLayout {
private boolean updateRunnableScheduled;
private boolean isSpeaking;
private Drawable speakingDrawable;
private AnimatorSet animatorSet;
public GroupCallUserCell(Context context) {
@ -102,32 +105,30 @@ public class GroupCallUserCell extends FrameLayout {
nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 54 : 67, 10, LocaleController.isRTL ? 67 : 54, 0));
for (int a = 0; a < 2; a++) {
speakingDrawable = context.getResources().getDrawable(R.drawable.voice_volume_mini);
speakingDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_voipgroup_speakingText), PorterDuff.Mode.MULTIPLY));
for (int a = 0; a < 3; a++) {
statusTextView[a] = new SimpleTextView(context);
statusTextView[a].setTextSize(15);
statusTextView[a].setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
if (a == 0) {
statusTextView[a].setTextColor(Theme.getColor(Theme.key_voipgroup_listeningText));
statusTextView[a].setText(LocaleController.getString("Listening", R.string.Listening));
} else {
} else if (a == 1) {
statusTextView[a].setTextColor(Theme.getColor(Theme.key_voipgroup_speakingText));
statusTextView[a].setText(LocaleController.getString("Speaking", R.string.Speaking));
statusTextView[a].setDrawablePadding(AndroidUtilities.dp(2));
} else {
statusTextView[a].setTextColor(Theme.getColor(Theme.key_voipgroup_mutedByAdminIcon));
statusTextView[a].setText(LocaleController.getString("VoipGroupMutedForMe", R.string.VoipGroupMutedForMe));
}
addView(statusTextView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 54 : 67, 32, LocaleController.isRTL ? 67 : 54, 0));
}
muteDrawable = new RLottieDrawable(R.raw.voice_outlined, "" + R.raw.voice_outlined, AndroidUtilities.dp(19), AndroidUtilities.dp(24), true, null);
muteButton = new RLottieImageView(context) {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
TLRPC.Chat chat = accountInstance.getMessagesController().getChat(currentCall.chatId);
if (!ChatObject.canManageCalls(chat)) {
return false;
}
return super.dispatchTouchEvent(event);
}
};
muteButton = new RLottieImageView(context);
muteButton.setScaleType(ImageView.ScaleType.CENTER);
muteButton.setAnimation(muteDrawable);
if (Build.VERSION.SDK_INT >= 21) {
@ -251,28 +252,7 @@ public class GroupCallUserCell extends FrameLayout {
private void applyParticipantChanges(boolean animated, boolean internal) {
TLRPC.Chat chat = accountInstance.getMessagesController().getChat(currentCall.chatId);
boolean canMute = ChatObject.canManageCalls(chat) && !isSelfUser();
if (canMute) {
boolean isAdmin = false;
if (chat.megagroup) {
isAdmin = accountInstance.getMessagesController().getAdminRank(currentCall.chatId, participant.user_id) != null;
} else {
TLRPC.ChatFull chatFull = accountInstance.getMessagesController().getChatFull(currentCall.chatId);
if (chatFull != null) {
for (int a = 0, N = chatFull.participants.participants.size(); a < N; a++) {
TLRPC.ChatParticipant chatParticipant = chatFull.participants.participants.get(a);
if (chatParticipant.user_id == participant.user_id) {
isAdmin = chatParticipant instanceof TLRPC.TL_chatParticipantAdmin || chatParticipant instanceof TLRPC.TL_chatParticipantCreator;
break;
}
}
}
}
if (isAdmin && participant.muted) {
canMute = false;
}
}
muteButton.setEnabled(canMute);
muteButton.setEnabled(!isSelfUser());
if (!internal) {
long diff = SystemClock.uptimeMillis() - participant.lastSpeakTime;
@ -299,44 +279,44 @@ public class GroupCallUserCell extends FrameLayout {
ArrayList<Animator> animators = null;
boolean newMuted;
boolean myted_by_me = participant.muted_by_you && !isSelfUser();
if (isSelfUser()) {
newMuted = VoIPService.getSharedInstance() != null && VoIPService.getSharedInstance().isMicMute() && (!isSpeaking || !participant.hasVoice);
} else {
newMuted = participant.muted && (!isSpeaking || !participant.hasVoice);
newMuted = participant.muted && (!isSpeaking || !participant.hasVoice) || myted_by_me;
}
boolean newMutedByAdmin = newMuted && !participant.can_self_unmute;
int newMuteColor;
Object newTag;
Object oldTag = statusTextView[0].getTag();
int newStatus;
currentIconGray = false;
if (participant.muted && !isSpeaking) {
if (!participant.can_self_unmute) {
if (participant.muted && !isSpeaking || myted_by_me) {
if (!participant.can_self_unmute || myted_by_me) {
newMuteColor = Theme.getColor(Theme.key_voipgroup_mutedByAdminIcon);
} else {
newMuteColor = Theme.getColor(grayIconColor);
currentIconGray = true;
}
newTag = null;
newStatus = myted_by_me ? 2 : 0;
} else {
if (isSpeaking && participant.hasVoice) {
newMuteColor = Theme.getColor(Theme.key_voipgroup_speakingText);
newTag = 1;
newStatus = 1;
} else {
newMuteColor = Theme.getColor(grayIconColor);
newTag = null;
newStatus = 0;
currentIconGray = true;
}
}
boolean somethingChanged = false;
if (animatorSet != null) {
if (newTag == null && oldTag != null || newTag != null && oldTag == null ||
lastMuteColor != newMuteColor) {
if (newStatus != currentStatus || lastMuteColor != newMuteColor) {
somethingChanged = true;
}
}
if (!animated || somethingChanged) {
if (animatorSet != null) {
animatorSet.cancel();
animatorSet = null;
}
}
if (!animated || lastMuteColor != newMuteColor || somethingChanged) {
@ -359,64 +339,63 @@ public class GroupCallUserCell extends FrameLayout {
Theme.setSelectorDrawableColor(muteButton.getDrawable(), newMuteColor & 0x24ffffff, true);
}
}
if (!animated || newTag == null && oldTag != null || newTag != null && oldTag == null || somethingChanged) {
if (newStatus == 1) {
int vol = ChatObject.getParticipantVolume(participant);
int volume = vol / 100;
if (volume != 100) {
statusTextView[1].setLeftDrawable(speakingDrawable);
statusTextView[1].setText((vol < 100 ? 1 : volume) + "% " + LocaleController.getString("Speaking", R.string.Speaking));
} else {
statusTextView[1].setLeftDrawable(null);
statusTextView[1].setText(LocaleController.getString("Speaking", R.string.Speaking));
}
}
if (!animated || newStatus != currentStatus || somethingChanged) {
if (animated) {
if (animators == null) {
animators = new ArrayList<>();
}
statusTextView[0].setVisibility(VISIBLE);
statusTextView[1].setVisibility(VISIBLE);
if (newTag == null) {
statusTextView[2].setVisibility(VISIBLE);
if (newStatus == 0) {
animators.add(ObjectAnimator.ofFloat(statusTextView[0], View.TRANSLATION_Y, 0));
animators.add(ObjectAnimator.ofFloat(statusTextView[0], View.ALPHA, 1.0f));
animators.add(ObjectAnimator.ofFloat(statusTextView[1], View.TRANSLATION_Y, -AndroidUtilities.dp(2)));
animators.add(ObjectAnimator.ofFloat(statusTextView[1], View.ALPHA, 0.0f));
} else {
animators.add(ObjectAnimator.ofFloat(statusTextView[2], View.TRANSLATION_Y, -AndroidUtilities.dp(2)));
animators.add(ObjectAnimator.ofFloat(statusTextView[2], View.ALPHA, 0.0f));
} else if (newStatus == 1) {
animators.add(ObjectAnimator.ofFloat(statusTextView[0], View.TRANSLATION_Y, AndroidUtilities.dp(2)));
animators.add(ObjectAnimator.ofFloat(statusTextView[0], View.ALPHA, 0.0f));
animators.add(ObjectAnimator.ofFloat(statusTextView[1], View.TRANSLATION_Y, 0));
animators.add(ObjectAnimator.ofFloat(statusTextView[1], View.ALPHA, 1.0f));
animators.add(ObjectAnimator.ofFloat(statusTextView[2], View.TRANSLATION_Y, -AndroidUtilities.dp(2)));
animators.add(ObjectAnimator.ofFloat(statusTextView[2], View.ALPHA, 0.0f));
} else {
animators.add(ObjectAnimator.ofFloat(statusTextView[0], View.TRANSLATION_Y, AndroidUtilities.dp(2)));
animators.add(ObjectAnimator.ofFloat(statusTextView[0], View.ALPHA, 0.0f));
animators.add(ObjectAnimator.ofFloat(statusTextView[1], View.TRANSLATION_Y, -AndroidUtilities.dp(2)));
animators.add(ObjectAnimator.ofFloat(statusTextView[1], View.ALPHA, 0.0f));
animators.add(ObjectAnimator.ofFloat(statusTextView[2], View.TRANSLATION_Y, 0));
animators.add(ObjectAnimator.ofFloat(statusTextView[2], View.ALPHA, 1.0f));
}
} else {
if (newTag == null) {
statusTextView[0].setVisibility(VISIBLE);
statusTextView[1].setVisibility(INVISIBLE);
statusTextView[0].setTranslationY(0);
statusTextView[0].setAlpha(1.0f);
statusTextView[1].setTranslationY(-AndroidUtilities.dp(2));
statusTextView[1].setAlpha(0.0f);
} else {
statusTextView[0].setVisibility(INVISIBLE);
statusTextView[1].setVisibility(VISIBLE);
statusTextView[0].setTranslationY(AndroidUtilities.dp(2));
statusTextView[0].setAlpha(0.0f);
statusTextView[1].setTranslationY(0);
statusTextView[1].setAlpha(1.0f);
}
applyStatus(newStatus);
}
statusTextView[0].setTag(newTag);
currentStatus = newStatus;
}
avatarWavesDrawable.setMuted(newTag == null, animated);
avatarWavesDrawable.setMuted(newStatus, animated);
if (animators != null) {
if (animatorSet != null) {
animatorSet.cancel();
animatorSet = null;
}
animatorSet = new AnimatorSet();
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (newTag == null) {
statusTextView[0].setVisibility(VISIBLE);
statusTextView[1].setVisibility(INVISIBLE);
statusTextView[0].setTranslationY(0);
statusTextView[0].setAlpha(1.0f);
statusTextView[1].setTranslationY(-AndroidUtilities.dp(2));
statusTextView[1].setAlpha(0.0f);
} else {
statusTextView[0].setVisibility(INVISIBLE);
statusTextView[1].setVisibility(VISIBLE);
statusTextView[0].setTranslationY(AndroidUtilities.dp(2));
statusTextView[0].setAlpha(0.0f);
statusTextView[1].setTranslationY(0);
statusTextView[1].setAlpha(1.0f);
}
applyStatus(newStatus);
animatorSet = null;
}
});
@ -448,6 +427,40 @@ public class GroupCallUserCell extends FrameLayout {
avatarWavesDrawable.setShowWaves(isSpeaking, this);
}
private void applyStatus(int newStatus) {
if (newStatus == 0) {
statusTextView[0].setVisibility(VISIBLE);
statusTextView[0].setTranslationY(0);
statusTextView[0].setAlpha(1.0f);
statusTextView[1].setVisibility(INVISIBLE);
statusTextView[1].setTranslationY(-AndroidUtilities.dp(2));
statusTextView[1].setAlpha(0.0f);
statusTextView[2].setVisibility(INVISIBLE);
statusTextView[2].setTranslationY(-AndroidUtilities.dp(2));
statusTextView[2].setAlpha(0.0f);
} else if (newStatus == 1) {
statusTextView[0].setVisibility(INVISIBLE);
statusTextView[0].setTranslationY(AndroidUtilities.dp(2));
statusTextView[0].setAlpha(0.0f);
statusTextView[1].setVisibility(VISIBLE);
statusTextView[1].setTranslationY(0);
statusTextView[1].setAlpha(1.0f);
statusTextView[2].setVisibility(INVISIBLE);
statusTextView[2].setTranslationY(-AndroidUtilities.dp(2));
statusTextView[2].setAlpha(0.0f);
} else {
statusTextView[0].setVisibility(INVISIBLE);
statusTextView[0].setTranslationY(AndroidUtilities.dp(2));
statusTextView[0].setAlpha(0.0f);
statusTextView[1].setVisibility(INVISIBLE);
statusTextView[1].setTranslationY(-AndroidUtilities.dp(2));
statusTextView[1].setAlpha(0.0f);
statusTextView[2].setVisibility(VISIBLE);
statusTextView[2].setTranslationY(0);
statusTextView[2].setAlpha(1.0f);
}
}
@Override
public boolean hasOverlappingRendering() {
return false;
@ -481,7 +494,7 @@ public class GroupCallUserCell extends FrameLayout {
private BlobDrawable blobDrawable2;
private boolean hasCustomColor;
private boolean isMuted;
private int isMuted;
private float progressToMuted = 0;
boolean invalidateColor = true;
@ -535,13 +548,13 @@ public class GroupCallUserCell extends FrameLayout {
canvas.scale(scaleBlob * wavesEnter, scaleBlob * wavesEnter, cx, cy);
if (!hasCustomColor) {
if (isMuted && progressToMuted != 1f) {
if (isMuted != 1 && progressToMuted != 1f) {
progressToMuted += 16 / 150f;
if (progressToMuted > 1f) {
progressToMuted = 1f;
}
invalidateColor = true;
} else if (!isMuted && progressToMuted != 0f) {
} else if (isMuted == 1 && progressToMuted != 0f) {
progressToMuted -= 16 / 150f;
if (progressToMuted < 0f) {
progressToMuted = 0f;
@ -550,7 +563,7 @@ public class GroupCallUserCell extends FrameLayout {
}
if (invalidateColor) {
int color = ColorUtils.blendARGB(Theme.getColor(Theme.key_voipgroup_speakingText), Theme.getColor(Theme.key_voipgroup_listeningText), progressToMuted);
int color = ColorUtils.blendARGB(Theme.getColor(Theme.key_voipgroup_speakingText), isMuted == 2 ? Theme.getColor(Theme.key_voipgroup_mutedByAdminIcon) : Theme.getColor(Theme.key_voipgroup_listeningText), progressToMuted);
blobDrawable.paint.setColor(ColorUtils.setAlphaComponent(color, (int) (255 * WaveDrawable.CIRCLE_ALPHA_2)));
}
}
@ -575,9 +588,9 @@ public class GroupCallUserCell extends FrameLayout {
return scaleAvatar * wavesEnter + 1f * (1f - wavesEnter);
}
public void setShowWaves(boolean show, View parenView) {
public void setShowWaves(boolean show, View parentView) {
if (showWaves != show) {
parenView.invalidate();
parentView.invalidate();
}
showWaves = show;
}
@ -601,10 +614,10 @@ public class GroupCallUserCell extends FrameLayout {
blobDrawable.paint.setColor(color);
}
public void setMuted(boolean isMuted, boolean animated) {
this.isMuted = isMuted;
public void setMuted(int status, boolean animated) {
this.isMuted = status;
if (!animated) {
progressToMuted = isMuted ? 1f : 0f;
progressToMuted = isMuted != 1 ? 1f : 0f;
}
invalidateColor = true;
}

View File

@ -30,6 +30,7 @@ import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CounterView;
import org.telegram.ui.Components.LayoutHelper;
public class HintDialogCell extends FrameLayout {
@ -40,12 +41,14 @@ public class HintDialogCell extends FrameLayout {
private RectF rect = new RectF();
private int lastUnreadCount;
private int countWidth;
private StaticLayout countLayout;
private TLRPC.User currentUser;
private long dialog_id;
private int currentAccount = UserConfig.selectedAccount;
float showOnlineProgress;
boolean wasDraw;
CounterView counterView;
public HintDialogCell(Context context) {
super(context);
@ -62,11 +65,17 @@ public class HintDialogCell extends FrameLayout {
nameTextView.setLines(1);
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 64, 6, 0));
counterView = new CounterView(context);
addView(counterView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, Gravity.TOP,0 ,4,0,0));
counterView.setColors(Theme.key_chats_unreadCounterText, Theme.key_chats_unreadCounter);
counterView.setGravity(Gravity.RIGHT);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(86), MeasureSpec.EXACTLY));
counterView.horizontalPadding = AndroidUtilities.dp(13);
}
public void update(int mask) {
@ -84,19 +93,11 @@ public class HintDialogCell extends FrameLayout {
if (dialog != null && dialog.unread_count != 0) {
if (lastUnreadCount != dialog.unread_count) {
lastUnreadCount = dialog.unread_count;
String countString = String.format("%d", dialog.unread_count);
countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(Theme.dialogs_countTextPaint.measureText(countString)));
countLayout = new StaticLayout(countString, Theme.dialogs_countTextPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
if (mask != 0) {
invalidate();
}
}
} else if (countLayout != null) {
if (mask != 0) {
invalidate();
counterView.setCount(lastUnreadCount, wasDraw);
}
} else {
lastUnreadCount = 0;
countLayout = null;
counterView.setCount(0, wasDraw);
}
}
@ -114,6 +115,10 @@ public class HintDialogCell extends FrameLayout {
}
public void setDialog(int uid, boolean counter, CharSequence name) {
if (dialog_id != uid) {
wasDraw = false;
invalidate();
}
dialog_id = uid;
if (uid > 0) {
currentUser = MessagesController.getInstance(currentAccount).getUser(uid);
@ -141,8 +146,6 @@ public class HintDialogCell extends FrameLayout {
}
if (counter) {
update(0);
} else {
countLayout = null;
}
}
@ -150,25 +153,35 @@ public class HintDialogCell extends FrameLayout {
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean result = super.drawChild(canvas, child, drawingTime);
if (child == imageView) {
if (countLayout != null) {
int top = AndroidUtilities.dp(6);
int left = AndroidUtilities.dp(54);
int x = left - AndroidUtilities.dp(5.5f);
rect.set(x, top, x + countWidth + AndroidUtilities.dp(11), top + AndroidUtilities.dp(23));
canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id) ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint);
canvas.save();
canvas.translate(left, top + AndroidUtilities.dp(4));
countLayout.draw(canvas);
canvas.restore();
boolean showOnline = currentUser != null && !currentUser.bot && (currentUser.status != null && currentUser.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(currentUser.id));
if (!wasDraw) {
showOnlineProgress = showOnline ? 1f : 0f;
}
if (currentUser != null && !currentUser.bot && (currentUser.status != null && currentUser.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(currentUser.id))) {
if (showOnline && showOnlineProgress != 1f) {
showOnlineProgress += 16f / 150;
if (showOnlineProgress > 1) {
showOnlineProgress = 1f;
}
invalidate();
} else if (!showOnline && showOnlineProgress != 0) {
showOnlineProgress -= 16f / 150;
if (showOnlineProgress < 0) {
showOnlineProgress = 0;
}
invalidate();
}
if (showOnlineProgress != 0) {
int top = AndroidUtilities.dp(53);
int left = AndroidUtilities.dp(59);
canvas.save();
canvas.scale(showOnlineProgress, showOnlineProgress, left, top);
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite));
canvas.drawCircle(left, top, AndroidUtilities.dp(7), Theme.dialogs_onlineCirclePaint);
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_chats_onlineCircle));
canvas.drawCircle(left, top, AndroidUtilities.dp(5), Theme.dialogs_onlineCirclePaint);
canvas.restore();
}
wasDraw = true;
}
return result;
}

View File

@ -35,6 +35,7 @@ import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.DotDividerSpan;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.MediaActionDrawable;
import org.telegram.ui.Components.RadialProgress2;
@ -109,25 +110,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
description2TextPaint.setTextSize(AndroidUtilities.dp(13));
dotSpan = new SpannableStringBuilder(".");
dotSpan.setSpan(new ReplacementSpan() {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
int color;
@Override
public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) {
return AndroidUtilities.dp(3);
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
if (color != paint.getColor()) {
p.setColor(paint.getColor());
}
float radius = AndroidUtilities.dpf2(3) / 2f;
canvas.drawCircle(x + radius, (bottom - top) / 2, radius, p);
}
}, 0, 1, 0);
dotSpan.setSpan(new DotDividerSpan(), 0, 1, 0);
}
captionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);

View File

@ -8,18 +8,29 @@
package org.telegram.ui.Cells;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ReplacementSpan;
import android.transition.ChangeBounds;
import android.transition.Fade;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.transition.TransitionValues;
import android.transition.Visibility;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
@ -40,11 +51,16 @@ import org.telegram.messenger.FileLoader;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.DotDividerSpan;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LineProgressView;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.FilteredSearchView;
import java.io.File;
@ -58,7 +74,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
private TextView nameTextView;
private TextView extTextView;
private TextView dateTextView;
private ImageView statusImageView;
private RLottieImageView statusImageView;
private LineProgressView progressView;
private CheckBox2 checkBox;
private TextView rightDateTextView;
@ -81,6 +97,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
private SpannableStringBuilder dotSpan;
private CharSequence caption;
private RLottieDrawable statusDrawable;
public SharedDocumentCell(Context context) {
this(context, VIEW_TYPE_DEFAULT);
@ -181,13 +198,15 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 5, LocaleController.isRTL ? 72 : 8, 0));
}
statusImageView = new ImageView(context);
statusDrawable = new RLottieDrawable(R.raw.download_arrow, "download_arrow", AndroidUtilities.dp(14), AndroidUtilities.dp(14), true, null);
statusImageView = new RLottieImageView(context);
statusImageView.setAnimation(statusDrawable);
statusImageView.setVisibility(INVISIBLE);
statusImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_sharedMedia_startStopLoadIcon), PorterDuff.Mode.MULTIPLY));
if (viewType == VIEW_TYPE_PICKER) {
addView(statusImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 39, LocaleController.isRTL ? 72 : 8, 0));
addView(statusImageView, LayoutHelper.createFrame(14, 14, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 70, 37, LocaleController.isRTL ? 72 : 8, 0));
} else {
addView(statusImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 35, LocaleController.isRTL ? 72 : 8, 0));
addView(statusImageView, LayoutHelper.createFrame(14, 14, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 70, 33, LocaleController.isRTL ? 72 : 8, 0));
}
dateTextView = new TextView(context);
@ -222,25 +241,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
if (viewType == VIEW_TYPE_GLOBAL_SEARCH) {
dotSpan = new SpannableStringBuilder(".");
dotSpan.setSpan(new ReplacementSpan() {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
int color;
@Override
public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) {
return AndroidUtilities.dp(3);
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
if (color != paint.getColor()) {
p.setColor(paint.getColor());
}
float radius = AndroidUtilities.dpf2(3) / 2f;
canvas.drawCircle(x + radius, (bottom - top) / 2, radius, p);
}
}, 0, 1, 0);
dotSpan.setSpan(new DotDividerSpan(), 0, 1, 0);
}
}
@ -359,7 +360,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (progressView.getVisibility() == VISIBLE) {
updateFileExistIcon();
updateFileExistIcon(false);
}
}
@ -371,6 +372,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
}
public void setDocument(MessageObject messageObject, boolean divider) {
boolean animated = message != null && messageObject != null && message.getId() != messageObject.getId();
needDivider = divider;
message = messageObject;
loaded = false;
@ -463,16 +465,31 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
setWillNotDraw(!needDivider);
progressView.setProgress(0, false);
updateFileExistIcon();
updateFileExistIcon(animated);
}
public void updateFileExistIcon() {
public void updateFileExistIcon(boolean animated) {
if (animated && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
TransitionSet transition = new TransitionSet();
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(150);
transition.addTransition(new Fade().setDuration(150)).addTransition(changeBounds);
transition.setOrdering(TransitionSet.ORDERING_TOGETHER);
transition.setInterpolator(CubicBezierInterpolator.DEFAULT);
TransitionManager.beginDelayedTransition(this, transition);
}
if (message != null && message.messageOwner.media != null) {
loaded = false;
if (message.attachPathExists || message.mediaExists) {
statusImageView.setVisibility(INVISIBLE);
progressView.setVisibility(INVISIBLE);
dateTextView.setPadding(0, 0, 0, 0);
LayoutParams layoutParams = (LayoutParams) dateTextView.getLayoutParams();
if (layoutParams != null) {
layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 8 : 72);
layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 72 : 8);
dateTextView.requestLayout();
}
loading = false;
loaded = true;
DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
@ -481,8 +498,20 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, message, this);
loading = FileLoader.getInstance(currentAccount).isLoadingFile(fileName);
statusImageView.setVisibility(VISIBLE);
statusImageView.setImageResource(loading ? R.drawable.media_doc_pause : R.drawable.media_doc_load);
dateTextView.setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(14), 0, LocaleController.isRTL ? AndroidUtilities.dp(14) : 0, 0);
statusDrawable.setCustomEndFrame(loading ? 15 : 0);
statusDrawable.setPlayInDirectionOfCustomEndFrame(true);
if (animated) {
statusImageView.playAnimation();
} else {
statusDrawable.setCurrentFrame(loading ? 15 : 0);
statusImageView.invalidate();
}
LayoutParams layoutParams = (LayoutParams) dateTextView.getLayoutParams();
if (layoutParams != null) {
layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 8 : (72 + 14));
layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? (72 + 14) : 8);
dateTextView.requestLayout();
}
if (loading) {
progressView.setVisibility(VISIBLE);
Float progress = ImageLoader.getInstance().getFileProgress(fileName);
@ -500,7 +529,12 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
progressView.setVisibility(INVISIBLE);
progressView.setProgress(0, false);
statusImageView.setVisibility(INVISIBLE);
dateTextView.setPadding(0, 0, 0, 0);
LayoutParams layoutParams = (LayoutParams) dateTextView.getLayoutParams();
if (layoutParams != null) {
layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 8 : 72);
layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 72 : 8);
dateTextView.requestLayout();
}
DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
}
}
@ -572,19 +606,19 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
@Override
public void onFailedDownload(String name, boolean canceled) {
updateFileExistIcon();
updateFileExistIcon(true);
}
@Override
public void onSuccessDownload(String name) {
progressView.setProgress(1, true);
updateFileExistIcon();
updateFileExistIcon(true);
}
@Override
public void onProgressDownload(String fileName, long downloadedSize, long totalSize) {
if (progressView.getVisibility() != VISIBLE) {
updateFileExistIcon();
updateFileExistIcon(true);
}
progressView.setProgress(Math.min(1f, downloadedSize / (float) totalSize), true);
}

View File

@ -34,6 +34,7 @@ public class TextCell extends FrameLayout {
private boolean needDivider;
private int offsetFromImage = 71;
private int imageLeft = 21;
private boolean inDialogs;
public TextCell(Context context) {
this(context, 23, false);
@ -70,6 +71,10 @@ public class TextCell extends FrameLayout {
setFocusable(true);
}
public void setIsInDialogs() {
inDialogs = true;
}
public SimpleTextView getTextView() {
return textView;
}
@ -219,7 +224,7 @@ public class TextCell extends FrameLayout {
@Override
protected void onDraw(Canvas canvas) {
if (needDivider) {
canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 68 : 20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 68 : 20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint);
canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? (inDialogs ? 72 : 68) : 20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? (inDialogs ? 72 : 68) : 20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint);
}
}

View File

@ -11,6 +11,7 @@ package org.telegram.ui.Cells;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
@ -45,7 +46,13 @@ public class TextInfoPrivacyCell extends FrameLayout {
public TextInfoPrivacyCell(Context context, int padding) {
super(context);
textView = new TextView(context);
textView = new TextView(context) {
@Override
protected void onDraw(Canvas canvas) {
onTextDraw();
super.onDraw(canvas);
}
};
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
textView.setPadding(0, AndroidUtilities.dp(10), 0, AndroidUtilities.dp(17));
@ -56,6 +63,10 @@ public class TextInfoPrivacyCell extends FrameLayout {
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, 0, padding, 0));
}
protected void onTextDraw() {
}
public void setLinkTextColorKey(String key) {
linkTextColorKey = key;
}

View File

@ -499,6 +499,11 @@ public class UserCell extends FrameLayout {
} else {
avatarImageView.setImageDrawable(avatarDrawable);
}
nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
if (adminTextView != null) {
adminTextView.setTextColor(Theme.getColor(Theme.key_profile_creatorIcon));
}
}
public void setSelfAsSavedMessages(boolean value) {

View File

@ -22,6 +22,7 @@ import android.os.Vibrator;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
@ -35,7 +36,6 @@ import android.widget.ScrollView;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
@ -59,12 +59,14 @@ import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextBlockCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.EditTextEmoji;
import org.telegram.ui.Components.ImageUpdater;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.EditTextBoldCursor;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkActionView;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.RadialProgressView;
import org.telegram.ui.Components.SizeNotifierFrameLayout;
@ -78,7 +80,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
private ShadowSectionCell sectionCell;
private BackupImageView avatarImage;
private View avatarOverlay;
private ImageView avatarEditor;
private RLottieImageView avatarEditor;
private AnimatorSet avatarAnimation;
private RadialProgressView avatarProgressView;
private AvatarDrawable avatarDrawable;
@ -91,11 +93,14 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
private HeaderCell headerCell2;
private EditTextBoldCursor editText;
private RLottieDrawable cameraDrawable;
private LinearLayout linearLayout;
private LinearLayout adminnedChannelsLayout;
private LinearLayout linkContainer;
private LinearLayout publicContainer;
private TextBlockCell privateContainer;
private LinearLayout privateContainer;
private LinkActionView permanentLinkView;
private RadioButtonCell radioButtonCell1;
private RadioButtonCell radioButtonCell2;
private TextInfoPrivacyCell typeInfoCell;
@ -108,7 +113,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
private boolean lastNameAvailable;
private boolean isPrivate;
private boolean loadingInvite;
private TLRPC.ExportedChatInvite invite;
private TLRPC.TL_chatInviteExported invite;
private boolean loadingAdminedChannels;
private TextInfoPrivacyCell adminedInfoCell;
@ -270,7 +275,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
progressDialog.show();
return;
}
final int reqId = MessagesController.getInstance(currentAccount).createChat(nameTextView.getText().toString(), new ArrayList<>(), descriptionTextView.getText().toString(), ChatObject.CHAT_TYPE_CHANNEL, null, null, ChannelCreateActivity.this);
final int reqId = MessagesController.getInstance(currentAccount).createChat(nameTextView.getText().toString(), new ArrayList<>(), descriptionTextView.getText().toString(), ChatObject.CHAT_TYPE_CHANNEL, false, null, null, ChannelCreateActivity.this);
progressDialog = new AlertDialog(getParentActivity(), 3);
progressDialog.setOnCancelListener(dialog -> {
ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true);
@ -481,18 +486,30 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
}
};
frameLayout.addView(avatarOverlay, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 16, 12, LocaleController.isRTL ? 16 : 0, 12));
avatarOverlay.setOnClickListener(view -> imageUpdater.openMenu(avatar != null, () -> {
avatar = null;
avatarBig = null;
inputPhoto = null;
inputVideo = null;
inputVideoPath = null;
videoTimestamp = 0;
showAvatarProgress(false, true);
avatarImage.setImage(null, null, avatarDrawable, null);
}));
avatarOverlay.setOnClickListener(view -> {
imageUpdater.openMenu(avatar != null, () -> {
avatar = null;
avatarBig = null;
inputPhoto = null;
inputVideo = null;
inputVideoPath = null;
videoTimestamp = 0;
showAvatarProgress(false, true);
avatarImage.setImage(null, null, avatarDrawable, null);
avatarEditor.setAnimation(cameraDrawable);
cameraDrawable.setCurrentFrame(0);
}, dialog -> {
cameraDrawable.setCustomEndFrame(86);
avatarEditor.playAnimation();
});
cameraDrawable.setCurrentFrame(0);
cameraDrawable.setCustomEndFrame(43);
avatarEditor.playAnimation();
});
avatarEditor = new ImageView(context) {
cameraDrawable = new RLottieDrawable(R.raw.camera, "" + R.raw.camera, AndroidUtilities.dp(60), AndroidUtilities.dp(60), false, null);
avatarEditor = new RLottieImageView(context) {
@Override
public void invalidate(int l, int t, int r, int b) {
super.invalidate(l, t, r, b);
@ -506,9 +523,10 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
}
};
avatarEditor.setScaleType(ImageView.ScaleType.CENTER);
avatarEditor.setImageResource(R.drawable.menu_camera_av);
avatarEditor.setAnimation(cameraDrawable);
avatarEditor.setEnabled(false);
avatarEditor.setClickable(false);
avatarEditor.setPadding(AndroidUtilities.dp(2), 0, 0, AndroidUtilities.dp(1));
frameLayout.addView(avatarEditor, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 16, 12, LocaleController.isRTL ? 16 : 0, 12));
avatarProgressView = new RadialProgressView(context);
@ -528,6 +546,15 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
InputFilter[] inputFilters = new InputFilter[1];
inputFilters[0] = new InputFilter.LengthFilter(100);
nameTextView.setFilters(inputFilters);
nameTextView.getEditText().setSingleLine(true);
nameTextView.getEditText().setImeOptions(EditorInfo.IME_ACTION_NEXT);
nameTextView.getEditText().setOnEditorActionListener((textView, i, keyEvent) -> {
if (i == EditorInfo.IME_ACTION_NEXT && !TextUtils.isEmpty(nameTextView.getEditText().getText())) {
descriptionTextView.requestFocus();
return true;
}
return false;
});
frameLayout.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 5 : 96, 0, LocaleController.isRTL ? 96 : 5, 0));
descriptionTextView = new EditTextBoldCursor(context);
@ -687,24 +714,14 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
}
});
privateContainer = new TextBlockCell(context);
privateContainer.setBackgroundDrawable(Theme.getSelectorDrawable(false));
linkContainer.addView(privateContainer);
privateContainer.setOnClickListener(v -> {
if (invite == null) {
return;
}
try {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("label", invite.link);
clipboard.setPrimaryClip(clip);
if (BulletinFactory.canShowBulletin(ChannelCreateActivity.this)) {
BulletinFactory.createCopyLinkBulletin(ChannelCreateActivity.this).show();
}
} catch (Exception e) {
FileLog.e(e);
}
});
privateContainer = new LinearLayout(context);
privateContainer.setOrientation(LinearLayout.VERTICAL);
linkContainer.addView(privateContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
permanentLinkView = new LinkActionView(context, this, null, chatId, true);
permanentLinkView.showOptions(false);
permanentLinkView.setUsers(0, null);
privateContainer.addView(permanentLinkView);
checkTextView = new TextView(context);
checkTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
@ -739,14 +756,18 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
return;
}
loadingInvite = true;
TLRPC.TL_messages_exportChatInvite req = new TLRPC.TL_messages_exportChatInvite();
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(-chatId);
TLRPC.TL_messages_getExportedChatInvites req = new TLRPC.TL_messages_getExportedChatInvites();
req.peer = getMessagesController().getInputPeer(-chatId);
req.admin_id = getMessagesController().getInputUser(getUserConfig().getCurrentUser());
req.limit = 1;
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (error == null) {
invite = (TLRPC.ExportedChatInvite) response;
TLRPC.TL_messages_exportedChatInvites invites = (TLRPC.TL_messages_exportedChatInvites) response;
invite = (TLRPC.TL_chatInviteExported) invites.invites.get(0);
}
loadingInvite = false;
privateContainer.setText(invite != null ? invite.link : LocaleController.getString("Loading", R.string.Loading), false);
permanentLinkView.setLink(invite != null ? invite.link : null);
}));
}
@ -785,7 +806,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
publicContainer.setVisibility(isPrivate ? View.GONE : View.VISIBLE);
privateContainer.setVisibility(isPrivate ? View.VISIBLE : View.GONE);
linkContainer.setPadding(0, 0, 0, isPrivate ? 0 : AndroidUtilities.dp(7));
privateContainer.setText(invite != null ? invite.link : LocaleController.getString("Loading", R.string.Loading), false);
permanentLinkView.setLink(invite != null ? invite.link : null);
checkTextView.setVisibility(!isPrivate && checkTextView.length() != 0 ? View.VISIBLE : View.GONE);
}
radioButtonCell1.setChecked(!isPrivate, true);
@ -917,7 +938,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
}
if (nameTextView != null) {
String text = nameTextView.getText().toString();
if (text != null && text.length() != 0) {
if (text.length() != 0) {
args.putString("nameTextView", text);
}
}

View File

@ -172,9 +172,11 @@ import org.telegram.ui.Components.ChatAttachAlertDocumentLayout;
import org.telegram.ui.Components.ChatAvatarContainer;
import org.telegram.ui.Components.ChatBigEmptyView;
import org.telegram.ui.Components.ChatGreetingsView;
import org.telegram.ui.Components.ChecksHintView;
import org.telegram.ui.Components.ClippingImageView;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.CorrectlyMeasuringTextView;
import org.telegram.ui.Components.CounterView;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.EditTextBoldCursor;
import org.telegram.ui.Components.EditTextCaption;
@ -184,7 +186,9 @@ import org.telegram.ui.Components.ExtendedGridLayoutManager;
import org.telegram.ui.Components.FireworksOverlay;
import org.telegram.ui.Components.FragmentContextView;
import org.telegram.ui.Components.HintView;
import org.telegram.ui.Components.ImportingAlert;
import org.telegram.ui.Components.InstantCameraView;
import org.telegram.ui.Components.InviteMembersBottomSheet;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.MessageBackgroundDrawable;
import org.telegram.ui.Components.NumberTextView;
@ -287,7 +291,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private FrameLayout pagedownButton;
private ImageView pagedownButtonImage;
private boolean pagedownButtonShowedByScroll;
private SimpleTextView pagedownButtonCounter;
private CounterView pagedownButtonCounter;
private FrameLayout mentiondownButton;
private SimpleTextView mentiondownButtonCounter;
private ImageView mentiondownButtonImage;
@ -326,6 +330,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private TextView voiceHintTextView;
private HintView noSoundHintView;
private HintView forwardHintView;
private ChecksHintView checksHintView;
private Runnable voiceHintHideRunnable;
private AnimatorSet voiceHintAnimation;
private View emojiButtonRed;
@ -636,6 +641,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private int distanceToPeer;
private boolean openImport;
private float chatListViewPaddingTop;
private int chatListViewPaddingVisibleOffset;
@ -645,7 +652,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private float topChatPanelViewOffset;
private float pinnedMessageEnterOffset;
private float topViewOffset;
protected TLRPC.Document preloadedGreetingsSticker;
private TLRPC.Document preloadedGreetingsSticker;
private boolean forceHistoryEmpty;
private float bottomPanelTranslationY;
private boolean invalidateChatListViewTopPadding;
private long activityResumeTime;
@ -667,7 +675,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
NotificationCenter.didUpdateConnectionState,
NotificationCenter.updateInterfaces,
NotificationCenter.closeChats,
NotificationCenter.contactsDidLoad,
// NotificationCenter.contactsDidLoad,
NotificationCenter.chatInfoCantLoad,
NotificationCenter.userInfoDidLoad,
NotificationCenter.pinnedInfoDidLoad,
@ -700,7 +708,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private int fixedKeyboardHeight = -1;
private boolean invalidateMessagesVisiblePart;
private boolean scrollByTouch;
private ChatActionCell infoTopView1;
public float getChatListViewPadding() {
return chatListViewPaddingTop;
@ -1290,6 +1297,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getNotificationCenter().addObserver(this, NotificationCenter.videoLoadingStateChanged);
getNotificationCenter().addObserver(this, NotificationCenter.scheduledMessagesUpdated);
getNotificationCenter().addObserver(this, NotificationCenter.diceStickersDidLoad);
getNotificationCenter().addObserver(this, NotificationCenter.dialogDeleted);
super.onFragmentCreate();
@ -1309,7 +1317,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int loadIndex = lastLoadIndex++;
waitingForLoad.add(loadIndex);
getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialog_id, messageObjects.size(), messageObjects, false, 0, last_message_id, 0, 0, 2, true, classGuid, loadIndex, pinnedMessageIds.get(0), 0, MODE_PINNED);
} else {
} else if (!forceHistoryEmpty) {
loading = true;
}
if (isThreadChat()) {
@ -1363,7 +1371,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
loadInfo = userInfo == null;
}
if (chatMode != MODE_PINNED) {
if (forceHistoryEmpty) {
endReached[0] = endReached[1] = true;
forwardEndReached[0] = forwardEndReached[1] = true;
firstLoading = false;
}
if (chatMode != MODE_PINNED && !forceHistoryEmpty) {
waitingForLoad.add(lastLoadIndex);
if (startLoadFromMessageId != 0 && (!isThreadChat() || startLoadFromMessageId == highlightMessageId)) {
startLoadFromMessageIdSaved = startLoadFromMessageId;
@ -1569,6 +1582,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getNotificationCenter().removeObserver(this, NotificationCenter.videoLoadingStateChanged);
getNotificationCenter().removeObserver(this, NotificationCenter.scheduledMessagesUpdated);
getNotificationCenter().removeObserver(this, NotificationCenter.diceStickersDidLoad);
getNotificationCenter().removeObserver(this, NotificationCenter.dialogDeleted);
if (currentEncryptedChat != null) {
getNotificationCenter().removeObserver(this, NotificationCenter.didVerifyMessagesStickers);
}
@ -1636,6 +1650,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
mediaBanTooltip = null;
noSoundHintView = null;
forwardHintView = null;
checksHintView = null;
textSelectionHint = null;
emojiButtonRed = null;
gifHintTextView = null;
@ -1756,7 +1771,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
final boolean isChat = (int) dialog_id < 0 && (int) (dialog_id >> 32) != 1;
AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, id == clear_history, currentChat, currentUser, currentEncryptedChat != null, (param) -> {
AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, id == clear_history, currentChat, currentUser, currentEncryptedChat != null, true, (param) -> {
if (id == clear_history && ChatObject.isChannel(currentChat) && (!currentChat.megagroup || !TextUtils.isEmpty(currentChat.username))) {
getMessagesController().deleteDialog(dialog_id, 2, param);
} else {
@ -2065,6 +2080,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
editTextItem = menu.addItem(0, R.drawable.ic_ab_other);
editTextItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions));
editTextItem.setTag(null);
editTextItem.setVisibility(View.GONE);
@ -2142,6 +2158,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (chatMode == 0 && !isThreadChat()) {
attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setOverrideMenuClick(true).setAllowCloseAnimation(false);
attachItem.setContentDescription(LocaleController.getString("AccDescrAttachButton", R.string.AccDescrAttachButton));
attachItem.setVisibility(View.GONE);
}
@ -2236,6 +2253,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
chatListView.setItemAnimator(null);
chatListView.invalidate();
updateBulletinLayout();
}
@Override
@ -2338,7 +2356,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (scrimView != null && (child == pagedownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay)) {
return false;
}
if (child == fragmentContextView && fragmentContextView.getCurrentStyle() == 3) {
if (child == fragmentContextView && fragmentContextView.isCallStyle()) {
return true;
}
if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) != null ) {
@ -2440,7 +2458,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
updateMessagesVisiblePart(false);
}
super.dispatchDraw(canvas);
if (fragmentContextView != null && fragmentContextView.getCurrentStyle() == 3) {
if (fragmentContextView != null && fragmentContextView.isCallStyle()) {
canvas.save();
canvas.translate(fragmentContextView.getX(), fragmentContextView.getY());
fragmentContextView.setDrawOverlay(true);
@ -2764,6 +2782,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
AndroidUtilities.runOnUIThread(() -> chatLayoutManager.scrollToPositionWithOffset(scrollTo, scrollToOffsetOnRecreate));
scrollToPositionOnRecreate = -1;
}
updateBulletinLayout();
}
@Override
@ -2843,7 +2863,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (child == blurredView) {
childTop = 0;
} else if (child instanceof HintView) {
} else if (child instanceof HintView || child instanceof ChecksHintView) {
childTop = 0;
} else if (child == mentionContainer) {
childTop -= chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(2);
@ -2942,7 +2962,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
emptyViewContainer.setOnTouchListener((v, event) -> true);
int distance = getArguments().getInt("nearby_distance", -1);
if (distance >= 0 && currentUser != null) {
if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null) {
greetingsViewContainer = new ChatGreetingsView(context, currentUser, distance, preloadedGreetingsSticker);
greetingsViewContainer.setListener((sticker) -> {
animatingDocuments.put(sticker, 0);
@ -3040,7 +3060,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
public void setTranslationY(float translationY) {
super.setTranslationY(translationY);
if (emptyViewContainer != null) {
emptyViewContainer.setTranslationY(translationY / 1.7f);
if (chatActivityEnterView != null && chatActivityEnterView.pannelAniamationInProgress()) {
emptyViewContainer.setTranslationY(translationY / 2f);
} else {
emptyViewContainer.setTranslationY(translationY / 1.7f);
}
}
invalidateChatListViewTopPadding();
invalidateMessagesVisiblePart();
@ -3263,7 +3287,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public boolean onTouchEvent(MotionEvent e) {
textSelectionHelper.checkSelectionCancel(e);
if (e != null && e.getAction() == MotionEvent.ACTION_DOWN) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
scrollByTouch = true;
}
if (isFastScrollAnimationRunning()) {
@ -4570,10 +4594,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
canvas.save();
canvas.clipRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(48));
}
boolean result = super.drawChild(canvas, child, drawingTime);
if (child == pinnedLineView) {
boolean result;
if (child == pinnedMessageTextView[0] || child == pinnedMessageTextView[1]) {
canvas.save();
canvas.clipRect(0,0,getMeasuredWidth() - AndroidUtilities.dp(38),getMeasuredHeight());
result = super.drawChild(canvas, child, drawingTime);
canvas.restore();
} else {
result = super.drawChild(canvas, child, drawingTime);
if (child == pinnedLineView) {
canvas.restore();
}
}
return result;
}
};
@ -4778,6 +4811,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public void requestLayout() {
if (ignoreLayout) {
@ -4805,7 +4839,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
reportSpamButton.setSingleLine(true);
reportSpamButton.setMaxLines(1);
reportSpamButton.setGravity(Gravity.CENTER);
topChatPanelView.addView(reportSpamButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, AndroidUtilities.dp(1)));
topChatPanelView.addView(reportSpamButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 1));
reportSpamButton.setOnClickListener(v2 -> AlertsCreator.showBlockReportSpamAlert(ChatActivity.this, dialog_id, currentUser, currentChat, currentEncryptedChat, reportSpamButton.getTag(R.id.object_tag) != null, chatInfo, param -> {
if (param == 0) {
updateTopPanel(true);
@ -4824,9 +4858,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
addToContactsButton.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0);
addToContactsButton.setGravity(Gravity.CENTER);
if (Build.VERSION.SDK_INT >= 21) {
addToContactsButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_chat_addContact) & 0x19ffffff, 5));
addToContactsButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_chat_addContact) & 0x19ffffff, 2));
}
topChatPanelView.addView(addToContactsButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, AndroidUtilities.dp(1)));
topChatPanelView.addView(addToContactsButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 1));
addToContactsButton.setOnClickListener(v -> {
if (addToContactsButtonArchive) {
getMessagesController().addDialogToFolder(dialog_id, 0, 0, 0);
@ -4839,6 +4873,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
editor.commit();
updateTopPanel(false);
getNotificationsController().clearDialogNotificationsSettings(dialog_id);
} else if (addToContactsButton.getTag() != null && (Integer) addToContactsButton.getTag() == 4) {
if (chatInfo != null && chatInfo.participants != null) {
SparseArray<TLObject> users = new SparseArray<>();
for (int a = 0; a < chatInfo.participants.participants.size(); a++) {
users.put(chatInfo.participants.participants.get(a).user_id, null);
}
int chatId = chatInfo.id;
InviteMembersBottomSheet bottomSheet = new InviteMembersBottomSheet(context, currentAccount, users, chatInfo.id, ChatActivity.this);
bottomSheet.setDelegate((users1, fwdCount) -> {
for (int a = 0, N = users1.size(); a < N; a++) {
TLRPC.User user = users1.get(a);
getMessagesController().addUserToChat(chatId, user, fwdCount, null, ChatActivity.this, null);
}
getMessagesController().hidePeerSettingsBar(dialog_id, currentUser, currentChat);
updateTopPanel(true);
updateInfoTopView(true);
});
bottomSheet.show();
}
} else if (addToContactsButton.getTag() != null) {
shareMyContact(1, null);
} else {
@ -4867,6 +4920,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
getMessagesController().hidePeerSettingsBar(did, currentUser, currentChat);
updateTopPanel(true);
updateInfoTopView(true);
});
alertView = new FrameLayout(context);
@ -4895,7 +4949,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
pagedownButton = new FrameLayout(context);
pagedownButton.setVisibility(View.INVISIBLE);
contentView.addView(pagedownButton, LayoutHelper.createFrame(66, 59, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5));
contentView.addView(pagedownButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5));
pagedownButton.setOnClickListener(view -> {
wasManualScroll = true;
textSelectionHelper.cancelTextSelectionRunnable();
@ -4914,7 +4968,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
mentiondownButton = new FrameLayout(context);
mentiondownButton.setVisibility(View.INVISIBLE);
contentView.addView(mentiondownButton, LayoutHelper.createFrame(46, 59, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 7, 5));
contentView.addView(mentiondownButton, LayoutHelper.createFrame(46, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 7, 5));
mentiondownButton.setOnClickListener(new View.OnClickListener() {
private void loadLastUnreadMention() {
@ -5524,16 +5578,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
pagedownButton.addView(pagedownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
pagedownButton.setContentDescription(LocaleController.getString("AccDescrPageDown", R.string.AccDescrPageDown));
pagedownButtonCounter = new SimpleTextView(context);
pagedownButtonCounter.setVisibility(View.INVISIBLE);
pagedownButtonCounter.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
pagedownButtonCounter.setTextSize(13);
pagedownButtonCounter.setTextColor(Theme.getColor(Theme.key_chat_goDownButtonCounter));
pagedownButtonCounter.setGravity(Gravity.CENTER);
pagedownButtonCounter.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(11.5f), Theme.getColor(Theme.key_chat_goDownButtonCounterBackground)));
pagedownButtonCounter.setMinWidth(AndroidUtilities.dp(23));
pagedownButtonCounter.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(1), AndroidUtilities.dp(8), 0);
pagedownButton.addView(pagedownButtonCounter, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 23, Gravity.TOP | Gravity.LEFT));
pagedownButtonCounter = new CounterView(context);
pagedownButtonCounter.setReverse(true);
pagedownButton.addView(pagedownButtonCounter, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, Gravity.TOP | Gravity.LEFT));
mentiondownButtonImage = new ImageView(context);
mentiondownButtonImage.setImageResource(R.drawable.mentionbutton);
@ -5573,7 +5620,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
mentiondownButton.setContentDescription(LocaleController.getString("AccDescrMentionDown", R.string.AccDescrMentionDown));
contentView.addView(fragmentLocationContextView = new FragmentContextView(context, this, true), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0));
contentView.addView(fragmentContextView = new FragmentContextView(context, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0));
contentView.addView(fragmentContextView = new FragmentContextView(context, this, false) {
@Override
protected void playbackSpeedChanged(boolean enabled) {
undoView.showWithAction(0, enabled ? UndoView.ACTION_PLAYBACK_SPEED_ENABLED : UndoView.ACTION_PLAYBACK_SPEED_DISABLED, null);
}
}, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0));
fragmentContextView.setAdditionalContextView(fragmentLocationContextView);
fragmentLocationContextView.setAdditionalContextView(fragmentContextView);
@ -6114,14 +6166,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (pagedownButton != null) {
pagedownButton.setTranslationY(translation);
}
if (mentiondownButton != null) {
mentiondownButton.setTranslationY(pagedownButton.getVisibility() != View.VISIBLE ? translation : translation - AndroidUtilities.dp(72));
if (mentiondownButton != null) {
mentiondownButton.setTranslationY(pagedownButton.getVisibility() != View.VISIBLE ? translation : translation - AndroidUtilities.dp(72));
}
}
invalidateChatListViewTopPadding();
invalidateMessagesVisiblePart();
updateTextureViewPosition(false);
contentView.invalidate();
updateBulletinLayout();
}
@Override
@ -6237,7 +6290,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
DialogsActivity fragment = new DialogsActivity(args);
fragment.setDelegate(ChatActivity.this);
presentFragment(fragment);
} else if (replyingMessageObject != null) {
} else if (replyingMessageObject != null && (!isThreadChat() || replyingMessageObject.getId() != threadMessageId)) {
scrollToMessageId(replyingMessageObject.getId(), 0, true, 0, true, 0);
} else if (editingMessageObject != null) {
if (editingMessageObject.canEditMedia() && editingMessageObjectReqId == 0) {
@ -6645,7 +6698,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
toggleMute(true);
}
} else {
AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, false, currentChat, currentUser, currentEncryptedChat != null, (param) -> {
AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, false, currentChat, currentUser, currentEncryptedChat != null, true, (param) -> {
getNotificationCenter().removeObserver(ChatActivity.this, NotificationCenter.closeChats);
getNotificationCenter().postNotificationName(NotificationCenter.closeChats);
finishFragment();
@ -6809,6 +6862,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return fragmentView;
}
private void updateBulletinLayout() {
Bulletin bulletin = Bulletin.getVisibleBulletin();
if (bulletin != null && bulletinDelegate != null) {
bulletin.updatePosition();
}
}
private void searchUserMessages(TLRPC.User user, TLRPC.Chat chat) {
searchingUserMessages = user;
searchingChatMessages = chat;
@ -8153,6 +8213,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (pollHintView != null) {
pollHintView.hide();
}
if (checksHintView != null) {
checksHintView.hide();
}
}
private void showSlowModeHint(View view, boolean show, CharSequence time) {
@ -8296,6 +8359,47 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
private void checkChecksHint() {
if (getMessagesController().pendingSuggestions.contains("NEWCOMER_TICKS")) {
AndroidUtilities.runOnUIThread(this::showChecksHint, 1000);
}
}
private void showChecksHint() {
if (scrollingChatListView || chatListView == null || getParentActivity() == null || fragmentView == null || checksHintView != null && checksHintView.getTag() != null) {
return;
}
if (checksHintView == null) {
SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView;
int index = frameLayout.indexOfChild(chatActivityEnterView);
if (index == -1) {
return;
}
checksHintView = new ChecksHintView(getParentActivity());
frameLayout.addView(checksHintView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0));
checksHintView.setAlpha(0.0f);
checksHintView.setVisibility(View.INVISIBLE);
}
int count = chatListView.getChildCount();
for (int a = 0; a < count; a++) {
View child = chatListView.getChildAt(a);
if (!(child instanceof ChatMessageCell)) {
continue;
}
ChatMessageCell messageCell = (ChatMessageCell) child;
MessageObject messageObject = messageCell.getMessageObject();
if (messageObject == null || !messageObject.isOutOwner() || !messageObject.isSent()) {
continue;
}
if (checksHintView.showForMessageCell(messageCell, true)) {
getMessagesController().removeSuggestion("NEWCOMER_TICKS");
break;
}
}
}
private void showForwardHint(ChatMessageCell cell) {
if (scrollingChatListView || chatListView == null || getParentActivity() == null || fragmentView == null) {
return;
@ -8936,7 +9040,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
private void searchLinks(final CharSequence charSequence, final boolean force) {
if (currentEncryptedChat != null && (getMessagesController().secretWebpagePreview == 0 || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46)) {
if (currentEncryptedChat != null && (getMessagesController().secretWebpagePreview == 0 || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46) || editingMessageObject != null && !editingMessageObject.isWebpage()) {
return;
}
if (force && foundWebPage != null) {
@ -9105,6 +9209,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
public boolean shouldShowImport() {
return openImport;
}
public void setOpenImport() {
openImport = true;
}
private void checkBotKeyboard() {
if (chatActivityEnterView == null || botButtons == null || userBlocked) {
return;
@ -10091,7 +10203,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
floatingDateView.setTranslationY(chatListView.getTranslationY() + chatListViewPaddingTop + floatingDateViewOffset - AndroidUtilities.dp(4));
}
invalidateChatListViewTopPadding();
if (!firstLoading && !paused && !inPreviewMode && (fragmentOpened || inBubbleMode) && chatMode == 0 && !getMessagesController().ignoreSetOnline) {
if (!firstLoading && !paused && !inPreviewMode && chatMode == 0 && !getMessagesController().ignoreSetOnline) {
int scheduledRead = 0;
if ((maxPositiveUnreadId != Integer.MIN_VALUE || maxNegativeUnreadId != Integer.MAX_VALUE)) {
int counterDecrement = 0;
@ -10155,26 +10267,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private void inlineUpdate1() {
if (prevSetUnreadCount != newUnreadMessageCount) {
prevSetUnreadCount = newUnreadMessageCount;
pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount));
}
if (newUnreadMessageCount <= 0) {
if (pagedownButtonCounter.getVisibility() != View.INVISIBLE) {
pagedownButtonCounter.setVisibility(View.INVISIBLE);
}
} else {
if (pagedownButtonCounter.getVisibility() != View.VISIBLE) {
pagedownButtonCounter.setVisibility(View.VISIBLE);
}
pagedownButtonCounter.setCount(newUnreadMessageCount, openAnimationEnded);
}
}
private void inlineUpdate2() {
if (prevSetUnreadCount != newUnreadMessageCount) {
prevSetUnreadCount = newUnreadMessageCount;
pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount));
}
if (pagedownButtonCounter.getVisibility() != View.INVISIBLE) {
pagedownButtonCounter.setVisibility(View.INVISIBLE);
pagedownButtonCounter.setCount(newUnreadMessageCount, true);
}
}
@ -11239,7 +11339,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else if (chatMode == MODE_PINNED) {
avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount()));
} else if (currentChat != null) {
avatarContainer.setTitle(currentChat.title, currentChat.scam);
avatarContainer.setTitle(currentChat.title, currentChat.scam, currentChat.fake);
} else if (currentUser != null) {
if (currentUser.self) {
avatarContainer.setTitle(LocaleController.getString("SavedMessages", R.string.SavedMessages));
@ -11247,10 +11347,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (!TextUtils.isEmpty(currentUser.phone)) {
avatarContainer.setTitle(PhoneFormat.getInstance().format("+" + currentUser.phone));
} else {
avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam);
avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake);
}
} else {
avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam);
avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake);
}
}
setParentActivityTitle(avatarContainer.getTitleTextView().getText());
@ -12362,9 +12462,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
updatePagedownButtonVisibility(true);
if (unread_to_load != 0) {
if (pagedownButtonCounter != null) {
pagedownButtonCounter.setVisibility(View.VISIBLE);
if (prevSetUnreadCount != newUnreadMessageCount) {
pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount = unread_to_load));
pagedownButtonCounter.setCount(newUnreadMessageCount = unread_to_load, openAnimationEnded);
prevSetUnreadCount = newUnreadMessageCount;
}
}
@ -12439,7 +12538,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (first) {
if (chatListView != null) {
chatListView.setEmptyView(emptyViewContainer);
if (!fragmentBeginToShow) {
chatListView.setAnimateEmptyView(false, 1);
chatListView.setEmptyView(emptyViewContainer);
chatListView.setAnimateEmptyView(true, 1);
} else {
chatListView.setEmptyView(emptyViewContainer);
}
}
}
} else {
@ -12818,16 +12923,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (pagedownButtonCounter != null) {
if (prevSetUnreadCount != newUnreadMessageCount) {
prevSetUnreadCount = newUnreadMessageCount;
pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount));
}
if (newUnreadMessageCount <= 0) {
if (pagedownButtonCounter.getVisibility() != View.INVISIBLE) {
pagedownButtonCounter.setVisibility(View.INVISIBLE);
}
} else {
if (pagedownButtonCounter.getVisibility() != View.VISIBLE) {
pagedownButtonCounter.setVisibility(View.VISIBLE);
}
pagedownButtonCounter.setCount(newUnreadMessageCount, true);
}
}
}
@ -12950,6 +13046,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
if (obj != null) {
checkChecksHint();
if (obj.shouldRemoveVideoEditedInfo) {
obj.videoEditedInfo = null;
obj.shouldRemoveVideoEditedInfo = false;
@ -13462,7 +13559,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
MessageObject playing = cell.getMessageObject();
if (playing != null && playing.getId() == mid) {
MessageObject player = MediaController.getInstance().getPlayingMessageObject();
if (player != null) {
if (player != null && !cell.getSeekBar().isDragging()) {
playing.audioProgress = player.audioProgress;
playing.audioProgressSec = player.audioProgressSec;
playing.audioPlayerDuration = player.audioPlayerDuration;
@ -14210,6 +14307,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
cell.setCurrentDiceValue(true);
}
}
} else if (id == NotificationCenter.dialogDeleted) {
long did = (Long) args[0];
if (did == dialog_id) {
if (parentLayout != null && parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) == this) {
finishFragment();
} else {
removeSelfFromStack();
}
}
}
}
@ -14611,7 +14717,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
pagedownButtonCounter.setVisibility(View.VISIBLE);
if (prevSetUnreadCount != newUnreadMessageCount) {
prevSetUnreadCount = newUnreadMessageCount;
pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount));
pagedownButtonCounter.setCount(newUnreadMessageCount, true);
}
}
if (newMentionsCount != 0 && mentiondownButtonCounter != null) {
@ -14937,10 +15043,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else {
if (newUnreadMessageCount != 0 && pagedownButtonCounter != null) {
pagedownButtonCounter.setVisibility(View.VISIBLE);
if (prevSetUnreadCount != newUnreadMessageCount) {
prevSetUnreadCount = newUnreadMessageCount;
pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount));
pagedownButtonCounter.setCount(newUnreadMessageCount, true);
}
}
canShowPagedownButton = true;
@ -15220,9 +15325,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
createUnreadMessageAfterId = 0;
removeMessageObject(unreadMessageObject);
unreadMessageObject = null;
if (pagedownButtonCounter != null) {
pagedownButtonCounter.setVisibility(View.INVISIBLE);
}
}
if (updateScheduled) {
updateScheduledInterface(true);
@ -16701,6 +16803,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
boolean showAdd = preferences.getBoolean("dialog_bar_add" + did, false);
boolean showArchive = preferences.getBoolean("dialog_bar_archived" + dialog_id, false);
boolean showGeo = preferences.getBoolean("dialog_bar_location" + did, false);
boolean showAddMembersToGroup = preferences.getBoolean("dialog_bar_invite" + did, false);
if (showAddMembersToGroup) {
show = true;
}
if (showReport || showBlock || showGeo) {
reportSpamButton.setVisibility(View.VISIBLE);
@ -16710,7 +16817,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
addToContactsButtonArchive = false;
TLRPC.User user = currentUser != null ? getMessagesController().getUser(currentUser.id) : null;
if (user != null) {
if (showAddMembersToGroup) {
String str = LocaleController.getString("GroupAddMembers", R.string.GroupAddMembers);
if (str != null) {
str = str.toUpperCase();
}
addToContactsButton.setVisibility(View.VISIBLE);
addToContactsButton.setText(str);
addToContactsButton.setTag(4);
addToContactsButton.setTextColor(Theme.getColor(Theme.key_chat_addContact));
if (Build.VERSION.SDK_INT >= 21) {
Theme.setSelectorDrawableColor(addToContactsButton.getBackground(), Theme.getColor(Theme.key_chat_addContact) & 0x19ffffff, true);
}
reportSpamButton.setTag(Theme.key_chat_addContact);
} else if (user != null) {
if (UserObject.isReplyUser(user)) {
addToContactsButton.setVisibility(View.GONE);
} else if (!user.contact && !user.self && showAdd) {
@ -16974,6 +17094,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
updateSecretStatus();
}
Bulletin.Delegate bulletinDelegate;
@Override
public void onResume() {
super.onResume();
@ -16982,6 +17104,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
blurredView.setBackground(null);
}
activityResumeTime = System.currentTimeMillis();
if (openImport && getSendMessagesHelper().getImportingHistory(dialog_id) != null) {
ImportingAlert alert = new ImportingAlert(getParentActivity(), this);
alert.setOnHideListener(dialog -> {
if (fragmentContextView != null) {
fragmentContextView.checkImport(false);
}
});
showDialog(alert);
openImport = false;
}
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
MediaController.getInstance().startRaiseToEarSensors(this);
@ -16992,20 +17124,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (contentView != null) {
contentView.onResume();
}
checkChecksHint();
Bulletin.addDelegate(this, new Bulletin.Delegate() {
Bulletin.addDelegate(this, bulletinDelegate = new Bulletin.Delegate() {
@Override
public int getBottomOffset() {
final int height;
int height;
if (chatActivityEnterView != null && chatActivityEnterView.getVisibility() == View.VISIBLE) {
final EmojiView emojiView = chatActivityEnterView.getEmojiView();
if (emojiView != null && emojiView.getVisibility() == View.VISIBLE) {
return 0;
if (contentView.getKeyboardHeight() < AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing() || chatActivityEnterView.pannelAniamationInProgress()) {
height = chatActivityEnterView.getHeight() + chatActivityEnterView.getEmojiPadding();
} else {
height = chatActivityEnterView.getHeight();
}
height = chatActivityEnterView.getHeight();
} else {
height = AndroidUtilities.dp(51);
}
if (chatActivityEnterView.pannelAniamationInProgress()) {
float translationY = bottomPanelTranslationY - chatActivityEnterView.getEmojiPadding();
height += translationY;
}
height += contentPanTranslation;
return height - AndroidUtilities.dp(1.5f);
}
});
@ -18180,6 +18318,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return;
}
processSelectedOption(options.get(i));
scrimView = null;
contentView.invalidate();
chatListView.invalidate();
if (scrimPopupWindow != null) {
scrimPopupWindow.dismiss();
}
@ -18582,6 +18723,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
AndroidUtilities.addToClipboard(getMessageContent(selectedObject, 0, false));
}
}
undoView.showWithAction(0, UndoView.ACTION_TEXT_COPIED, null);
break;
}
case 4: {
@ -19166,6 +19308,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getSendMessagesHelper().sendMessage(fmessages, did, true, 0);
}
fragment.finishFragment();
if (dids.size() == 1) {
undoView.showWithAction(dids.get(0), UndoView.ACTION_FWD_MESSAGES, fmessages.size());
} else {
undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, fmessages.size(), dids.size(), null, null);
}
} else {
long did = dids.get(0);
if (did != dialog_id || chatMode == MODE_PINNED) {
@ -20439,6 +20586,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
fragmentView.requestLayout();
}
}
@Override
protected void onSend(LongSparseArray<TLRPC.Dialog> dids, int count) {
if (dids.size() == 1) {
undoView.showWithAction(dids.valueAt(0).id, UndoView.ACTION_FWD_MESSAGES, count);
} else {
undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, count, dids.size(), null, null);
}
}
});
AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid);
fragmentView.requestLayout();
@ -20462,6 +20618,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showNoSoundHint();
}
@Override
public void didPressTime(ChatMessageCell cell) {
undoView.showWithAction(dialog_id, UndoView.ACTION_IMPORT_INFO, null);
}
@Override
public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY) {
if (chat == null) {
@ -20476,6 +20637,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public void didPressHiddenForward(ChatMessageCell cell) {
if (cell.getMessageObject().isImportedForward()) {
didPressTime(cell);
return;
}
showForwardHint(cell);
}
@ -21120,7 +21285,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
MessageObject nextMessage = messages.get(nextPosition - messagesStartRow);
pinnedBottom = nextMessage.isOutOwner() == message.isOutOwner() && Math.abs(nextMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60;
if (pinnedBottom) {
if (currentChat != null) {
if (message.isImportedForward() || nextMessage.isImportedForward()) {
if (message.isImportedForward() && nextMessage.isImportedForward()) {
if (Math.abs(nextMessage.messageOwner.fwd_from.date - message.messageOwner.fwd_from.date) <= 5 * 60) {
if (nextMessage.messageOwner.fwd_from.from_name != null && message.messageOwner.fwd_from.from_name != null) {
pinnedBottom = nextMessage.messageOwner.fwd_from.from_name.equals(message.messageOwner.fwd_from.from_name);
} else if (nextMessage.messageOwner.fwd_from.from_id != null && message.messageOwner.fwd_from.from_id != null) {
pinnedBottom = MessageObject.getPeerId(nextMessage.messageOwner.fwd_from.from_id) == MessageObject.getPeerId(message.messageOwner.fwd_from.from_id);
} else {
pinnedBottom = false;
}
} else {
pinnedBottom = false;
}
} else {
pinnedBottom = false;
}
} else if (currentChat != null) {
int fromId = nextMessage.getFromChatId();
pinnedBottom = fromId == message.getFromChatId();
if (!pinnedBottomByGroup && pinnedBottom && fromId < 0 && currentChat.megagroup) {
@ -21139,9 +21320,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
MessageObject prevMessage = messages.get(prevPosition - messagesStartRow);
pinnedTop = !prevMessage.hasReactions() && !(prevMessage.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && prevMessage.isOutOwner() == message.isOutOwner() && Math.abs(prevMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60;
if (pinnedTop) {
if (currentChat != null) {
if (message.isImportedForward() || prevMessage.isImportedForward()) {
if (message.isImportedForward() && prevMessage.isImportedForward()) {
if (Math.abs(message.messageOwner.fwd_from.date - prevMessage.messageOwner.fwd_from.date) <= 5 * 60) {
if (prevMessage.messageOwner.fwd_from.from_name != null && message.messageOwner.fwd_from.from_name != null) {
pinnedTop = prevMessage.messageOwner.fwd_from.from_name.equals(message.messageOwner.fwd_from.from_name);
} else if (prevMessage.messageOwner.fwd_from.from_id != null && message.messageOwner.fwd_from.from_id != null) {
pinnedTop = MessageObject.getPeerId(prevMessage.messageOwner.fwd_from.from_id) == MessageObject.getPeerId(message.messageOwner.fwd_from.from_id);
} else {
pinnedTop = false;
}
} else {
pinnedTop = false;
}
} else {
pinnedTop = false;
}
} else if (currentChat != null) {
int fromId = prevMessage.getFromChatId();
pinnedTop = fromId == message.getFromChatId();
pinnedTop = fromId == message.getFromChatId() && !message.isImportedForward() && !prevMessage.isImportedForward();
if (!pinnedTopByGroup && pinnedTop && fromId < 0 && currentChat.megagroup) {
pinnedTop = false;
}
@ -21718,8 +21915,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return false;
}
public void setPreloadedSticker(TLRPC.Document preloadedSticker) {
public void setPreloadedSticker(TLRPC.Document preloadedSticker, boolean historyEmpty) {
preloadedGreetingsSticker = preloadedSticker;
forceHistoryEmpty = historyEmpty;
}
public class ChatScrollCallback extends RecyclerAnimationScrollHelper.AnimationCallback {
@ -22067,6 +22265,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_pollHintDrawable[1]}, null, Theme.key_chat_outPreviewInstantText));
themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_psaHelpDrawable[0]}, null, Theme.key_chat_inViews));
themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_psaHelpDrawable[1]}, null, Theme.key_chat_outViews));
themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_shareBackground));
themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_shareBackgroundSelected));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, Theme.avatarDrawables, null, Theme.key_avatar_text));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countPaint, null, null, Theme.key_chats_unreadCounter));
@ -22074,7 +22274,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Paint[]{Theme.dialogs_nameEncryptedPaint[0], Theme.dialogs_nameEncryptedPaint[1], Theme.dialogs_searchNameEncryptedPaint}, null, null, Theme.key_chats_secretName));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, null, Theme.key_chats_secretIcon));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, null, Theme.key_chats_nameIcon));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_scamDrawable}, null, Theme.key_chats_draft));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_scamDrawable, Theme.dialogs_fakeDrawable}, null, Theme.key_chats_draft));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePaint[1], null, null, Theme.key_chats_message_threeLines));
themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messageNamePaint, null, null, Theme.key_chats_nameMessage_threeLines));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chats_nameMessage));
@ -22186,7 +22386,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_inappPlayerBackground));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"playButton"}, null, null, null, Theme.key_inappPlayerPlayPause));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerTitle));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"subtitleTextView"}, null, null, null, Theme.key_inappPlayerClose));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"closeButton"}, null, null, null, Theme.key_inappPlayerClose));

View File

@ -44,7 +44,6 @@ import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
@ -108,6 +107,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
private LinearLayout infoContainer;
private TextCell membersCell;
private TextCell inviteLinksCell;
private TextCell adminCell;
private TextCell blockCell;
private TextCell logCell;
@ -209,9 +209,28 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
signMessages = currentChat.signatures;
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatInfoDidLoad);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateInterfaces);
if (info != null) {
loadLinksCount();
}
return super.onFragmentCreate();
}
private void loadLinksCount() {
// TLRPC.TL_messages_getExportedChatInvites req = new TLRPC.TL_messages_getExportedChatInvites();
// req.peer = getMessagesController().getInputPeer(-chatId);
// req.admin_id = getMessagesController().getInputUser(getUserConfig().getCurrentUser());
// req.limit = 0;
// getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
// if (error == null) {
// TLRPC.TL_messages_exportedChatInvites invites = (TLRPC.TL_messages_exportedChatInvites) response;
// info.invitesCount = invites.count;
// getMessagesStorage().saveChatLinksCount(chatId, info.invitesCount);
// updateFields(false);
// }
// }));
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
@ -555,7 +574,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
MessagesController.getInstance(currentAccount).changeChatAvatar(chatId, null, null, null, 0, null, null, null);
showAvatarProgress(false, true);
avatarImage.setImage(null, null, avatarDrawable, currentChat);
}));
}, null));
settingsContainer.addView(setAvatarCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
@ -753,6 +772,14 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
presentFragment(fragment);
});
// inviteLinksCell = new TextCell(context);
// inviteLinksCell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
// inviteLinksCell.setOnClickListener(v -> {
// ManageLinksActivity fragment = new ManageLinksActivity(chatId);
// fragment.setInfo(info, info.exported_invite);
// presentFragment(fragment);
// });
adminCell = new TextCell(context);
adminCell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
adminCell.setOnClickListener(v -> {
@ -785,6 +812,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
if (!isChannel) {
infoContainer.addView(blockCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
// infoContainer.addView(inviteLinksCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
infoContainer.addView(adminCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
infoContainer.addView(membersCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
if (isChannel) {
@ -832,20 +860,18 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
deleteCell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
if (isChannel) {
deleteCell.setText(LocaleController.getString("ChannelDelete", R.string.ChannelDelete), false);
} else if (currentChat.megagroup) {
deleteCell.setText(LocaleController.getString("DeleteMega", R.string.DeleteMega), false);
} else {
deleteCell.setText(LocaleController.getString("DeleteAndExitButton", R.string.DeleteAndExitButton), false);
}
deleteContainer.addView(deleteCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
deleteCell.setOnClickListener(v -> AlertsCreator.createClearOrDeleteDialogAlert(ChatEditActivity.this, false, true, false, currentChat, null, false, (param) -> {
deleteCell.setOnClickListener(v -> AlertsCreator.createClearOrDeleteDialogAlert(ChatEditActivity.this, false, true, false, currentChat, null, false, true, (param) -> {
if (AndroidUtilities.isTablet()) {
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats, -(long) chatId);
getNotificationCenter().postNotificationName(NotificationCenter.closeChats, -(long) chatId);
} else {
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats);
getNotificationCenter().postNotificationName(NotificationCenter.closeChats);
}
MessagesController.getInstance(currentAccount).deleteUserFromChat(chatId, MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()), info, true, false);
finishFragment();
getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, (long) -currentChat.id, null, currentChat, param);
}));
deleteInfoCell = new ShadowSectionCell(context);
@ -917,9 +943,13 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
if (info == null && descriptionTextView != null) {
descriptionTextView.setText(chatFull.about);
}
boolean infoWasEmpty = info == null;
info = chatFull;
historyHidden = !ChatObject.isChannel(currentChat) || info.hidden_prehistory;
updateFields(false);
if (infoWasEmpty) {
loadLinksCount();
}
}
} else if (id == NotificationCenter.updateInterfaces) {
int mask = (Integer) args[0];
@ -1324,6 +1354,11 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
}
adminCell.setTextAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), R.drawable.actions_addadmin, true);
}
// if (info != null && info.invitesCount >= 0) {
// inviteLinksCell.setTextAndValueAndIcon(LocaleController.getString("InviteLinks", R.string.InviteLinks), Integer.toString(info.invitesCount), R.drawable.actions_link, true);
// } else {
// inviteLinksCell.setTextAndIcon(LocaleController.getString("InviteLinks", R.string.InviteLinks), R.drawable.actions_link, true);
// }
}
if (stickersCell != null && info != null) {
@ -1361,6 +1396,10 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
themeDescriptions.add(new ThemeDescription(adminCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(adminCell, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(adminCell, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon));
// themeDescriptions.add(new ThemeDescription(inviteLinksCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
// themeDescriptions.add(new ThemeDescription(inviteLinksCell, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
// themeDescriptions.add(new ThemeDescription(inviteLinksCell, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon));
themeDescriptions.add(new ThemeDescription(blockCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(blockCell, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(blockCell, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon));

View File

@ -9,7 +9,6 @@
package org.telegram.ui;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Vibrator;
import android.text.Editable;
@ -24,9 +23,7 @@ import android.widget.LinearLayout;
import android.widget.ScrollView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
@ -44,14 +41,16 @@ import org.telegram.ui.Cells.HeaderCell;
import org.telegram.ui.Cells.LoadingCell;
import org.telegram.ui.Cells.RadioButtonCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextBlockCell;
import org.telegram.ui.Cells.TextCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Cells.TextSettingsCell;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.EditTextBoldCursor;
import org.telegram.ui.Components.InviteLinkBottomSheet;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkActionView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
public class ChatEditTypeActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
@ -72,10 +71,9 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
private LinearLayout linkContainer;
private LinearLayout publicContainer;
private LinearLayout privateContainer;
private TextBlockCell privateTextView;
private TextSettingsCell copyCell;
private TextSettingsCell revokeCell;
private TextSettingsCell shareCell;
private LinkActionView permanentLinkView;
// private TextCell manageLinksTextView;
// private TextInfoPrivacyCell manageLinksInfoCell;
private ShadowSectionCell sectionCell2;
private TextInfoPrivacyCell infoCell;
private TextSettingsCell textCell;
@ -99,13 +97,15 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
private Runnable checkRunnable;
private boolean lastNameAvailable;
private boolean loadingInvite;
private TLRPC.ExportedChatInvite invite;
private TLRPC.TL_chatInviteExported invite;
private boolean ignoreTextChanges;
private boolean isForcePublic;
HashMap<Integer, TLRPC.User> usersMap = new HashMap<>();
private final static int done_button = 1;
private InviteLinkBottomSheet inviteLinkBottomSheet;
public ChatEditTypeActivity(int id, boolean forcePublic) {
chatId = id;
@ -142,6 +142,9 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
}
}));
}
if (isPrivate && info != null) {
getMessagesController().loadFullChat(chatId, classGuid, true);
}
getNotificationCenter().addObserver(this, NotificationCenter.chatInfoDidLoad);
return super.onFragmentCreate();
}
@ -164,6 +167,11 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
textCell2.setText(LocaleController.getString("GroupStickers", R.string.GroupStickers), false);
}
}
if (info != null) {
invite = info.exported_invite;
permanentLinkView.setLink(invite == null ? null : invite.link);
permanentLinkView.loadUsers(invite, chatId);
}
}
@Override
@ -340,71 +348,21 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
privateContainer.setOrientation(LinearLayout.VERTICAL);
linkContainer.addView(privateContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
privateTextView = new TextBlockCell(context);
privateTextView.setBackgroundDrawable(Theme.getSelectorDrawable(false));
privateContainer.addView(privateTextView);
privateTextView.setOnClickListener(v -> {
if (invite == null) {
return;
permanentLinkView = new LinkActionView(context, this, null, chatId, true);
permanentLinkView.setDelegate(new LinkActionView.Delegate() {
@Override
public void revokeLink() {
ChatEditTypeActivity.this.generateLink(true);
}
try {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("label", invite.link);
clipboard.setPrimaryClip(clip);
BulletinFactory.createCopyLinkBulletin(this).show();
} catch (Exception e) {
FileLog.e(e);
}
});
copyCell = new TextSettingsCell(context);
copyCell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
copyCell.setText(LocaleController.getString("CopyLink", R.string.CopyLink), true);
privateContainer.addView(copyCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
copyCell.setOnClickListener(v -> {
if (invite == null) {
return;
}
try {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("label", invite.link);
clipboard.setPrimaryClip(clip);
BulletinFactory.createCopyLinkBulletin(this).show();
} catch (Exception e) {
FileLog.e(e);
}
});
revokeCell = new TextSettingsCell(context);
revokeCell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
revokeCell.setText(LocaleController.getString("RevokeLink", R.string.RevokeLink), true);
privateContainer.addView(revokeCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
revokeCell.setOnClickListener(v -> {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setMessage(LocaleController.getString("RevokeAlert", R.string.RevokeAlert));
builder.setTitle(LocaleController.getString("RevokeLink", R.string.RevokeLink));
builder.setPositiveButton(LocaleController.getString("RevokeButton", R.string.RevokeButton), (dialogInterface, i) -> generateLink(true));
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
showDialog(builder.create());
});
shareCell = new TextSettingsCell(context);
shareCell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
shareCell.setText(LocaleController.getString("ShareLink", R.string.ShareLink), false);
privateContainer.addView(shareCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
shareCell.setOnClickListener(v -> {
if (invite == null) {
return;
}
try {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, invite.link);
getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink)), 500);
} catch (Exception e) {
FileLog.e(e);
@Override
public void showUsersForPermanentLink() {
inviteLinkBottomSheet = new InviteLinkBottomSheet(context, invite, info, usersMap, ChatEditTypeActivity.this, chatId, true);
inviteLinkBottomSheet.show();
}
});
permanentLinkView.setUsers(0, null);
privateContainer.addView(permanentLinkView);
checkTextView = new TextInfoPrivacyCell(context);
checkTextView.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
@ -425,6 +383,25 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
adminedInfoCell = new ShadowSectionCell(context);
linearLayout.addView(adminedInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
// manageLinksTextView = new TextCell(context);
// manageLinksTextView.setBackgroundDrawable(Theme.getSelectorDrawable(true));
// manageLinksTextView.setOnClickListener(v -> {
// if (invite == null) {
// return;
// }
// });
// manageLinksTextView.setTextAndIcon(LocaleController.getString("ManageInviteLinks", R.string.ManageInviteLinks), R.drawable.actions_link, false);
// manageLinksTextView.setOnClickListener(v -> {
// ManageLinksActivity fragment = new ManageLinksActivity(chatId);
// fragment.setInfo(info, invite);
// presentFragment(fragment);
// });
// linearLayout.addView(manageLinksTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
//
// manageLinksInfoCell = new TextInfoPrivacyCell(context);
// linearLayout.addView(manageLinksInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
if (!isPrivate && currentChat.username != null) {
ignoreTextChanges = true;
usernameTextView.setText(currentChat.username);
@ -451,7 +428,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
public void setInfo(TLRPC.ChatFull chatFull) {
info = chatFull;
if (chatFull != null) {
if (chatFull.exported_invite instanceof TLRPC.TL_chatInviteExported) {
if (chatFull.exported_invite != null) {
invite = chatFull.exported_invite;
} else {
generateLink(false);
@ -603,10 +580,19 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
}
publicContainer.setVisibility(isPrivate ? View.GONE : View.VISIBLE);
privateContainer.setVisibility(isPrivate ? View.VISIBLE : View.GONE);
//manageLinksTextView.setVisibility(isPrivate ? View.VISIBLE : View.GONE);
// manageLinksInfoCell.setVisibility(isPrivate ? View.VISIBLE : View.GONE);
linkContainer.setPadding(0, 0, 0, isPrivate ? 0 : AndroidUtilities.dp(7));
privateTextView.setText(invite != null ? invite.link : LocaleController.getString("Loading", R.string.Loading), true);
permanentLinkView.setLink(invite != null ? invite.link : null);
permanentLinkView.loadUsers(invite, chatId);
checkTextView.setVisibility(!isPrivate && checkTextView.length() != 0 ? View.VISIBLE : View.GONE);
typeInfoCell.setBackgroundDrawable(checkTextView.getVisibility() == View.VISIBLE ? null : Theme.getThemedDrawable(typeInfoCell.getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
if (isPrivate) {
typeInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(typeInfoCell.getContext(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
// manageLinksInfoCell.setBackground(Theme.getThemedDrawable(typeInfoCell.getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
// manageLinksInfoCell.setText(LocaleController.getString("ManageLinksInfoHelp", R.string.ManageLinksInfoHelp));
} else {
typeInfoCell.setBackgroundDrawable(checkTextView.getVisibility() == View.VISIBLE ? null : Theme.getThemedDrawable(typeInfoCell.getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
}
}
radioButtonCell1.setChecked(!isPrivate, true);
radioButtonCell2.setChecked(isPrivate, true);
@ -702,10 +688,11 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
private void generateLink(final boolean newRequest) {
loadingInvite = true;
TLRPC.TL_messages_exportChatInvite req = new TLRPC.TL_messages_exportChatInvite();
//req.legacy_revoke_permanent = true; TODO layer 124
req.peer = getMessagesController().getInputPeer(-chatId);
final int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (error == null) {
invite = (TLRPC.ExportedChatInvite) response;
invite = (TLRPC.TL_chatInviteExported) response;
if (info != null) {
info.exported_invite = invite;
}
@ -721,8 +708,9 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
}
}
loadingInvite = false;
if (privateTextView != null) {
privateTextView.setText(invite != null ? invite.link : LocaleController.getString("Loading", R.string.Loading), true);
if (permanentLinkView != null) {
permanentLinkView.setLink(invite != null ? invite.link : null);
permanentLinkView.loadUsers(invite, chatId);
}
}));
getConnectionsManager().bindRequestToGuid(reqId, classGuid);
@ -730,7 +718,8 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
@Override
public ArrayList<ThemeDescription> getThemeDescriptions() {
ArrayList<ThemeDescription> themeDescriptions = new ArrayList<>();ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> {
ArrayList<ThemeDescription> themeDescriptions = new ArrayList<>();
ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> {
if (adminnedChannelsLayout != null) {
int count = adminnedChannelsLayout.getChildCount();
for (int a = 0; a < count; a++) {
@ -740,6 +729,12 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
}
}
}
permanentLinkView.updateColors();
// manageLinksTextView.setBackgroundDrawable(Theme.getSelectorDrawable(true));
if (inviteLinkBottomSheet != null) {
inviteLinkBottomSheet.updateColors();
}
};
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
@ -777,10 +772,12 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
themeDescriptions.add(new ThemeDescription(typeInfoCell, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
themeDescriptions.add(new ThemeDescription(typeInfoCell, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteRedText4));
// themeDescriptions.add(new ThemeDescription(manageLinksInfoCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
// themeDescriptions.add(new ThemeDescription(manageLinksInfoCell, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
// themeDescriptions.add(new ThemeDescription(manageLinksInfoCell, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteRedText4));
themeDescriptions.add(new ThemeDescription(adminedInfoCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
themeDescriptions.add(new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
themeDescriptions.add(new ThemeDescription(privateTextView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(privateTextView, 0, new Class[]{TextBlockCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(loadingAdminedCell, 0, new Class[]{LoadingCell.class}, new String[]{"progressBar"}, null, null, null, Theme.key_progressCircle));
themeDescriptions.add(new ThemeDescription(radioButtonCell1, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(radioButtonCell1, ThemeDescription.FLAG_CHECKBOX, new Class[]{RadioButtonCell.class}, new String[]{"radioButton"}, null, null, null, Theme.key_radioBackground));
@ -793,15 +790,6 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
themeDescriptions.add(new ThemeDescription(radioButtonCell2, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{RadioButtonCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(radioButtonCell2, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{RadioButtonCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2));
themeDescriptions.add(new ThemeDescription(copyCell, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(copyCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(revokeCell, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(revokeCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(shareCell, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(shareCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText));
themeDescriptions.add(new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_LINKCOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText));
@ -815,6 +803,11 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink));
// themeDescriptions.add(new ThemeDescription(manageLinksTextView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
// themeDescriptions.add(new ThemeDescription(manageLinksTextView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
// themeDescriptions.add(new ThemeDescription(manageLinksTextView, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon));
return themeDescriptions;
}
}

View File

@ -8,6 +8,8 @@
package org.telegram.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
@ -22,6 +24,7 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
@ -36,9 +39,10 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
@ -86,6 +90,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private ListAdapter listViewAdapter;
private StickerEmptyView emptyView;
private RecyclerListView listView;
private LinearLayoutManager layoutManager;
private SearchAdapter searchListViewAdapter;
private ActionBarMenuItem searchItem;
private ActionBarMenuItem doneItem;
@ -150,7 +155,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private int blockedEmptyRow;
private int rowCount;
private int selectType;
private int lastEmptyViewRow;
private int loadingUserCellRow;
private int loadingHeaderRow;
private int delayResults;
@ -170,7 +176,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
public final static int TYPE_ADMIN = 1;
public final static int TYPE_USERS = 2;
public final static int TYPE_KICKED = 3;
private boolean openTransitionEnded;
private boolean openTransitionStarted;
private FlickerLoadingView flickerLoadingView;
private View progressBar;
@ -186,6 +192,10 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
default void didSelectUser(int uid) {
}
default void didUserKicked(int userId) {
}
}
private class ChooseView extends View {
@ -454,7 +464,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
slowmodeSelectRow = -1;
slowmodeInfoRow = -1;
loadingProgressRow = -1;
lastEmptyViewRow = -1;
loadingUserCellRow = -1;
loadingHeaderRow = -1;
rowCount = 0;
if (type == TYPE_KICKED) {
@ -486,9 +497,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
addNewRow = rowCount++;
}
if (loadingUsers && !firstLoaded) {
//loadingProgressRow = rowCount++;
} else {
if (!(loadingUsers && !firstLoaded)) {
if (!participants.isEmpty()) {
participantsStartRow = rowCount;
rowCount += participants.size();
@ -497,18 +506,19 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
if (addNewRow != -1 || participantsStartRow != -1) {
addNewSectionRow = rowCount++;
}
lastEmptyViewRow = rowCount++;
} else if (!firstLoaded) {
if (info != null && info.banned_count > 0) {
loadingUserCellRow = rowCount++;
}
}
} else if (type == TYPE_BANNED) {
if (ChatObject.canBlockUsers(currentChat)) {
addNewRow = rowCount++;
if (!participants.isEmpty()) {
if (!participants.isEmpty() || (loadingUsers && !firstLoaded && (info != null && info.kicked_count > 0))) {
participantsInfoRow = rowCount++;
}
}
if (loadingUsers && !firstLoaded) {
// loadingProgressRow = rowCount++;
} else {
if (!(loadingUsers && !firstLoaded)) {
if (!participants.isEmpty()) {
restricted1SectionRow = rowCount++;
participantsStartRow = rowCount;
@ -518,14 +528,16 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
if (participantsStartRow != -1) {
if (participantsInfoRow == -1) {
participantsInfoRow = rowCount++;
lastEmptyViewRow = rowCount++;
} else {
addNewSectionRow = rowCount++;
}
} else {
restricted1SectionRow = rowCount++;
blockedEmptyRow = rowCount++;
}
lastEmptyViewRow = rowCount++;
} else if (!firstLoaded) {
restricted1SectionRow = rowCount++;
loadingUserCellRow = rowCount++;
}
} else if (type == TYPE_ADMIN) {
if (ChatObject.isChannel(currentChat) && currentChat.megagroup && (info == null || info.participants_count <= 200)) {
@ -536,28 +548,21 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
if (ChatObject.canAddAdmins(currentChat)) {
addNewRow = rowCount++;
}
if (loadingUsers && !firstLoaded) {
// loadingProgressRow = rowCount++;
} else {
if (!(loadingUsers && !firstLoaded)) {
if (!participants.isEmpty()) {
participantsStartRow = rowCount;
rowCount += participants.size();
participantsEndRow = rowCount;
}
participantsInfoRow = rowCount++;
lastEmptyViewRow = rowCount++;
} else if (!firstLoaded) {
loadingUserCellRow = rowCount++;
}
} else if (type == TYPE_USERS) {
if (selectType == 0 && ChatObject.canAddUsers(currentChat)) {
/*if (ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_INVITE) && (!ChatObject.isChannel(currentChat) || currentChat.megagroup || TextUtils.isEmpty(currentChat.username))) {
addNew2Row = rowCount++;
addNewSectionRow = rowCount++;
}*/
addNewRow = rowCount++;
}
if (loadingUsers && !firstLoaded) {
// loadingProgressRow = rowCount++;
} else {
if (!(loadingUsers && !firstLoaded)) {
boolean hasAnyOther = false;
if (!contacts.isEmpty()) {
contactsHeaderRow = rowCount++;
@ -583,8 +588,12 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
}
if (rowCount != 0) {
participantsInfoRow = rowCount++;
lastEmptyViewRow = rowCount++;
}
} else if (!firstLoaded) {
if (selectType == 0) {
loadingHeaderRow = rowCount++;
}
loadingUserCellRow = rowCount++;
}
}
}
@ -660,6 +669,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
public void onSearchCollapse() {
searchListViewAdapter.searchUsers(null);
searching = false;
listView.setAnimateEmptyView(false, 0);
listView.setAdapter(listViewAdapter);
listViewAdapter.notifyDataSetChanged();
listView.setFastScrollVisible(true);
@ -678,6 +688,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
int oldItemsCount = listView.getAdapter() == null ? 0 : listView.getAdapter().getItemCount();
searchListViewAdapter.searchUsers(text);
if (TextUtils.isEmpty(text) && listView != null && listView.getAdapter() != listViewAdapter) {
listView.setAnimateEmptyView(false, 0);
listView.setAdapter(listViewAdapter);
if (oldItemsCount == 0) {
showItemsAnimated(0);
@ -698,8 +709,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
}
}
fragmentView = new FrameLayout(context);
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
fragmentView = new FrameLayout(context) {
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawColor(Theme.getColor(listView.getAdapter() == searchListViewAdapter ? Theme.key_windowBackgroundWhite : Theme.key_windowBackgroundGray));
super.dispatchDraw(canvas);
}
};
FrameLayout frameLayout = (FrameLayout) fragmentView;
FrameLayout progressLayout = new FrameLayout(context);
@ -711,24 +727,66 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
progressBar = new RadialProgressView(context);
progressLayout.addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
frameLayout.addView(progressLayout);
if (type == 3) {
flickerLoadingView.setVisibility(View.GONE);
} else {
progressBar.setVisibility(View.GONE);
}
flickerLoadingView.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
emptyView = new StickerEmptyView(context, progressLayout, StickerEmptyView.STICKER_TYPE_SEARCH);
emptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult));
emptyView.subtitle.setText(LocaleController.getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2));
emptyView.setVisibility(View.GONE);
emptyView.setAnimateLayoutChange(true);
emptyView.showProgress(true, false);
frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
listView = new RecyclerListView(context);
listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
((SimpleItemAnimator) listView.getItemAnimator()).setSupportsChangeAnimations(false);
frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
emptyView.addView(progressLayout,0);
listView = new RecyclerListView(context) {
@Override
public void invalidate() {
super.invalidate();
fragmentView.invalidate();
}
};
listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) {
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
if (!firstLoaded && type != TYPE_KICKED) {
return 0;
}
return super.scrollVerticallyBy(dy, recycler, state);
}
});
DefaultItemAnimator itemAnimator = new DefaultItemAnimator() {
@Override
protected long getAddAnimationDelay(long removeDuration, long moveDuration, long changeDuration) {
return 0;
}
@Override
protected long getMoveAnimationDelay() {
return 0;
}
@Override
public long getMoveDuration() {
return 220;
}
@Override
public long getRemoveDuration() {
return 220;
}
@Override
public long getAddDuration() {
return 220;
}
};
listView.setItemAnimator(itemAnimator);
itemAnimator.setSupportsChangeAnimations(false);
listView.setAnimateEmptyView(true, 0);
listView.setAdapter(listViewAdapter = new ListAdapter(context));
listView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT);
frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
@ -744,6 +802,35 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
bundle.putInt("selectType", type == TYPE_BANNED ? 2 : 3);
ChatUsersActivity fragment = new ChatUsersActivity(bundle);
fragment.setInfo(info);
fragment.setDelegate(new ChatUsersActivityDelegate() {
@Override
public void didAddParticipantToList(int uid, TLObject participant) {
if (participantsMap.get(uid) == null) {
DiffCallback diffCallback = saveState();
participants.add(participant);
participantsMap.put(uid, participant);
sortUsers(participants);
updateListAnimated(diffCallback);
}
}
@Override
public void didUserKicked(int uid) {
if (participantsMap.get(uid) == null) {
DiffCallback diffCallback = saveState();
TLRPC.TL_channelParticipantBanned chatParticipant = new TLRPC.TL_channelParticipantBanned();
chatParticipant.user_id = uid;
chatParticipant.date = getConnectionsManager().getCurrentTime();
chatParticipant.kicked_by = getAccountInstance().getUserConfig().clientUserId;
info.kicked_count++;
participants.add(chatParticipant);
participantsMap.put(uid, chatParticipant);
sortUsers(participants);
updateListAnimated(diffCallback);
}
}
});
presentFragment(fragment);
} else if (type == TYPE_ADMIN) {
Bundle bundle = new Bundle();
@ -755,21 +842,11 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
@Override
public void didAddParticipantToList(int uid, TLObject participant) {
if (participant != null && participantsMap.get(uid) == null) {
DiffCallback diffCallback = saveState();
participants.add(participant);
Collections.sort(participants, (lhs, rhs) -> {
int type1 = getChannelAdminParticipantType(lhs);
int type2 = getChannelAdminParticipantType(rhs);
if (type1 > type2) {
return 1;
} else if (type1 < type2) {
return -1;
}
return 0;
});
updateRows();
if (listViewAdapter != null) {
listViewAdapter.notifyDataSetChanged();
}
participantsMap.put(uid, participant);
sortAdmins(participants);
updateListAnimated(diffCallback);
}
}
@ -788,6 +865,20 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
}
}, 200);
}
if (participantsMap.get(uid) == null) {
DiffCallback diffCallback = saveState();
TLRPC.TL_channelParticipantAdmin chatParticipant = new TLRPC.TL_channelParticipantAdmin();
chatParticipant.user_id = user.id;
chatParticipant.date = getConnectionsManager().getCurrentTime();
chatParticipant.promoted_by = getAccountInstance().getUserConfig().clientUserId;
participants.add(chatParticipant);
participantsMap.put(user.id, chatParticipant);
sortAdmins(participants);
updateListAnimated(diffCallback);
}
}
});
fragment.setInfo(info);
@ -802,10 +893,30 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
fragment.setDelegate(new GroupCreateActivity.ContactsAddActivityDelegate() {
@Override
public void didSelectUsers(ArrayList<TLRPC.User> users, int fwdCount) {
DiffCallback savedState = saveState();
ArrayList<TLObject> array = contactsMap != null && contactsMap.size() != 0 ? contacts : participants;
SparseArray<TLObject> map = contactsMap != null && contactsMap.size() != 0 ? contactsMap : participantsMap;
int k = 0;
for (int a = 0, N = users.size(); a < N; a++) {
TLRPC.User user = users.get(a);
getMessagesController().addUserToChat(chatId, user, fwdCount, null, ChatUsersActivity.this, null);
getMessagesController().putUser(user, false);
if (map.get(user.id) == null) {
TLRPC.ChatParticipant participant = new TLRPC.TL_chatParticipant();
participant.inviter_id = getUserConfig().getClientUserId();
participant.user_id = user.id;
participant.date = getConnectionsManager().getCurrentTime();
array.add(k, participant);
k++;
map.put(user.id, participant);
}
}
if (array == participants) {
sortAdmins(participants);
}
updateListAnimated(savedState);
}
@Override
@ -1081,7 +1192,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
updateRows();
listView.setEmptyView(emptyView);
listView.setAnimateEmptyView(true, 0);
listView.setAnimateEmptyView(false, 0);
if (needOpenSearch) {
searchItem.openSearch(false);
@ -1090,10 +1201,40 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
return fragmentView;
}
private void sortAdmins(ArrayList<TLObject> participants) {
Collections.sort(participants, (lhs, rhs) -> {
int type1 = getChannelAdminParticipantType(lhs);
int type2 = getChannelAdminParticipantType(rhs);
if (type1 > type2) {
return 1;
} else if (type1 < type2) {
return -1;
}
if (lhs instanceof TLRPC.ChannelParticipant && rhs instanceof TLRPC.ChannelParticipant) {
return ((TLRPC.ChannelParticipant) lhs).user_id - ((TLRPC.ChannelParticipant) rhs).user_id;
}
return 0;
});
}
private void showItemsAnimated(int from) {
if (isPaused || !openTransitionEnded) {
if (isPaused || !openTransitionStarted || (listView.getAdapter() == listViewAdapter && firstLoaded)) {
return;
}
View progressView = null;
for (int i = 0; i < listView.getChildCount(); i++) {
View child = listView.getChildAt(i);
if (child instanceof FlickerLoadingView) {
progressView = child;
}
}
final View finalProgressView = progressView;
if (progressView != null) {
listView.removeView(progressView);
from--;
}
int finalFrom = from;
listView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
@ -1102,7 +1243,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
AnimatorSet animatorSet = new AnimatorSet();
for (int i = 0; i < n; i++) {
View child = listView.getChildAt(i);
if (listView.getChildAdapterPosition(child) < from) {
if (child == finalProgressView || listView.getChildAdapterPosition(child) < finalFrom) {
continue;
}
child.setAlpha(0);
@ -1113,6 +1254,25 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
a.setDuration(200);
animatorSet.playTogether(a);
}
if (finalProgressView != null && finalProgressView.getParent() == null) {
listView.addView(finalProgressView);
RecyclerView.LayoutManager layoutManager = listView.getLayoutManager();
if (layoutManager != null) {
layoutManager.ignoreView(finalProgressView);
Animator animator = ObjectAnimator.ofFloat(finalProgressView, View.ALPHA, finalProgressView.getAlpha(), 0);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
finalProgressView.setAlpha(1f);
layoutManager.stopIgnoringView(finalProgressView);
listView.removeView(finalProgressView);
}
});
animator.start();
}
}
animatorSet.start();
return true;
}
@ -1195,16 +1355,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
creator.user_id = user.id;
participantsMap.put(user.id, creator);
participants.add(creator);
Collections.sort(participants, (lhs, rhs) -> {
int type1 = getChannelAdminParticipantType(lhs);
int type2 = getChannelAdminParticipantType(rhs);
if (type1 > type2) {
return 1;
} else if (type1 < type2) {
return -1;
}
return 0;
});
sortAdmins(participants);
updateRows();
}
listViewAdapter.notifyDataSetChanged();
@ -1306,6 +1457,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
}
if (delegate != null && rights == 1) {
delegate.didSelectUser(user_id);
} else if (delegate != null) {
delegate.didAddParticipantToList(user_id, participant);
}
if (removeFragment) {
removeSelfFromStack();
@ -1326,11 +1479,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
}
TLRPC.User user = getMessagesController().getUser(userId);
getMessagesController().deleteUserFromChat(chatId, user, null);
if (delegate != null) {
delegate.didUserKicked(userId);
}
finishFragment();
}
private TLObject getAnyParticipant(int userId) {
boolean updated = false;
for (int a = 0; a < 3; a++) {
SparseArray<TLObject> map;
if (a == 0) {
@ -1360,6 +1515,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private void removeParticipants(int userId) {
boolean updated = false;
DiffCallback savedState = saveState();
for (int a = 0; a < 3; a++) {
SparseArray<TLObject> map;
ArrayList<TLObject> arrayList;
@ -1378,11 +1534,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
map.remove(userId);
arrayList.remove(p);
updated = true;
if (type == TYPE_BANNED) {
info.kicked_count--;
}
}
}
if (updated) {
updateRows();
listViewAdapter.notifyDataSetChanged();
updateListAnimated(savedState);
}
if (listView.getAdapter() == searchListViewAdapter) {
searchListViewAdapter.removeUserId(userId);
@ -1998,7 +2156,6 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
req.offset = offset;
req.limit = count;
int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
resumeDelayedFragmentAnimation();
if (error == null) {
TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response;
if (type == TYPE_ADMIN) {
@ -2060,82 +2217,80 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
}
try {
if ((type == TYPE_BANNED || type == TYPE_KICKED || type == TYPE_USERS) && currentChat != null && currentChat.megagroup && info instanceof TLRPC.TL_channelFull && info.participants_count <= 200) {
int currentTime = getConnectionsManager().getCurrentTime();
Collections.sort(objects, (lhs, rhs) -> {
TLRPC.ChannelParticipant p1 = (TLRPC.ChannelParticipant) lhs;
TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) rhs;
TLRPC.User user1 = getMessagesController().getUser(p1.user_id);
TLRPC.User user2 = getMessagesController().getUser(p2.user_id);
int status1 = 0;
int status2 = 0;
if (user1 != null && user1.status != null) {
if (user1.self) {
status1 = currentTime + 50000;
} else {
status1 = user1.status.expires;
}
}
if (user2 != null && user2.status != null) {
if (user2.self) {
status2 = currentTime + 50000;
} else {
status2 = user2.status.expires;
}
}
if (status1 > 0 && status2 > 0) {
if (status1 > status2) {
return 1;
} else if (status1 < status2) {
return -1;
}
return 0;
} else if (status1 < 0 && status2 < 0) {
if (status1 > status2) {
return 1;
} else if (status1 < status2) {
return -1;
}
return 0;
} else if (status1 < 0 && status2 > 0 || status1 == 0 && status2 != 0) {
return -1;
} else if (status2 < 0 && status1 > 0 || status2 == 0 && status1 != 0) {
return 1;
}
return 0;
});
sortUsers(objects);
} else if (type == TYPE_ADMIN) {
Collections.sort(participants, (lhs, rhs) -> {
int type1 = getChannelAdminParticipantType(lhs);
int type2 = getChannelAdminParticipantType(rhs);
if (type1 > type2) {
return 1;
} else if (type1 < type2) {
return -1;
}
return 0;
});
sortAdmins(participants);
}
} catch (Exception e) {
FileLog.e(e);
}
}
if (type != TYPE_USERS || delayResults <= 0) {
showItemsAnimated(listViewAdapter != null ? listViewAdapter.getItemCount() : 0);
loadingUsers = false;
firstLoaded = true;
showItemsAnimated(listViewAdapter != null ? listViewAdapter.getItemCount() : 0);
}
updateRows();
if (listViewAdapter != null) {
listView.setAnimateEmptyView(openTransitionStarted, 0);
listViewAdapter.notifyDataSetChanged();
if (emptyView != null && listViewAdapter.getItemCount() == 0 && firstLoaded) {
emptyView.showProgress(false, true);
}
}
resumeDelayedFragmentAnimation();
}));
getConnectionsManager().bindRequestToGuid(reqId, classGuid);
}
}
private void sortUsers(ArrayList<TLObject> objects) {
int currentTime = getConnectionsManager().getCurrentTime();
Collections.sort(objects, (lhs, rhs) -> {
TLRPC.ChannelParticipant p1 = (TLRPC.ChannelParticipant) lhs;
TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) rhs;
TLRPC.User user1 = getMessagesController().getUser(p1.user_id);
TLRPC.User user2 = getMessagesController().getUser(p2.user_id);
int status1 = 0;
int status2 = 0;
if (user1 != null && user1.status != null) {
if (user1.self) {
status1 = currentTime + 50000;
} else {
status1 = user1.status.expires;
}
}
if (user2 != null && user2.status != null) {
if (user2.self) {
status2 = currentTime + 50000;
} else {
status2 = user2.status.expires;
}
}
if (status1 > 0 && status2 > 0) {
if (status1 > status2) {
return 1;
} else if (status1 < status2) {
return -1;
}
return 0;
} else if (status1 < 0 && status2 < 0) {
if (status1 > status2) {
return 1;
} else if (status1 < status2) {
return -1;
}
return 0;
} else if (status1 < 0 && status2 > 0 || status1 == 0 && status2 != 0) {
return -1;
} else if (status2 < 0 && status1 > 0 || status2 == 0 && status1 != 0) {
return 1;
}
return 0;
});
}
@Override
public void onResume() {
super.onResume();
@ -2167,10 +2322,18 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
return selectType;
}
// @Override
// protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
// super.onTransitionAnimationStart(isOpen, backward);
// if (isOpen) {
// openTransitionStarted = true;
// }
// }
@Override
protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
if (isOpen) {
openTransitionEnded = true;
openTransitionStarted = true;
}
if (isOpen && !backward && needOpenSearch) {
searchItem.getSearchField().requestFocus();
@ -2409,6 +2572,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
globalStartRow = -1;
}
if (searching && listView != null && listView.getAdapter() != searchListViewAdapter) {
listView.setAnimateEmptyView(true, 0);
listView.setAdapter(searchListViewAdapter);
listView.setFastScrollVisible(false);
listView.setVerticalScrollBarEnabled(true);
@ -2652,9 +2816,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
@Override
public int getItemCount() {
if (type == TYPE_KICKED && loadingUsers && !firstLoaded) {
/* if (type == TYPE_KICKED && loadingUsers && !firstLoaded) {
return 0;
}
}*/
return rowCount;
}
@ -2672,27 +2836,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
view = manageChatUserCell;
break;
case 1:
view = new TextInfoPrivacyCell(mContext) {
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundGray));
super.dispatchDraw(canvas);
}
};
view = new TextInfoPrivacyCell(mContext);
break;
case 2:
view = new ManageChatTextCell(mContext);
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
break;
case 3:
view = new ShadowSectionCell(mContext) {
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundGray));
super.dispatchDraw(canvas);
}
};
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
view = new ShadowSectionCell(mContext);
break;
case 4:
view = new FrameLayout(mContext) {
@ -2701,12 +2852,6 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - AndroidUtilities.dp(56), MeasureSpec.EXACTLY));
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundGray));
super.dispatchDraw(canvas);
}
};
FrameLayout frameLayout = (FrameLayout) view;
frameLayout.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
@ -2758,28 +2903,20 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
break;
case 8:
view = new GraySectionCell(mContext);
view.setBackground(null);
break;
case 10:
view = new LoadingCell(mContext, AndroidUtilities.dp(40), AndroidUtilities.dp(120));
break;
case 11:
view = new View(mContext) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int h = 0;
for (int i = 0; i < listView.getChildCount(); i++) {
if (listView.getChildAt(i) != this) {
h += listView.getChildAt(i).getMeasuredHeight();
}
}
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), Math.max(0, listView.getMeasuredHeight() - h));
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundGray));
}
};
FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext);
flickerLoadingView.setIsSingleCell(true);
flickerLoadingView.setViewType(FlickerLoadingView.USERS_TYPE);
flickerLoadingView.showDate(false);
flickerLoadingView.setPaddingLeft(AndroidUtilities.dp(5));
flickerLoadingView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
flickerLoadingView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
view = flickerLoadingView;
break;
case 9:
default:
@ -3031,6 +3168,16 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
} else {
sectionCell.setText(LocaleController.getString("GroupContacts", R.string.GroupContacts));
}
} else if (position == loadingHeaderRow) {
sectionCell.setText("");
}
break;
case 11:
FlickerLoadingView flickerLoadingView = (FlickerLoadingView) holder.itemView;
if (type == TYPE_BANNED) {
flickerLoadingView.setItemsCount(info == null ? 1 : info.kicked_count);
} else {
flickerLoadingView.setItemsCount(1);
}
break;
}
@ -3064,13 +3211,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
} else if (position == changeInfoRow || position == addUsersRow || position == pinMessagesRow || position == sendMessagesRow ||
position == sendMediaRow || position == sendStickersRow || position == embedLinksRow || position == sendPollsRow) {
return 7;
} else if (position == membersHeaderRow || position == contactsHeaderRow || position == botHeaderRow) {
} else if (position == membersHeaderRow || position == contactsHeaderRow || position == botHeaderRow || position == loadingHeaderRow) {
return 8;
} else if (position == slowmodeSelectRow) {
return 9;
} else if (position == loadingProgressRow) {
return 10;
} else if (position == lastEmptyViewRow) {
} else if (position == loadingUserCellRow) {
return 11;
}
return 0;
@ -3088,6 +3235,143 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
}
}
public DiffCallback saveState() {
DiffCallback diffCallback = new DiffCallback();
diffCallback.oldRowCount = rowCount;
diffCallback.oldBotStartRow = botStartRow;
diffCallback.oldBotEndRow = botEndRow;
diffCallback.oldBots.clear();
diffCallback.oldBots.addAll(bots);
diffCallback.oldContactsEndRow = contactsEndRow;
diffCallback.oldContactsStartRow = contactsStartRow;
diffCallback.oldContacts.clear();
diffCallback.oldContacts.addAll(contacts);
diffCallback.oldParticipantsStartRow = participantsStartRow;
diffCallback.oldParticipantsEndRow = participantsEndRow;
diffCallback.oldParticipants.clear();
diffCallback.oldParticipants.addAll(participants);
diffCallback.fillPositions(diffCallback.oldPositionToItem);
return diffCallback;
}
public void updateListAnimated(DiffCallback savedState) {
if (listViewAdapter == null) {
updateRows();
return;
}
updateRows();
savedState.fillPositions(savedState.newPositionToItem);
DiffUtil.calculateDiff(savedState).dispatchUpdatesTo(listViewAdapter);
if (listView != null && layoutManager != null && listView.getChildCount() > 0) {
View view = null;
int position = -1;
for (int i = 0; i < listView.getChildCount(); i++) {
position = listView.getChildAdapterPosition(listView.getChildAt(i));
if (position != RecyclerListView.NO_POSITION) {
view = listView.getChildAt(i);
break;
}
}
if (view != null) {
layoutManager.scrollToPositionWithOffset(position, view.getTop() - listView.getPaddingTop());
}
}
}
private class DiffCallback extends DiffUtil.Callback {
int oldRowCount;
SparseIntArray oldPositionToItem = new SparseIntArray();
SparseIntArray newPositionToItem = new SparseIntArray();
int oldParticipantsStartRow;
int oldParticipantsEndRow;
int oldContactsStartRow;
int oldContactsEndRow;
int oldBotStartRow;
int oldBotEndRow;
private ArrayList<TLObject> oldParticipants = new ArrayList<>();
private ArrayList<TLObject> oldBots = new ArrayList<>();
private ArrayList<TLObject> oldContacts = new ArrayList<>();
@Override
public int getOldListSize() {
return oldRowCount;
}
@Override
public int getNewListSize() {
return rowCount;
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
if (oldItemPosition >= oldBotStartRow && oldItemPosition < oldBotEndRow && newItemPosition >= botStartRow && newItemPosition < botEndRow) {
return oldBots.get(oldItemPosition - oldBotStartRow).equals(bots.get(newItemPosition - botStartRow));
} else if (oldItemPosition >= oldContactsStartRow && oldItemPosition < oldContactsEndRow && newItemPosition >= contactsStartRow && newItemPosition < contactsEndRow) {
return oldContacts.get(oldItemPosition - oldContactsStartRow).equals(contacts.get(newItemPosition - contactsStartRow));
} else if (oldItemPosition >= oldParticipantsStartRow && oldItemPosition < oldParticipantsEndRow && newItemPosition >= participantsStartRow && newItemPosition < participantsEndRow) {
return oldParticipants.get(oldItemPosition - oldParticipantsStartRow).equals(participants.get(newItemPosition - participantsStartRow));
}
return oldPositionToItem.get(oldItemPosition) == newPositionToItem.get(newItemPosition);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
if (areItemsTheSame(oldItemPosition, newItemPosition)) {
if (restricted1SectionRow == newItemPosition) {
return false;
}
return true;
}
return false;
}
public void fillPositions(SparseIntArray sparseIntArray) {
sparseIntArray.clear();
int pointer = 0;
put(++pointer, recentActionsRow, sparseIntArray);
put(++pointer, addNewRow, sparseIntArray);
put(++pointer, addNew2Row, sparseIntArray);
put(++pointer, addNewSectionRow, sparseIntArray);
put(++pointer, restricted1SectionRow, sparseIntArray);
put(++pointer, participantsDividerRow, sparseIntArray);
put(++pointer, participantsDivider2Row, sparseIntArray);
put(++pointer, participantsInfoRow, sparseIntArray);
put(++pointer, blockedEmptyRow, sparseIntArray);
put(++pointer, permissionsSectionRow, sparseIntArray);
put(++pointer, sendMessagesRow, sparseIntArray);
put(++pointer, sendMediaRow, sparseIntArray);
put(++pointer, sendStickersRow, sparseIntArray);
put(++pointer, sendPollsRow, sparseIntArray);
put(++pointer, embedLinksRow, sparseIntArray);
put(++pointer, addUsersRow, sparseIntArray);
put(++pointer, pinMessagesRow, sparseIntArray);
put(++pointer, changeInfoRow, sparseIntArray);
put(++pointer, removedUsersRow, sparseIntArray);
put(++pointer, contactsHeaderRow, sparseIntArray);
put(++pointer, botHeaderRow, sparseIntArray);
put(++pointer, membersHeaderRow, sparseIntArray);
put(++pointer, slowmodeRow, sparseIntArray);
put(++pointer, slowmodeSelectRow, sparseIntArray);
put(++pointer, slowmodeInfoRow, sparseIntArray);
put(++pointer, loadingProgressRow, sparseIntArray);
put(++pointer, loadingUserCellRow, sparseIntArray);
put(++pointer, loadingHeaderRow, sparseIntArray);
}
private void put(int id, int position, SparseIntArray sparseIntArray) {
if (position >= 0) {
sparseIntArray.put(position, id);
}
}
}
@Override
public ArrayList<ThemeDescription> getThemeDescriptions() {
ArrayList<ThemeDescription> themeDescriptions = new ArrayList<>();

View File

@ -113,7 +113,35 @@ public class AlertsCreator {
if (error.code == 406 || error.text == null) {
return null;
}
if (request instanceof TLRPC.TL_account_saveSecureValue || request instanceof TLRPC.TL_account_getAuthorizationForm) {
if (request instanceof TLRPC.TL_messages_initHistoryImport || request instanceof TLRPC.TL_messages_checkHistoryImport || request instanceof TLRPC.TL_messages_startHistoryImport) {
TLRPC.InputPeer peer;
if (request instanceof TLRPC.TL_messages_initHistoryImport) {
peer = ((TLRPC.TL_messages_initHistoryImport) request).peer;
} else if (request instanceof TLRPC.TL_messages_startHistoryImport) {
peer = ((TLRPC.TL_messages_startHistoryImport) request).peer;
} else {
peer = null;
}
if (error.text.contains("USER_IS_BLOCKED")) {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ImportErrorUserBlocked", R.string.ImportErrorUserBlocked));
} else if (error.text.contains("USER_NOT_MUTUAL_CONTACT")) {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ImportMutualError", R.string.ImportMutualError));
} else if (error.text.contains("IMPORT_PEER_TYPE_INVALID")) {
if (peer instanceof TLRPC.TL_inputPeerUser) {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ImportErrorChatInvalidUser", R.string.ImportErrorChatInvalidUser));
} else {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ImportErrorChatInvalidGroup", R.string.ImportErrorChatInvalidGroup));
}
} else if (error.text.contains("CHAT_ADMIN_REQUIRED")) {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ImportErrorNotAdmin", R.string.ImportErrorNotAdmin));
} else if (error.text.startsWith("IMPORT_FORMAT")) {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ImportErrorFileFormatInvalid", R.string.ImportErrorFileFormatInvalid));
} else if (error.text.contains("IMPORT_LANG_NOT_FOUND")) {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ImportErrorFileLang", R.string.ImportErrorFileLang));
} else {
showSimpleAlert(fragment, LocaleController.getString("ImportErrorTitle", R.string.ImportErrorTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text);
}
} else if (request instanceof TLRPC.TL_account_saveSecureValue || request instanceof TLRPC.TL_account_getAuthorizationForm) {
if (error.text.contains("PHONE_NUMBER_INVALID")) {
showSimpleAlert(fragment, LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber));
} else if (error.text.startsWith("FLOOD_WAIT")) {
@ -1044,11 +1072,97 @@ public class AlertsCreator {
}
}
public static void createClearOrDeleteDialogAlert(BaseFragment fragment, boolean clear, TLRPC.Chat chat, TLRPC.User user, boolean secret, MessagesStorage.BooleanCallback onProcessRunnable) {
createClearOrDeleteDialogAlert(fragment, clear, false, false, chat, user, secret, onProcessRunnable);
public static void createImportDialogAlert(BaseFragment fragment, String title, TLRPC.User user, TLRPC.Chat chat, Runnable onProcessRunnable) {
if (fragment == null || fragment.getParentActivity() == null || chat == null && user == null) {
return;
}
int account = fragment.getCurrentAccount();
Context context = fragment.getParentActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
int selfUserId = UserConfig.getInstance(account).getClientUserId();
TextView messageTextView = new TextView(context);
messageTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
messageTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
FrameLayout frameLayout = new FrameLayout(context);
builder.setView(frameLayout);
AvatarDrawable avatarDrawable = new AvatarDrawable();
avatarDrawable.setTextSize(AndroidUtilities.dp(12));
BackupImageView imageView = new BackupImageView(context);
imageView.setRoundRadius(AndroidUtilities.dp(20));
frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 22, 5, 22, 0));
TextView textView = new TextView(context);
textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setLines(1);
textView.setMaxLines(1);
textView.setSingleLine(true);
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setText(LocaleController.formatString("ImportMessages", R.string.ImportMessages));
frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 11, (LocaleController.isRTL ? 76 : 21), 0));
frameLayout.addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 57, 24, 9));
if (user != null) {
if (UserObject.isReplyUser(user)) {
avatarDrawable.setSmallSize(true);
avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_REPLIES);
imageView.setImage(null, null, avatarDrawable, user);
} else if (user.id == selfUserId) {
avatarDrawable.setSmallSize(true);
avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED);
imageView.setImage(null, null, avatarDrawable, user);
} else {
avatarDrawable.setSmallSize(false);
avatarDrawable.setInfo(user);
imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user);
}
} else {
avatarDrawable.setInfo(chat);
imageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat);
}
if (chat != null) {
if (TextUtils.isEmpty(title)) {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ImportToChatNoTitle", R.string.ImportToChatNoTitle, chat.title)));
} else {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ImportToChat", R.string.ImportToChat, title, chat.title)));
}
} else {
if (TextUtils.isEmpty(title)) {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ImportToUserNoTitle", R.string.ImportToUserNoTitle, ContactsController.formatName(user.first_name, user.last_name))));
} else {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ImportToUser", R.string.ImportToUser, title, ContactsController.formatName(user.first_name, user.last_name))));
}
}
builder.setPositiveButton(LocaleController.getString("Import", R.string.Import), (dialogInterface, i) -> {
if (onProcessRunnable != null) {
onProcessRunnable.run();
}
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
AlertDialog alertDialog = builder.create();
fragment.showDialog(alertDialog);
}
public static void createClearOrDeleteDialogAlert(BaseFragment fragment, boolean clear, boolean admin, boolean second, TLRPC.Chat chat, TLRPC.User user, boolean secret, MessagesStorage.BooleanCallback onProcessRunnable) {
public static void createClearOrDeleteDialogAlert(BaseFragment fragment, boolean clear, TLRPC.Chat chat, TLRPC.User user, boolean secret, MessagesStorage.BooleanCallback onProcessRunnable) {
createClearOrDeleteDialogAlert(fragment, clear, false, false, chat, user, secret, false, onProcessRunnable);
}
public static void createClearOrDeleteDialogAlert(BaseFragment fragment, boolean clear, TLRPC.Chat chat, TLRPC.User user, boolean secret, boolean checkDeleteForAll, MessagesStorage.BooleanCallback onProcessRunnable) {
createClearOrDeleteDialogAlert(fragment, clear, chat != null && chat.creator, false, chat, user, secret, checkDeleteForAll, onProcessRunnable);
}
public static void createClearOrDeleteDialogAlert(BaseFragment fragment, boolean clear, boolean admin, boolean second, TLRPC.Chat chat, TLRPC.User user, boolean secret, boolean checkDeleteForAll, MessagesStorage.BooleanCallback onProcessRunnable) {
if (fragment == null || fragment.getParentActivity() == null || chat == null && user == null) {
return;
}
@ -1139,11 +1253,16 @@ public class AlertsCreator {
}
boolean canDeleteInbox = !secret && user != null && canRevokeInbox && revokeTimeLimit == 0x7fffffff;
final boolean[] deleteForAll = new boolean[1];
boolean deleteGroupForAll = false;
if (!second && canDeleteInbox && !UserObject.isDeleted(user)) {
if (!second && (secret || canDeleteInbox) && !UserObject.isDeleted(user) || (deleteGroupForAll = checkDeleteForAll && !clear && chat != null && chat.creator && (!ChatObject.isChannel(chat) || chat.megagroup))) {
cell[0] = new CheckBoxCell(context, 1);
cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false));
if (clear) {
if (secret) {
cell[0].setText(LocaleController.formatString("DeleteForUser", R.string.DeleteForUser, UserObject.getFirstName(user)), "", false, false);
} else if (deleteGroupForAll) {
cell[0].setText(LocaleController.getString("DeleteGroupForAll", R.string.DeleteGroupForAll), "", false, false);
} else if (clear) {
cell[0].setText(LocaleController.formatString("ClearHistoryOptionAlso", R.string.ClearHistoryOptionAlso, UserObject.getFirstName(user)), "", false, false);
} else {
cell[0].setText(LocaleController.formatString("DeleteMessagesOptionAlso", R.string.DeleteMessagesOptionAlso, UserObject.getFirstName(user)), "", false, false);
@ -1207,7 +1326,7 @@ public class AlertsCreator {
if (admin) {
if (ChatObject.isChannel(chat)) {
if (chat.megagroup) {
messageTextView.setText(LocaleController.getString("MegaDeleteAlert", R.string.MegaDeleteAlert));
messageTextView.setText(LocaleController.getString("AreYouSureDeleteAndExit", R.string.AreYouSureDeleteAndExit));
} else {
messageTextView.setText(LocaleController.getString("ChannelDeleteAlert", R.string.ChannelDeleteAlert));
}
@ -1277,14 +1396,14 @@ public class AlertsCreator {
}
}
builder.setPositiveButton(actionText, (dialogInterface, i) -> {
if (!clearingCache && !second) {
if (!clearingCache && !second && !secret) {
if (UserObject.isUserSelf(user)) {
createClearOrDeleteDialogAlert(fragment, clear, admin, true, chat, user, secret, onProcessRunnable);
createClearOrDeleteDialogAlert(fragment, clear, admin, true, chat, user, false, checkDeleteForAll, onProcessRunnable);
return;
} else if (user != null && deleteForAll[0]) {
MessagesStorage.getInstance(fragment.getCurrentAccount()).getMessagesCount(user.id, (count) -> {
if (count >= 50) {
createClearOrDeleteDialogAlert(fragment, clear, admin, true, chat, user, secret, onProcessRunnable);
createClearOrDeleteDialogAlert(fragment, clear, admin, true, chat, user, false, checkDeleteForAll, onProcessRunnable);
} else {
if (onProcessRunnable != null) {
onProcessRunnable.run(deleteForAll[0]);
@ -1824,6 +1943,188 @@ public class AlertsCreator {
return builder;
}
public static BottomSheet.Builder createDatePickerDialog(Context context, long currentDate, final ScheduleDatePickerDelegate datePickerDelegate) {
if (context == null) {
return null;
}
ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors();
BottomSheet.Builder builder = new BottomSheet.Builder(context, false);
builder.setApplyBottomPadding(false);
final NumberPicker dayPicker = new NumberPicker(context);
dayPicker.setTextColor(datePickerColors.textColor);
dayPicker.setTextOffset(AndroidUtilities.dp(10));
dayPicker.setItemCount(5);
final NumberPicker hourPicker = new NumberPicker(context) {
@Override
protected CharSequence getContentDescription(int value) {
return LocaleController.formatPluralString("Hours", value);
}
};
hourPicker.setItemCount(5);
hourPicker.setTextColor(datePickerColors.textColor);
hourPicker.setTextOffset(-AndroidUtilities.dp(10));
final NumberPicker minutePicker = new NumberPicker(context) {
@Override
protected CharSequence getContentDescription(int value) {
return LocaleController.formatPluralString("Minutes", value);
}
};
minutePicker.setItemCount(5);
minutePicker.setTextColor(datePickerColors.textColor);
minutePicker.setTextOffset(-AndroidUtilities.dp(34));
LinearLayout container = new LinearLayout(context) {
boolean ignoreLayout = false;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
ignoreLayout = true;
int count;
if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) {
count = 3;
} else {
count = 5;
}
dayPicker.setItemCount(count);
hourPicker.setItemCount(count);
minutePicker.setItemCount(count);
dayPicker.getLayoutParams().height = AndroidUtilities.dp(54) * count;
hourPicker.getLayoutParams().height = AndroidUtilities.dp(54) * count;
minutePicker.getLayoutParams().height = AndroidUtilities.dp(54) * count;
ignoreLayout = false;
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public void requestLayout() {
if (ignoreLayout) {
return;
}
super.requestLayout();
}
};
container.setOrientation(LinearLayout.VERTICAL);
FrameLayout titleLayout = new FrameLayout(context);
container.addView(titleLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 22, 0, 0, 4));
TextView titleView = new TextView(context);
titleView.setText(LocaleController.getString("ExpireAfter", R.string.ExpireAfter));
titleView.setTextColor(datePickerColors.textColor);
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 12, 0, 0));
titleView.setOnTouchListener((v, event) -> true);
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.setWeightSum(1.0f);
container.addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
long currentTime = System.currentTimeMillis();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(currentTime);
int currentYear = calendar.get(Calendar.YEAR);
TextView buttonTextView = new TextView(context) {
@Override
public CharSequence getAccessibilityClassName() {
return Button.class.getName();
}
};
linearLayout.addView(dayPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f));
dayPicker.setMinValue(0);
dayPicker.setMaxValue(365);
dayPicker.setWrapSelectorWheel(false);
dayPicker.setFormatter(value -> {
if (value == 0) {
return LocaleController.getString("MessageScheduleToday", R.string.MessageScheduleToday);
} else {
long date = currentTime + (long) value * 86400000L;
calendar.setTimeInMillis(date);
int year = calendar.get(Calendar.YEAR);
if (year == currentYear) {
return LocaleController.getInstance().formatterScheduleDay.format(date);
} else {
return LocaleController.getInstance().formatterScheduleYear.format(date);
}
}
});
final NumberPicker.OnValueChangeListener onValueChangeListener = (picker, oldVal, newVal) -> {
try {
container.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
} catch (Exception ignore) {
}
checkScheduleDate(null, false, dayPicker, hourPicker, minutePicker);
};
dayPicker.setOnValueChangedListener(onValueChangeListener);
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
linearLayout.addView(hourPicker, LayoutHelper.createLinear(0, 54 * 5, 0.2f));
hourPicker.setFormatter(value -> String.format("%02d", value));
hourPicker.setOnValueChangedListener(onValueChangeListener);
minutePicker.setMinValue(0);
minutePicker.setMaxValue(59);
minutePicker.setValue(0);
minutePicker.setFormatter(value -> String.format("%02d", value));
linearLayout.addView(minutePicker, LayoutHelper.createLinear(0, 54 * 5, 0.3f));
minutePicker.setOnValueChangedListener(onValueChangeListener);
if (currentDate > 0 && currentDate != 0x7FFFFFFE) {
currentDate *= 1000;
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
int days = (int) ((currentDate - calendar.getTimeInMillis()) / (24 * 60 * 60 * 1000));
calendar.setTimeInMillis(currentDate);
if (days >= 0) {
minutePicker.setValue(calendar.get(Calendar.MINUTE));
hourPicker.setValue(calendar.get(Calendar.HOUR_OF_DAY));
dayPicker.setValue(days);
}
}
final boolean[] canceled = {true};
checkScheduleDate(null, false, dayPicker, hourPicker, minutePicker);
buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0);
buttonTextView.setGravity(Gravity.CENTER);
buttonTextView.setTextColor(datePickerColors.buttonTextColor);
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), datePickerColors.buttonBackgroundColor, datePickerColors.buttonBackgroundPressedColor));
buttonTextView.setText(LocaleController.getString("SetTimeLimit", R.string.SetTimeLimit));
container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16));
buttonTextView.setOnClickListener(v -> {
canceled[0] = false;
boolean setSeconds = checkScheduleDate(null, false, dayPicker, hourPicker, minutePicker);
calendar.setTimeInMillis(System.currentTimeMillis() + (long) dayPicker.getValue() * 24 * 3600 * 1000);
calendar.set(Calendar.HOUR_OF_DAY, hourPicker.getValue());
calendar.set(Calendar.MINUTE, minutePicker.getValue());
if (setSeconds) {
calendar.set(Calendar.SECOND, 0);
}
datePickerDelegate.didSelectDate(true, (int) (calendar.getTimeInMillis() / 1000));
builder.getDismissRunnable().run();
});
builder.setCustomView(container);
BottomSheet bottomSheet = builder.show();
bottomSheet.setBackgroundColor(datePickerColors.backgroundColor);
return builder;
}
private static void checkCalendarDate(long minDate, NumberPicker dayPicker, NumberPicker monthPicker, NumberPicker yearPicker) {
int day = dayPicker.getValue();
int month = monthPicker.getValue();
@ -2099,13 +2400,25 @@ public class AlertsCreator {
BottomSheet.Builder builder = new BottomSheet.Builder(context);
builder.setTitle(LocaleController.getString("ReportChat", R.string.ReportChat), true);
CharSequence[] items = new CharSequence[]{
LocaleController.getString("ReportChatSpam", R.string.ReportChatSpam),
LocaleController.getString("ReportChatViolence", R.string.ReportChatViolence),
LocaleController.getString("ReportChatChild", R.string.ReportChatChild),
LocaleController.getString("ReportChatPornography", R.string.ReportChatPornography),
LocaleController.getString("ReportChatOther", R.string.ReportChatOther)
};
CharSequence[] items;
if (messageId != 0) {
items = new CharSequence[]{
LocaleController.getString("ReportChatSpam", R.string.ReportChatSpam),
LocaleController.getString("ReportChatViolence", R.string.ReportChatViolence),
LocaleController.getString("ReportChatChild", R.string.ReportChatChild),
LocaleController.getString("ReportChatPornography", R.string.ReportChatPornography),
LocaleController.getString("ReportChatOther", R.string.ReportChatOther)
};
} else {
items = new CharSequence[]{
LocaleController.getString("ReportChatSpam", R.string.ReportChatSpam),
LocaleController.getString("ReportChatFakeAccount", R.string.ReportChatFakeAccount),
LocaleController.getString("ReportChatViolence", R.string.ReportChatViolence),
LocaleController.getString("ReportChatChild", R.string.ReportChatChild),
LocaleController.getString("ReportChatPornography", R.string.ReportChatPornography),
LocaleController.getString("ReportChatOther", R.string.ReportChatOther)
};
}
builder.setItems(items, (dialogInterface, i) -> {
if (i == 4) {
Bundle args = new Bundle();
@ -2136,10 +2449,12 @@ public class AlertsCreator {
if (i == 0) {
request.reason = new TLRPC.TL_inputReportReasonSpam();
} else if (i == 1) {
request.reason = new TLRPC.TL_inputReportReasonViolence();
request.reason = new TLRPC.TL_inputReportReasonFake();
} else if (i == 2) {
request.reason = new TLRPC.TL_inputReportReasonChildAbuse();
request.reason = new TLRPC.TL_inputReportReasonViolence();
} else if (i == 3) {
request.reason = new TLRPC.TL_inputReportReasonChildAbuse();
} else if (i == 4) {
request.reason = new TLRPC.TL_inputReportReasonPornography();
}
req = request;

View File

@ -33,18 +33,13 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
@ -52,6 +47,13 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.C;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildConfig;
@ -162,6 +164,58 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
private int TAG;
private LaunchActivity parentActivity;
int rewindingState;
float rewindingProgress = -1;
int rewindingForwardPressedCount;
long lastRewindingTime;
long lastUpdateRewindingPlayerTime;
private final Runnable forwardSeek = new Runnable() {
@Override
public void run() {
long duration = MediaController.getInstance().getDuration();
if (duration == 0 || duration == C.TIME_UNSET) {
lastRewindingTime = System.currentTimeMillis();
return;
}
float currentProgress = rewindingProgress;
long t = System.currentTimeMillis();
long dt = t - lastRewindingTime;
lastRewindingTime = t;
long updateDt = t - lastUpdateRewindingPlayerTime;
if (rewindingForwardPressedCount == 1) {
dt = dt * 3 - dt;
} else if (rewindingForwardPressedCount == 2) {
dt = dt * 6 - dt;
} else {
dt = dt * 12 - dt;
}
long currentTime = (long) (duration * currentProgress + dt);
currentProgress = currentTime / (float) duration;
if (currentProgress < 0) {
currentProgress = 0;
}
rewindingProgress = currentProgress;
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
if (messageObject != null && messageObject.isMusic()) {
if (!MediaController.getInstance().isMessagePaused()) {
MediaController.getInstance().getPlayingMessageObject().audioProgress = rewindingProgress;
}
updateProgress(messageObject);
}
if (rewindingState == 1 && rewindingForwardPressedCount > 0 && MediaController.getInstance().isMessagePaused()) {
if (updateDt > 200 || rewindingProgress == 0) {
lastUpdateRewindingPlayerTime = t;
MediaController.getInstance().seekToProgress(MediaController.getInstance().getPlayingMessageObject(), currentProgress);
}
if (rewindingForwardPressedCount > 0 && rewindingProgress > 0) {
AndroidUtilities.runOnUIThread(forwardSeek, 16);
}
}
}
};
public AudioPlayerAlert(final Context context) {
super(context, true);
@ -524,12 +578,43 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setSingleLine(true);
textView.setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), AndroidUtilities.dp(1));
textView.setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector), AndroidUtilities.dp(4), AndroidUtilities.dp(4)));
textView.setOnClickListener(view -> {
int dialogsCount = MessagesController.getInstance(currentAccount).getTotalDialogsCount();
if (dialogsCount <= 10) {
return;
}
String query = (String) textView.getText();
if (parentActivity.getActionBarLayout().getLastFragment() instanceof DialogsActivity) {
DialogsActivity dialogsActivity = (DialogsActivity) parentActivity.getActionBarLayout().getLastFragment();
if (!dialogsActivity.onlyDialogsAdapter()) {
dialogsActivity.setShowSearch(query, 4);
dismiss();
return;
}
}
DialogsActivity fragment = new DialogsActivity(null);
fragment.setSearchString(query);
fragment.setInitialSearchType(4);
parentActivity.presentFragment(fragment, false, false);
dismiss();
});
return textView;
}
};
playerLayout.addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 20, 47, 72, 0));
playerLayout.addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 14, 47, 72, 0));
seekBarView = new SeekBarView(context);
seekBarView = new SeekBarView(context) {
@Override
boolean onTouch(MotionEvent ev) {
if (rewindingState != 0) {
return false;
}
return super.onTouch(ev);
}
};
seekBarView.setDelegate(new SeekBarView.SeekBarViewDelegate() {
@Override
public void onSeekBarDrag(boolean stop, float progress) {
@ -659,8 +744,135 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
});
final int iconColor = Theme.getColor(Theme.key_player_button);
float touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
buttons[1] = prevButton = new RLottieImageView(context);
buttons[1] = prevButton = new RLottieImageView(context) {
float startX;
float startY;
int pressedCount = 0;
long lastTime;
long lastUpdateTime;
private final Runnable pressedRunnable = new Runnable() {
@Override
public void run() {
pressedCount++;
if (pressedCount == 1) {
rewindingState = -1;
rewindingProgress = MediaController.getInstance().getPlayingMessageObject().audioProgress;
lastTime = System.currentTimeMillis();
AndroidUtilities.runOnUIThread(this, 2000);
AndroidUtilities.runOnUIThread(backSeek);
} else if (pressedCount == 2) {
AndroidUtilities.runOnUIThread(this, 2000);
}
}
};
private final Runnable backSeek = new Runnable() {
@Override
public void run() {
long duration = MediaController.getInstance().getDuration();
if (duration == 0 || duration == C.TIME_UNSET) {
lastTime = System.currentTimeMillis();
return;
}
float currentProgress = rewindingProgress;
long t = System.currentTimeMillis();
long dt = t - lastTime;
lastTime = t;
long updateDt = t - lastUpdateTime;
if (pressedCount == 1) {
dt *= 3;
} else if (pressedCount == 2) {
dt *= 6;
} else {
dt *= 12;
}
long currentTime = (long) (duration * currentProgress - dt);
currentProgress = currentTime / (float) duration;
if (currentProgress < 0) {
currentProgress = 0;
}
rewindingProgress = currentProgress;
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
if (messageObject != null && messageObject.isMusic()) {
updateProgress(messageObject);
}
if (rewindingState == -1 && pressedCount > 0) {
if (updateDt > 200 || rewindingProgress == 0) {
lastUpdateTime = t;
if (rewindingProgress == 0) {
MediaController.getInstance().seekToProgress(MediaController.getInstance().getPlayingMessageObject(), 0);
MediaController.getInstance().pauseByRewind();
} else {
MediaController.getInstance().seekToProgress(MediaController.getInstance().getPlayingMessageObject(), currentProgress);
}
}
if (pressedCount > 0 && rewindingProgress > 0) {
AndroidUtilities.runOnUIThread(backSeek, 16);
}
}
}
};
long startTime;
@Override
public boolean onTouchEvent(MotionEvent event) {
if (seekBarView.isDragging() || rewindingState == 1) {
return false;
}
float x = event.getRawX();
float y = event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = x;
startY = y;
startTime = System.currentTimeMillis();
rewindingState = 0;
AndroidUtilities.runOnUIThread(pressedRunnable, 300);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && getBackground() != null) {
getBackground().setHotspot(startX, startY);
}
setPressed(true);
break;
case MotionEvent.ACTION_MOVE:
float dx = x - startX;
float dy = y - startY;
if ((dx * dx + dy * dy) > touchSlop * touchSlop && rewindingState == 0) {
AndroidUtilities.cancelRunOnUIThread(pressedRunnable);
setPressed(false);
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
AndroidUtilities.cancelRunOnUIThread(pressedRunnable);
AndroidUtilities.cancelRunOnUIThread(backSeek);
if (rewindingState == 0 && event.getAction() == MotionEvent.ACTION_UP && (System.currentTimeMillis() - startTime < 300)) {
MediaController.getInstance().playPreviousMessage();
prevButton.setProgress(0f);
prevButton.playAnimation();
}
if (pressedCount > 0) {
lastUpdateTime = 0;
backSeek.run();
MediaController.getInstance().resumeByRewind();
}
rewindingProgress = -1;
setPressed(false);
rewindingState = 0;
pressedCount = 0;
break;
}
return true;
}
};
prevButton.setScaleType(ImageView.ScaleType.CENTER);
prevButton.setAnimation(R.raw.player_prev, 20, 20);
prevButton.setLayerColor("Triangle 3.**", iconColor);
@ -670,11 +882,6 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
prevButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 1, AndroidUtilities.dp(22)));
}
bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
prevButton.setOnClickListener(v -> {
MediaController.getInstance().playPreviousMessage();
prevButton.setProgress(0f);
prevButton.playAnimation();
});
prevButton.setContentDescription(LocaleController.getString("AccDescrPrevious", R.string.AccDescrPrevious));
buttons[2] = playButton = new ImageView(context);
@ -697,7 +904,92 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
}
});
buttons[3] = nextButton = new RLottieImageView(context);
buttons[3] = nextButton = new RLottieImageView(context) {
float startX;
float startY;
boolean pressed;
private final Runnable pressedRunnable = new Runnable() {
@Override
public void run() {
if (MediaController.getInstance().getPlayingMessageObject() == null) {
return;
}
rewindingForwardPressedCount++;
if (rewindingForwardPressedCount == 1) {
pressed = true;
rewindingState = 1;
if (MediaController.getInstance().isMessagePaused()) {
startForwardRewindingSeek();
} else if (rewindingState == 1) {
AndroidUtilities.cancelRunOnUIThread(forwardSeek);
lastUpdateRewindingPlayerTime = 0;
}
MediaController.getInstance().setPlaybackSpeed(true, 4);
AndroidUtilities.runOnUIThread(this, 2000);
} else if (rewindingForwardPressedCount == 2) {
MediaController.getInstance().setPlaybackSpeed(true, 7);
AndroidUtilities.runOnUIThread(this, 2000);
} else {
MediaController.getInstance().setPlaybackSpeed(true, 13);
}
}
};
@Override
public boolean onTouchEvent(MotionEvent event) {
if (seekBarView.isDragging() || rewindingState == -1) {
return false;
}
float x = event.getRawX();
float y = event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
pressed = false;
startX = x;
startY = y;
AndroidUtilities.runOnUIThread(pressedRunnable, 300);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && getBackground() != null) {
getBackground().setHotspot(startX, startY);
}
setPressed(true);
break;
case MotionEvent.ACTION_MOVE:
float dx = x - startX;
float dy = y - startY;
if ((dx * dx + dy * dy) > touchSlop * touchSlop && !pressed) {
AndroidUtilities.cancelRunOnUIThread(pressedRunnable);
setPressed(false);
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (!pressed && event.getAction() == MotionEvent.ACTION_UP && isPressed()) {
MediaController.getInstance().playNextMessage();
nextButton.setProgress(0f);
nextButton.playAnimation();
}
AndroidUtilities.cancelRunOnUIThread(pressedRunnable);
if (rewindingForwardPressedCount > 0) {
MediaController.getInstance().setPlaybackSpeed(true, 1f);
if (MediaController.getInstance().isMessagePaused()) {
lastUpdateRewindingPlayerTime = 0;
forwardSeek.run();
}
}
rewindingState = 0;
setPressed(false);
rewindingForwardPressedCount = 0;
rewindingProgress = -1;
break;
}
return true;
}
};
nextButton.setScaleType(ImageView.ScaleType.CENTER);
nextButton.setAnimation(R.raw.player_prev, 20, 20);
nextButton.setLayerColor("Triangle 3.**", iconColor);
@ -708,11 +1000,6 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
nextButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 1, AndroidUtilities.dp(22)));
}
bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
nextButton.setOnClickListener(v -> {
MediaController.getInstance().playNextMessage();
nextButton.setProgress(0f);
nextButton.playAnimation();
});
nextButton.setContentDescription(LocaleController.getString("Next", R.string.Next));
buttons[4] = optionsButton = new ActionBarMenuItem(context, null, 0, iconColor);
@ -888,6 +1175,15 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
updateEmptyView();
}
private void startForwardRewindingSeek() {
if (rewindingState == 1) {
lastRewindingTime = System.currentTimeMillis();
rewindingProgress = MediaController.getInstance().getPlayingMessageObject().audioProgress;
AndroidUtilities.cancelRunOnUIThread(forwardSeek);
AndroidUtilities.runOnUIThread(forwardSeek);
}
}
private void updateEmptyViewPosition() {
if (emptyView.getVisibility() != View.VISIBLE) {
return;
@ -1201,6 +1497,18 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
}
}
}
if (id == NotificationCenter.messagePlayingPlayStateChanged) {
if (MediaController.getInstance().getPlayingMessageObject() != null) {
if (MediaController.getInstance().isMessagePaused()) {
startForwardRewindingSeek();
} else if (rewindingState == 1 && rewindingProgress != -1f) {
AndroidUtilities.cancelRunOnUIThread(forwardSeek);
lastUpdateRewindingPlayerTime = 0;
forwardSeek.run();
rewindingProgress = -1f;
}
}
}
} else if (id == NotificationCenter.messagePlayingDidStart) {
MessageObject messageObject = (MessageObject) args[0];
if (messageObject.eventId != 0) {
@ -1433,7 +1741,12 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
if (seekBarView.isDragging()) {
newTime = (int) (messageObject.getDuration() * seekBarView.getProgress());
} else {
seekBarView.setProgress(messageObject.audioProgress, animated);
boolean updateRewinding = rewindingProgress >= 0 && (rewindingState == -1 || (rewindingState == 1 && MediaController.getInstance().isMessagePaused()));
if (updateRewinding) {
seekBarView.setProgress(rewindingProgress, animated);
} else {
seekBarView.setProgress(messageObject.audioProgress, animated);
}
float bufferedProgress;
if (currentAudioFinishedLoading) {
@ -1450,7 +1763,12 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
if (bufferedProgress != -1) {
seekBarView.setBufferedProgress(bufferedProgress);
}
newTime = messageObject.audioProgressSec;
if (updateRewinding) {
newTime = (int) (messageObject.getDuration() * seekBarView.getProgress());
messageObject.audioProgressSec = newTime;
} else {
newTime = messageObject.audioProgressSec;
}
}
if (lastTime != newTime) {
lastTime = newTime;
@ -1999,6 +2317,8 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
private int activeIndex;
private AnimatorSet animatorSet;
private LinearGradient gradientShader;
private int stableOffest = -1;
private final RectF rectF = new RectF();
public ClippingTextViewSwitcher(@NonNull Context context) {
super(context);
@ -2028,7 +2348,27 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
final int index = child == textViews[0] ? 0 : 1;
final boolean result;
if (clipProgress[index] > 0f) {
boolean hasStableRect = false;
if (stableOffest > 0 && textViews[activeIndex].getAlpha() != 1f && textViews[activeIndex].getLayout() != null) {
float x1 = textViews[activeIndex].getLayout().getPrimaryHorizontal(0);
float x2 = textViews[activeIndex].getLayout().getPrimaryHorizontal(stableOffest);
hasStableRect = true;
if (x1 == x2) {
hasStableRect = false;
} else if (x2 > x1) {
rectF.set(x1, 0, x2, getMeasuredHeight());
} else {
rectF.set(x2, 0, x1, getMeasuredHeight());
}
if (hasStableRect && index == activeIndex) {
canvas.save();
canvas.clipRect(rectF);
textViews[0].draw(canvas);
canvas.restore();
}
}
if (clipProgress[index] > 0f || hasStableRect) {
final int width = child.getWidth();
final int height = child.getHeight();
final int saveCount = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG);
@ -2041,6 +2381,9 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
if (width > gradientEnd) {
canvas.drawRect(gradientEnd, 0, width, height, erasePaint);
}
if (hasStableRect) {
canvas.drawRect(rectF, erasePaint);
}
canvas.restoreToCount(saveCount);
} else {
result = super.drawChild(canvas, child, drawingTime);
@ -2049,15 +2392,31 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
}
public void setText(CharSequence text) {
setText(text, true);
}
public void setText(CharSequence text, boolean animated) {
final CharSequence currentText = textViews[activeIndex].getText();
if (TextUtils.isEmpty(currentText)) {
if (TextUtils.isEmpty(currentText) || !animated) {
textViews[activeIndex].setText(text);
return;
} else if (TextUtils.equals(text, currentText)) {
return;
}
stableOffest = 0;
int n = Math.min(text.length(), currentText.length());
for (int i = 0; i < n; i++) {
if (text.charAt(i) != currentText.charAt(i)) {
break;
}
stableOffest++;
}
if (stableOffest <= 3) {
stableOffest = -1;
}
final int index = activeIndex == 0 ? 1 : 0;
final int prevIndex = activeIndex;
activeIndex = index;

View File

@ -242,6 +242,7 @@ public class AvatarsImageView extends FrameLayout {
protected void onDraw(Canvas canvas) {
wasDraw = true;
int size = AndroidUtilities.dp(currentStyle == 4 ? 32 : 24);
int toAdd = AndroidUtilities.dp(currentStyle == 4 ? 24 : 20);
int drawCount = 0;
for (int i = 0; i < 3; i++) {
@ -249,7 +250,7 @@ public class AvatarsImageView extends FrameLayout {
drawCount++;
}
}
int ax = centered ? (getMeasuredWidth() - drawCount * toAdd - AndroidUtilities.dp(currentStyle == 4 ? 8 : 4)) / 2 : AndroidUtilities.dp(10);
int ax = centered ? (getMeasuredWidth() - drawCount * toAdd - AndroidUtilities.dp(currentStyle == 4 ? 8 : 4)) / 2 : (currentStyle == 0 ? 0 : AndroidUtilities.dp(10));
boolean isMuted = VoIPService.getSharedInstance() != null && VoIPService.getSharedInstance().isMicMute();
if (currentStyle == 4) {
paint.setColor(Theme.getColor(Theme.key_inappPlayerBackground));
@ -263,7 +264,7 @@ public class AvatarsImageView extends FrameLayout {
animateToDrawCount++;
}
}
boolean useAlphaLayer = currentStyle == 3 || currentStyle == 4 || currentStyle == 5;
boolean useAlphaLayer = currentStyle == 0 || currentStyle == 1 || currentStyle == 3 || currentStyle == 4 || currentStyle == 5;
if (useAlphaLayer) {
canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG);
}
@ -289,7 +290,11 @@ public class AvatarsImageView extends FrameLayout {
imageReceiver.setImageX(ax + toAdd * a);
}
imageReceiver.setImageY(AndroidUtilities.dp(currentStyle == 4 ? 8 : 6));
if (currentStyle == 0) {
imageReceiver.setImageY((getMeasuredHeight() - size) / 2f);
} else {
imageReceiver.setImageY(AndroidUtilities.dp(currentStyle == 4 ? 8 : 6));
}
boolean needRestore = false;
float alpha = 1f;
@ -319,7 +324,7 @@ public class AvatarsImageView extends FrameLayout {
float avatarScale = 1f;
if (a != states.length - 1) {
if (currentStyle == 3 || currentStyle == 5) {
if (currentStyle == 1 || currentStyle == 3 || currentStyle == 5) {
canvas.drawCircle(imageReceiver.getCenterX(), imageReceiver.getCenterY(), AndroidUtilities.dp(13), xRefP);
if (states[a].wavesDrawable == null) {
if (currentStyle == 5) {
@ -331,7 +336,7 @@ public class AvatarsImageView extends FrameLayout {
if (currentStyle == 5) {
states[a].wavesDrawable.setColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_voipgroup_speakingText), (int) (255 * 0.3f * alpha)));
}
if (states[a].participant.amplitude > 0) {
if (states[a].participant != null && states[a].participant.amplitude > 0) {
states[a].wavesDrawable.setShowWaves(true, this);
float amplitude = states[a].participant.amplitude * 15f;
states[a].wavesDrawable.setAmplitude(amplitude);
@ -368,13 +373,17 @@ public class AvatarsImageView extends FrameLayout {
states[a].wavesDrawable.draw(canvas, imageReceiver.getCenterX(), imageReceiver.getCenterY(), this);
avatarScale = states[a].wavesDrawable.getAvatarScale();
} else {
int paintAlpha = paint.getAlpha();
if (alpha != 1f) {
paint.setAlpha((int) (paintAlpha * alpha));
}
canvas.drawCircle(imageReceiver.getCenterX(), imageReceiver.getCenterY(), AndroidUtilities.dp(currentStyle == 4 ? 17 : 13), paint);
if (alpha != 1f) {
paint.setAlpha(paintAlpha);
if (useAlphaLayer) {
canvas.drawCircle(imageReceiver.getCenterX(), imageReceiver.getCenterY(), AndroidUtilities.dp(currentStyle == 4 ? 17 : 13), xRefP);
} else {
int paintAlpha = paint.getAlpha();
if (alpha != 1f) {
paint.setAlpha((int) (paintAlpha * alpha));
}
canvas.drawCircle(imageReceiver.getCenterX(), imageReceiver.getCenterY(), AndroidUtilities.dp(currentStyle == 4 ? 17 : 13), paint);
if (alpha != 1f) {
paint.setAlpha(paintAlpha);
}
}
}
}

View File

@ -6,13 +6,15 @@ import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.Property;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.Gravity;
@ -32,6 +34,7 @@ import androidx.annotation.Nullable;
import androidx.core.util.Consumer;
import androidx.core.view.ViewCompat;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@ -104,7 +107,7 @@ public final class Bulletin {
private boolean showing;
private boolean canHide;
private int currentBottomOffset;
public int currentBottomOffset;
private Delegate currentDelegate;
private Layout.Transition layoutTransition;
@ -128,6 +131,10 @@ public final class Bulletin {
this.duration = duration;
}
public static Bulletin getVisibleBulletin() {
return visibleBulletin;
}
public Bulletin show() {
if (!showing) {
showing = true;
@ -154,14 +161,12 @@ public final class Bulletin {
currentDelegate.onShow(Bulletin.this);
}
if (isTransitionsEnabled()) {
if (currentBottomOffset != 0) {
ViewCompat.setClipBounds(parentLayout, new Rect(left, top - currentBottomOffset, right, bottom - currentBottomOffset));
} else {
ViewCompat.setClipBounds(parentLayout, null);
}
ensureLayoutTransitionCreated();
layout.transitionRunning = true;
layout.delegate = currentDelegate;
layout.invalidate();
layoutTransition.animateEnter(layout, layout::onEnterTransitionStart, () -> {
ViewCompat.setClipBounds(parentLayout, null);
layout.transitionRunning = false;
layout.onEnterTransitionEnd();
setCanHide(true);
}, offset -> {
@ -173,7 +178,7 @@ public final class Bulletin {
if (currentDelegate != null) {
currentDelegate.onOffsetChange(layout.getHeight() - currentBottomOffset);
}
layout.setTranslationY(-currentBottomOffset);
updatePosition();
layout.onEnterTransitionStart();
layout.onEnterTransitionEnd();
setCanHide(true);
@ -233,18 +238,16 @@ public final class Bulletin {
if (ViewCompat.isLaidOut(layout)) {
layout.removeCallbacks(hideRunnable);
if (animated) {
if (bottomOffset != 0) {
ViewCompat.setClipBounds(parentLayout, new Rect(layout.getLeft(), layout.getTop() - bottomOffset, layout.getRight(), layout.getBottom() - bottomOffset));
} else {
ViewCompat.setClipBounds(parentLayout, null);
}
layout.transitionRunning = true;
layout.delegate = currentDelegate;
layout.invalidate();
ensureLayoutTransitionCreated();
layoutTransition.animateExit(layout, layout::onExitTransitionStart, () -> {
if (currentDelegate != null) {
currentDelegate.onOffsetChange(0);
currentDelegate.onHide(this);
}
ViewCompat.setClipBounds(parentLayout, null);
layout.transitionRunning = false;
layout.onExitTransitionEnd();
layout.onHide();
containerLayout.removeView(parentLayout);
@ -284,6 +287,10 @@ public final class Bulletin {
return MessagesController.getGlobalMainSettings().getBoolean("view_animations", true) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
}
public void updatePosition() {
layout.updatePosition();
}
@Retention(SOURCE)
@IntDef(value = {ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT})
private @interface WidthDef {
@ -461,6 +468,9 @@ public final class Bulletin {
public abstract static class Layout extends FrameLayout {
private final List<Callback> callbacks = new ArrayList<>();
public boolean transitionRunning;
Delegate delegate;
public float inOutOffset;
protected Bulletin bulletin;
@ -473,13 +483,42 @@ public final class Bulletin {
this(context, Theme.getColor(Theme.key_undo_background));
}
Drawable background;
public Layout(@NonNull Context context, @ColorInt int backgroundColor) {
super(context);
setMinimumHeight(AndroidUtilities.dp(48));
setBackground(new InsetDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(6), backgroundColor), AndroidUtilities.dp(8)));
background = Theme.createRoundRectDrawable(AndroidUtilities.dp(6), backgroundColor);
updateSize();
setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8));
setWillNotDraw(false);
}
public final static FloatPropertyCompat<Layout> IN_OUT_OFFSET_Y = new FloatPropertyCompat<Layout>("offsetY") {
@Override
public float getValue(Layout object) {
return object.inOutOffset;
}
@Override
public void setValue(Layout object, float value) {
object.setInOutOffset(value);
}
};
public final static Property<Layout, Float> IN_OUT_OFFSET_Y2 = new AnimationProperties.FloatProperty<Layout>("offsetY") {
@Override
public Float get(Layout layout) {
return layout.inOutOffset;
}
@Override
public void setValue(Layout object, float value) {
object.setInOutOffset(value);
}
};
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@ -602,6 +641,14 @@ public final class Bulletin {
callbacks.remove(callback);
}
public void updatePosition() {
float tranlsation = 0;
if (delegate != null) {
tranlsation += delegate.getBottomOffset() ;
}
setTranslationY(-tranlsation + inOutOffset);
}
public interface Callback {
void onAttach(@NonNull Layout layout, @NonNull Bulletin bulletin);
@ -637,7 +684,11 @@ public final class Bulletin {
@Override
public void animateEnter(@NonNull Layout layout, @Nullable Runnable startAction, @Nullable Runnable endAction, @Nullable Consumer<Float> onUpdate, int bottomOffset) {
final ObjectAnimator animator = ObjectAnimator.ofFloat(layout, View.TRANSLATION_Y, layout.getHeight(), -bottomOffset);
layout.setInOutOffset(layout.getMeasuredHeight());
if (onUpdate != null) {
onUpdate.accept(layout.getTranslationY());
}
final ObjectAnimator animator = ObjectAnimator.ofFloat(layout, IN_OUT_OFFSET_Y2, 0);
animator.setDuration(225);
animator.setInterpolator(Easings.easeOutQuad);
if (startAction != null || endAction != null) {
@ -658,14 +709,14 @@ public final class Bulletin {
});
}
if (onUpdate != null) {
animator.addUpdateListener(a -> onUpdate.accept((Float) a.getAnimatedValue()));
animator.addUpdateListener(a -> onUpdate.accept(layout.getTranslationY()));
}
animator.start();
}
@Override
public void animateExit(@NonNull Layout layout, @Nullable Runnable startAction, @Nullable Runnable endAction, @Nullable Consumer<Float> onUpdate, int bottomOffset) {
final ObjectAnimator animator = ObjectAnimator.ofFloat(layout, View.TRANSLATION_Y, layout.getTranslationY(), layout.getHeight());
final ObjectAnimator animator = ObjectAnimator.ofFloat(layout, IN_OUT_OFFSET_Y2, layout.getHeight());
animator.setDuration(175);
animator.setInterpolator(Easings.easeInQuad);
if (startAction != null || endAction != null) {
@ -686,7 +737,7 @@ public final class Bulletin {
});
}
if (onUpdate != null) {
animator.addUpdateListener(a -> onUpdate.accept((Float) a.getAnimatedValue()));
animator.addUpdateListener(a -> onUpdate.accept(layout.getTranslationY()));
}
animator.start();
}
@ -699,23 +750,23 @@ public final class Bulletin {
@Override
public void animateEnter(@NonNull Layout layout, @Nullable Runnable startAction, @Nullable Runnable endAction, @Nullable Consumer<Float> onUpdate, int bottomOffset) {
final int translationY = layout.getHeight() - bottomOffset;
layout.setTranslationY(translationY);
layout.setInOutOffset(layout.getMeasuredHeight());
if (onUpdate != null) {
onUpdate.accept((float) translationY);
onUpdate.accept(layout.getTranslationY());
}
final SpringAnimation springAnimation = new SpringAnimation(layout, SpringAnimation.TRANSLATION_Y, -bottomOffset);
final SpringAnimation springAnimation = new SpringAnimation(layout, IN_OUT_OFFSET_Y, 0);
springAnimation.getSpring().setDampingRatio(DAMPING_RATIO);
springAnimation.getSpring().setStiffness(STIFFNESS);
if (endAction != null) {
springAnimation.addEndListener((animation, canceled, value, velocity) -> {
layout.setInOutOffset(0);
if (!canceled) {
endAction.run();
}
});
}
if (onUpdate != null) {
springAnimation.addUpdateListener((animation, value, velocity) -> onUpdate.accept(value));
springAnimation.addUpdateListener((animation, value, velocity) -> onUpdate.accept(layout.getTranslationY()));
}
springAnimation.start();
if (startAction != null) {
@ -725,7 +776,7 @@ public final class Bulletin {
@Override
public void animateExit(@NonNull Layout layout, @Nullable Runnable startAction, @Nullable Runnable endAction, @Nullable Consumer<Float> onUpdate,int bottomOffset) {
final SpringAnimation springAnimation = new SpringAnimation(layout, SpringAnimation.TRANSLATION_Y, layout.getHeight() - bottomOffset);
final SpringAnimation springAnimation = new SpringAnimation(layout, IN_OUT_OFFSET_Y, layout.getHeight());
springAnimation.getSpring().setDampingRatio(DAMPING_RATIO);
springAnimation.getSpring().setStiffness(STIFFNESS);
if (endAction != null) {
@ -736,7 +787,7 @@ public final class Bulletin {
});
}
if (onUpdate != null) {
springAnimation.addUpdateListener((animation, value, velocity) -> onUpdate.accept(value));
springAnimation.addUpdateListener((animation, value, velocity) -> onUpdate.accept(layout.getTranslationY()));
}
springAnimation.start();
if (startAction != null) {
@ -744,6 +795,30 @@ public final class Bulletin {
}
}
}
private void setInOutOffset(float offset) {
inOutOffset = offset;
updatePosition();
}
@Override
protected void dispatchDraw(Canvas canvas) {
background.setBounds(AndroidUtilities.dp(8), AndroidUtilities.dp(8), getMeasuredWidth() - AndroidUtilities.dp(8), getMeasuredHeight() - AndroidUtilities.dp(8));
if (transitionRunning && delegate != null) {
int clipBottom = ((View)getParent()).getMeasuredHeight() - delegate.getBottomOffset();
int viewBottom = (int) (getY() + getMeasuredHeight());
canvas.save();
canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight() - (viewBottom - clipBottom));
background.draw(canvas);
super.dispatchDraw(canvas);
canvas.restore();
invalidate();
} else {
background.draw(canvas);
super.dispatchDraw(canvas);
}
}
//endregion
}

View File

@ -1,6 +1,7 @@
package org.telegram.ui.Components;
import android.content.Context;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.CheckResult;
@ -25,6 +26,20 @@ public final class BulletinFactory {
return fragment != null && fragment.getParentActivity() != null && fragment.getLayoutContainer() != null;
}
public Bulletin createMembersNotifyInfo(boolean on) {
if (on) {
final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext());
layout.setAnimation(R.raw.silent_unmute, 36, 36, "NULL BODY", "BODY", "Waves R", "Waves L", "Bottom");
layout.textView.setText(LocaleController.getString("ChannelNotifyMembersInfoOn", R.string.ChannelNotifyMembersInfoOn));
return create(layout, Bulletin.DURATION_SHORT);
} else {
final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext());
layout.setAnimation(R.raw.silent_mute, 36, 36, "NULL BODY", "BODY", "Pieces", "Line Cross", "Bottom");
layout.textView.setText(LocaleController.getString("ChannelNotifyMembersInfoOff", R.string.ChannelNotifyMembersInfoOff));
return create(layout, Bulletin.DURATION_SHORT);
}
}
public enum FileType {
PHOTO("PhotoSavedHint", R.string.PhotoSavedHint, Icon.SAVED_TO_GALLERY),
@ -289,6 +304,11 @@ public final class BulletinFactory {
return of(fragment).createCopyLinkBulletin();
}
@CheckResult
public static Bulletin createCopyLinkBulletin(FrameLayout containerView) {
return of(containerView).createCopyLinkBulletin();
}
@CheckResult
public static Bulletin createPinMessageBulletin(BaseFragment fragment) {
return createPinMessageBulletin(fragment, true, null, null);

View File

@ -218,6 +218,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
private NumberTextView captionLimitView;
private int currentLimit = -1;
private int codePointCount;
CrossOutDrawable notifySilentDrawable;
private class SeekBarWaveformView extends View {
@ -353,6 +354,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
public ValueAnimator currentTopViewAnimation;
private ReplaceableIconDrawable botButtonDrawablel;
private boolean isPaste;
private boolean destroyed;
private MessageObject editingMessageObject;
@ -1771,6 +1774,14 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
}
isInitLineCount = false;
}
@Override
public boolean onTextContextMenuItem(int id) {
if (id == android.R.id.paste) {
isPaste = true;
}
return super.onTextContextMenuItem(id);
}
};
messageEditText.setDelegate(() -> {
if (delegate != null) {
@ -1780,7 +1791,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
messageEditText.setWindowView(parentActivity.getWindow().getDecorView());
TLRPC.EncryptedChat encryptedChat = parentFragment != null ? parentFragment.getCurrentEncryptedChat() : null;
messageEditText.setAllowTextEntitiesIntersection(supportsSendingNewEntities());
updateFieldHint();
updateFieldHint(false);
int flags = EditorInfo.IME_FLAG_NO_EXTRACT_UI;
if (encryptedChat != null) {
flags |= 0x01000000; //EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING;
@ -1876,9 +1887,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
if (innerTextChange == 1) {
return;
}
if (sendByEnter && editingMessageObject == null && count > before && charSequence.length() > 0 && count == 1 && before == 0 && charSequence.length() == start + count && charSequence.charAt(charSequence.length() - 1) == '\n') {
if (sendByEnter && !isPaste && editingMessageObject == null && count > before && charSequence.length() > 0 && charSequence.length() == start + count && charSequence.charAt(charSequence.length() - 1) == '\n') {
nextChangeIsSend = true;
}
isPaste = false;
checkSendButton(true);
CharSequence message = AndroidUtilities.getTrimmedString(charSequence.toString());
if (delegate != null) {
@ -2036,7 +2048,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
});
notifyButton = new ImageView(context);
notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on);
notifySilentDrawable = new CrossOutDrawable(context, R.drawable.input_notify_on, Theme.key_chat_messagePanelIcons);
notifyButton.setImageDrawable(notifySilentDrawable);
notifySilentDrawable.setCrossOut(silent, false);
notifyButton.setContentDescription(silent ? LocaleController.getString("AccDescrChanSilentOn", R.string.AccDescrChanSilentOn) : LocaleController.getString("AccDescrChanSilentOff", R.string.AccDescrChanSilentOff));
notifyButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY));
notifyButton.setScaleType(ImageView.ScaleType.CENTER);
@ -2052,7 +2066,11 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
@Override
public void onClick(View v) {
silent = !silent;
notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on);
if (notifySilentDrawable == null) {
notifySilentDrawable = new CrossOutDrawable(context, R.drawable.input_notify_on, Theme.key_chat_messagePanelIcons);
}
notifySilentDrawable.setCrossOut(silent, true);
notifyButton.setImageDrawable(notifySilentDrawable);
MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + dialog_id, silent).commit();
NotificationsController.getInstance(currentAccount).updateServerNotificationsSettings(dialog_id);
try {
@ -2062,15 +2080,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
} catch (Exception e) {
FileLog.e(e);
}
if (silent) {
visibleToast = Toast.makeText(parentActivity, LocaleController.getString("ChannelNotifyMembersInfoOff", R.string.ChannelNotifyMembersInfoOff), Toast.LENGTH_SHORT);
visibleToast.show();
} else {
visibleToast = Toast.makeText(parentActivity, LocaleController.getString("ChannelNotifyMembersInfoOn", R.string.ChannelNotifyMembersInfoOn), Toast.LENGTH_SHORT);
visibleToast.show();
}
BulletinFactory.of(fragment).createMembersNotifyInfo(!silent).show();
notifyButton.setContentDescription(silent ? LocaleController.getString("AccDescrChanSilentOn", R.string.AccDescrChanSilentOn) : LocaleController.getString("AccDescrChanSilentOff", R.string.AccDescrChanSilentOff));
updateFieldHint();
updateFieldHint(true);
}
});
@ -3434,7 +3446,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
updateScheduleButton(false);
checkRoundVideo();
updateFieldHint();
updateFieldHint(false);
}
public void setChatInfo(TLRPC.ChatFull chatInfo) {
@ -3495,7 +3507,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
return hasRecordVideo;
}
private void updateFieldHint() {
private void updateFieldHint(boolean animated) {
if (editingMessageObject != null) {
messageEditText.setHintText(editingCaption ? LocaleController.getString("Caption", R.string.Caption) : LocaleController.getString("TypeMessage", R.string.TypeMessage));
} else {
@ -3517,9 +3529,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
}
} else if (isChannel) {
if (silent) {
messageEditText.setHintText(LocaleController.getString("ChannelSilentBroadcast", R.string.ChannelSilentBroadcast));
messageEditText.setHintText(LocaleController.getString("ChannelSilentBroadcast", R.string.ChannelSilentBroadcast), animated);
} else {
messageEditText.setHintText(LocaleController.getString("ChannelBroadcast", R.string.ChannelBroadcast));
messageEditText.setHintText(LocaleController.getString("ChannelBroadcast", R.string.ChannelBroadcast), animated);
}
} else {
messageEditText.setHintText(LocaleController.getString("TypeMessage", R.string.TypeMessage));
@ -5454,7 +5466,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
}
updateFieldRight(1);
}
updateFieldHint();
updateFieldHint(false);
}
public ImageView getAttachButton() {
@ -5654,7 +5666,11 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
canWriteToChannel = ChatObject.isChannel(currentChat) && (currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.post_messages) && !currentChat.megagroup;
if (notifyButton != null) {
notifyVisible = canWriteToChannel;
notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on);
if (notifySilentDrawable == null) {
notifySilentDrawable = new CrossOutDrawable(getContext(), R.drawable.input_notify_on, Theme.key_chat_messagePanelIcons);
}
notifySilentDrawable.setCrossOut(silent, false);
notifyButton.setImageDrawable(notifySilentDrawable);
}
if (attachLayout != null) {
updateFieldRight(attachLayout.getVisibility() == VISIBLE ? 1 : 0);

View File

@ -1578,15 +1578,19 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
}
}
fixLayoutInternal(true);
if (checkPermission && Build.VERSION.SDK_INT >= 23) {
Activity activity = getParentActivity();
if (activity != null) {
checkPermission = false;
if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 2);
boolean keyboardVisible = parentAlert.delegate.needEnterComment();
AndroidUtilities.runOnUIThread(() -> {
if (checkPermission && Build.VERSION.SDK_INT >= 23) {
Activity activity = getParentActivity();
if (activity != null) {
checkPermission = false;
if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 2);
}
}
}
}
}, keyboardVisible ? 200 : 0);
layoutManager.scrollToPositionWithOffset(0, 0);
updateClipView();

View File

@ -40,6 +40,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
@ -441,12 +442,19 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
cameraDrawable = context.getResources().getDrawable(R.drawable.instant_camera).mutate();
ActionBarMenu menu = parentAlert.actionBar.createMenu();
dropDownContainer = new ActionBarMenuItem(context, menu, 0, 0);
dropDownContainer = new ActionBarMenuItem(context, menu, 0, 0) {
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setText(dropDown.getText());
}
};
dropDownContainer.setSubMenuOpenSide(1);
parentAlert.actionBar.addView(dropDownContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, AndroidUtilities.isTablet() ? 64 : 56, 0, 40, 0));
dropDownContainer.setOnClickListener(view -> dropDownContainer.toggleSubMenu());
dropDown = new TextView(context);
dropDown.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
dropDown.setGravity(Gravity.LEFT);
dropDown.setSingleLine(true);
dropDown.setLines(1);

View File

@ -264,14 +264,14 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
}
public void setTitle(CharSequence value) {
setTitle(value, false);
setTitle(value, false, false);
}
public void setTitle(CharSequence value, boolean scam) {
public void setTitle(CharSequence value, boolean scam, boolean fake) {
titleTextView.setText(value);
if (scam) {
if (scam || fake) {
if (!(titleTextView.getRightDrawable() instanceof ScamDrawable)) {
ScamDrawable drawable = new ScamDrawable(11);
ScamDrawable drawable = new ScamDrawable(11, scam ? 0 : 1);
drawable.setColor(Theme.getColor(Theme.key_actionBarDefaultSubtitle));
titleTextView.setRightDrawable(drawable);
}

View File

@ -8,12 +8,14 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.DocumentObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.R;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
@ -53,8 +55,13 @@ public class ChatGreetingsView extends LinearLayout {
updateColors();
titleView.setText(LocaleController.formatString("NearbyPeopleGreetingsMessage", R.string.NearbyPeopleGreetingsMessage, user.first_name, LocaleController.formatDistance(distance, 1)));
descriptionView.setText(LocaleController.getString("NearbyPeopleGreetingsDescription", R.string.NearbyPeopleGreetingsDescription));
if (distance <= 0) {
titleView.setText(LocaleController.getString("NoMessages", R.string.NoMessages));
descriptionView.setText(LocaleController.getString("NoMessagesGreetingsDescription", R.string.NoMessagesGreetingsDescription));
} else {
titleView.setText(LocaleController.formatString("NearbyPeopleGreetingsMessage", R.string.NearbyPeopleGreetingsMessage, user.first_name, LocaleController.formatDistance(distance, 1)));
descriptionView.setText(LocaleController.getString("NearbyPeopleGreetingsDescription", R.string.NearbyPeopleGreetingsDescription));
}
if (preloadedGreetingsSticker == null) {
TLRPC.TL_messages_getStickers req = new TLRPC.TL_messages_getStickers();
@ -64,27 +71,23 @@ public class ChatGreetingsView extends LinearLayout {
ArrayList<TLRPC.Document> list = ((TLRPC.TL_messages_stickers) response).stickers;
if (!list.isEmpty()) {
TLRPC.Document sticker = list.get(Math.abs(new Random().nextInt() % list.size()));
AndroidUtilities.runOnUIThread(() -> {
setSticker(sticker);
});
AndroidUtilities.runOnUIThread(() -> setSticker(sticker));
}
}
});
} else {
setSticker(preloadedGreetingsSticker);
}
}
private void setSticker(TLRPC.Document sticker) {
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90);
stickerToSendView.setImage(
ImageLocation.getForDocument(sticker), createFilter(sticker),
ImageLocation.getForDocument(thumb, sticker), null,
0, sticker
);
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(sticker, Theme.key_chat_serviceBackground, 1.0f);
if (svgThumb != null) {
stickerToSendView.setImage(ImageLocation.getForDocument(sticker), createFilter(sticker), svgThumb, 0, sticker);
} else {
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90);
stickerToSendView.setImage(ImageLocation.getForDocument(sticker), createFilter(sticker), ImageLocation.getForDocument(thumb, sticker), null, 0, sticker);
}
stickerToSendView.setOnClickListener(v -> {
if (listener != null) {
listener.onGreetings(sticker);

View File

@ -0,0 +1,209 @@
package org.telegram.ui.Components;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ChatMessageCell;
@SuppressWarnings("FieldCanBeLocal")
public class ChecksHintView extends FrameLayout {
private TextView[] textView = new TextView[2];
private RLottieImageView[] imageView = new RLottieImageView[2];
private ImageView arrowImageView;
private ChatMessageCell messageCell;
private View currentView;
private AnimatorSet animatorSet;
private Runnable hideRunnable;
private float translationY;
private long showingDuration = 2000;
public ChecksHintView(Context context) {
super(context);
FrameLayout backgroundView = new FrameLayout(context);
backgroundView.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_chat_gifSaveHintBackground)));
backgroundView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8));
addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 6));
for (int a = 0; a < 2; a++) {
imageView[a] = new RLottieImageView(context);
imageView[a].setScaleType(ImageView.ScaleType.CENTER);
backgroundView.addView(imageView[a], LayoutHelper.createFrame(24, 24, Gravity.LEFT | Gravity.TOP, 0, a == 0 ? 0 : 24, 0, 0));
textView[a] = new TextView(context);
textView[a].setTextColor(Theme.getColor(Theme.key_chat_gifSaveHintText));
textView[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView[a].setMaxLines(1);
textView[a].setSingleLine(true);
textView[a].setMaxWidth(AndroidUtilities.dp(250));
textView[a].setGravity(Gravity.LEFT | Gravity.TOP);
textView[a].setPivotX(0);
backgroundView.addView(textView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 32, a == 0 ? 2 : 26, 10, 0));
if (a == 0) {
imageView[a].setAnimation(R.raw.ticks_single, 24, 24);
textView[a].setText(LocaleController.getString("HintSent", R.string.HintSent));
} else {
imageView[a].setAnimation(R.raw.ticks_double, 24, 24);
textView[a].setText(LocaleController.getString("HintRead", R.string.HintRead));
}
imageView[a].playAnimation();
}
arrowImageView = new ImageView(context);
arrowImageView.setImageResource(R.drawable.tooltip_arrow);
arrowImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_gifSaveHintBackground), PorterDuff.Mode.MULTIPLY));
addView(arrowImageView, LayoutHelper.createFrame(14, 6, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 0));
}
public float getBaseTranslationY() {
return translationY;
}
public boolean showForMessageCell(ChatMessageCell cell, boolean animated) {
if (hideRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(hideRunnable);
hideRunnable = null;
}
int[] position = new int[2];
cell.getLocationInWindow(position);
int top = position[1];
View p = (View) getParent();
p.getLocationInWindow(position);
top -= position[1];
View parentView = (View) cell.getParent();
measure(MeasureSpec.makeMeasureSpec(1000, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(1000, MeasureSpec.AT_MOST));
if (top <= getMeasuredHeight() + AndroidUtilities.dp(10)) {
return false;
}
top += cell.getChecksY() + AndroidUtilities.dp(6);
int centerX = cell.getChecksX() + AndroidUtilities.dp(5);
int parentWidth = parentView.getMeasuredWidth();
setTranslationY(translationY = top - getMeasuredHeight());
int iconX = cell.getLeft() + centerX;
int left = AndroidUtilities.dp(15);
if (iconX > parentView.getMeasuredWidth() / 2) {
int offset = parentWidth - getMeasuredWidth() - AndroidUtilities.dp(20);
setTranslationX(offset);
left += offset;
} else {
setTranslationX(0);
}
float arrowX = cell.getLeft() + centerX - left - arrowImageView.getMeasuredWidth() / 2;
arrowImageView.setTranslationX(arrowX);
if (iconX > parentView.getMeasuredWidth() / 2) {
if (arrowX < AndroidUtilities.dp(10)) {
float diff = arrowX - AndroidUtilities.dp(10);
setTranslationX(getTranslationX() + diff);
arrowImageView.setTranslationX(arrowX - diff);
}
} else {
if (arrowX > getMeasuredWidth() - AndroidUtilities.dp(14 + 10)) {
float diff = arrowX - getMeasuredWidth() + AndroidUtilities.dp(14 + 10);
setTranslationX(diff);
arrowImageView.setTranslationX(arrowX - diff);
} else if (arrowX < AndroidUtilities.dp(10)) {
float diff = arrowX - AndroidUtilities.dp(10);
setTranslationX(getTranslationX() + diff);
arrowImageView.setTranslationX(arrowX - diff);
}
}
setPivotX(arrowX);
setPivotY(getMeasuredHeight());
messageCell = cell;
if (animatorSet != null) {
animatorSet.cancel();
animatorSet = null;
}
setTag(1);
setVisibility(VISIBLE);
if (animated) {
animatorSet = new AnimatorSet();
animatorSet.playTogether(
ObjectAnimator.ofFloat(this, View.ALPHA, 0.0f, 1.0f),
ObjectAnimator.ofFloat(this, View.SCALE_X, 0.0f, 1.0f),
ObjectAnimator.ofFloat(this, View.SCALE_Y, 0.0f, 1.0f)
);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animatorSet = null;
AndroidUtilities.runOnUIThread(hideRunnable = () -> hide(), 3000);
}
});
animatorSet.setDuration(180);
animatorSet.start();
for (int a = 0; a < 2; a++) {
final int num = a;
textView[a].animate().scaleX(1.04f).scaleY(1.04f).setInterpolator(CubicBezierInterpolator.EASE_IN).setStartDelay((a == 0 ? 132 : 500) + 140).setDuration(100).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
textView[num].animate().scaleX(1.0f).scaleY(1.0f).setInterpolator(CubicBezierInterpolator.EASE_OUT).setStartDelay(0).setDuration(100).start();
}
}).start();
}
} else {
setAlpha(1.0f);
}
return true;
}
public void hide() {
if (getTag() == null) {
return;
}
setTag(null);
if (hideRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(hideRunnable);
hideRunnable = null;
}
if (animatorSet != null) {
animatorSet.cancel();
animatorSet = null;
}
animatorSet = new AnimatorSet();
animatorSet.playTogether(
ObjectAnimator.ofFloat(this, View.ALPHA, 0.0f),
ObjectAnimator.ofFloat(this, View.SCALE_X, 0.0f),
ObjectAnimator.ofFloat(this, View.SCALE_Y, 0.0f)
);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(View.INVISIBLE);
currentView = null;
messageCell = null;
animatorSet = null;
}
});
animatorSet.setDuration(180);
animatorSet.start();
}
}

View File

@ -0,0 +1,311 @@
package org.telegram.ui.Components;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.view.Gravity;
import android.view.View;
import android.view.animation.OvershootInterpolator;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.ActionBar.Theme;
public class CounterView extends View {
private final static int ANIMATION_TYPE_IN = 0;
private final static int ANIMATION_TYPE_OUT = 1;
private final static int ANIMATION_TYPE_REPLACE = 2;
int animationType = -1;
Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
RectF rectF = new RectF();
int currentCount;
private boolean countAnimationIncrement;
private ValueAnimator countAnimator;
private float countChangeProgress = 1f;
private StaticLayout countLayout;
private StaticLayout countOldLayout;
private StaticLayout countAnimationStableLayout;
private StaticLayout countAnimationInLayout;
private int countWidthOld;
private int countWidth;
private int circleColor;
private int textColor;
private String textColorKey = Theme.key_chat_goDownButtonCounter;
private String circleColorKey = Theme.key_chat_goDownButtonCounterBackground;
int lastH;
int gravity = Gravity.CENTER;
float countLeft;
float x;
private boolean reverseAnimation;
public float horizontalPadding;
public CounterView(Context context) {
super(context);
setVisibility(View.GONE);
circlePaint.setColor(Color.BLACK);
textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textPaint.setTextSize(AndroidUtilities.dp(13));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getMeasuredHeight() != lastH) {
int count = currentCount;
currentCount = -1;
setCount(count, animationType == ANIMATION_TYPE_IN);
lastH = getMeasuredHeight();
}
}
public void setCount(int count, boolean animated) {
if (count == currentCount) {
return;
}
if (countAnimator != null) {
countAnimator.cancel();
}
if (count > 0) {
setVisibility(View.VISIBLE);
}
if (!animated) {
currentCount = count;
if (count == 0) {
setVisibility(View.GONE);
return;
}
String newStr = String.valueOf(count);
countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr)));
countLayout = new StaticLayout(newStr, textPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
invalidate();
}
String newStr = String.valueOf(count);
if (animated) {
if (countAnimator != null) {
countAnimator.cancel();
}
countChangeProgress = 0f;
countAnimator = ValueAnimator.ofFloat(0, 1f);
countAnimator.addUpdateListener(valueAnimator -> {
countChangeProgress = (float) valueAnimator.getAnimatedValue();
invalidate();
});
countAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animationType = -1;
countChangeProgress = 1f;
countOldLayout = null;
countAnimationStableLayout = null;
countAnimationInLayout = null;
if (currentCount == 0) {
setVisibility(View.GONE);
}
invalidate();
}
});
if (currentCount <= 0) {
animationType = ANIMATION_TYPE_IN;
countAnimator.setDuration(220);
countAnimator.setInterpolator(new OvershootInterpolator());
} else if (count == 0) {
animationType = ANIMATION_TYPE_OUT;
countAnimator.setDuration(150);
countAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
} else {
animationType = ANIMATION_TYPE_REPLACE;
countAnimator.setDuration(430);
countAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
}
if (countLayout != null) {
String oldStr = String.valueOf(currentCount);
if (oldStr.length() == newStr.length()) {
SpannableStringBuilder oldSpannableStr = new SpannableStringBuilder(oldStr);
SpannableStringBuilder newSpannableStr = new SpannableStringBuilder(newStr);
SpannableStringBuilder stableStr = new SpannableStringBuilder(newStr);
for (int i = 0; i < oldStr.length(); i++) {
if (oldStr.charAt(i) == newStr.charAt(i)) {
oldSpannableStr.setSpan(new EmptyStubSpan(), i, i + 1, 0);
newSpannableStr.setSpan(new EmptyStubSpan(), i, i + 1, 0);
} else {
stableStr.setSpan(new EmptyStubSpan(), i, i + 1, 0);
}
}
int countOldWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(oldStr)));
countOldLayout = new StaticLayout(oldSpannableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
countAnimationStableLayout = new StaticLayout(stableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
countAnimationInLayout = new StaticLayout(newSpannableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
} else {
countOldLayout = countLayout;
}
}
countWidthOld = countWidth;
countAnimationIncrement = count > currentCount;
countAnimator.start();
}
if (count > 0) {
countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr)));
countLayout = new StaticLayout(newStr, textPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
}
currentCount = count;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int textColor = Theme.getColor(textColorKey);
int circleColor = Theme.getColor(circleColorKey);
if (this.textColor != textColor) {
this.textColor = textColor;
textPaint.setColor(textColor);
}
if (this.circleColor != circleColor) {
this.circleColor = circleColor;
circlePaint.setColor(circleColor);
}
if (countChangeProgress != 1f) {
if (animationType == ANIMATION_TYPE_IN || animationType == ANIMATION_TYPE_OUT) {
updateX(countWidth);
float cx = countLeft + countWidth / 2f;
float cy = getMeasuredHeight() / 2f;
canvas.save();
float progress = animationType == ANIMATION_TYPE_IN ? countChangeProgress : (1f - countChangeProgress);
canvas.scale(progress, progress, cx, cy);
drawInternal(canvas);
canvas.restore();
} else {
float progressHalf = countChangeProgress * 2;
if (progressHalf > 1f) {
progressHalf = 1f;
}
float countTop = (getMeasuredHeight() - AndroidUtilities.dp(23)) / 2f;
float countWidth;
if (this.countWidth == this.countWidthOld) {
countWidth = this.countWidth;
} else {
countWidth = this.countWidth * progressHalf + this.countWidthOld * (1f - progressHalf);
}
updateX(countWidth);
float scale = 1f;
if (countAnimationIncrement) {
if (countChangeProgress <= 0.5f) {
scale += 0.1f * CubicBezierInterpolator.EASE_OUT.getInterpolation(countChangeProgress * 2);
} else {
scale += 0.1f * CubicBezierInterpolator.EASE_IN.getInterpolation((1f - (countChangeProgress - 0.5f) * 2));
}
}
rectF.set(x, countTop, x + countWidth + AndroidUtilities.dp(11), countTop + AndroidUtilities.dp(23));
canvas.save();
canvas.scale(scale, scale, rectF.centerX(), rectF.centerY());
canvas.drawRoundRect(rectF, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, circlePaint);
canvas.clipRect(rectF);
boolean increment = reverseAnimation != countAnimationIncrement;
if (countAnimationInLayout != null) {
canvas.save();
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4) + (increment ? AndroidUtilities.dp(13) : -AndroidUtilities.dp(13)) * (1f - progressHalf));
textPaint.setAlpha((int) (255 * progressHalf));
countAnimationInLayout.draw(canvas);
canvas.restore();
} else if (countLayout != null) {
canvas.save();
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4) + (increment ? AndroidUtilities.dp(13) : -AndroidUtilities.dp(13)) * (1f - progressHalf));
textPaint.setAlpha((int) (255 * progressHalf));
countLayout.draw(canvas);
canvas.restore();
}
if (countOldLayout != null) {
canvas.save();
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4) + (increment ? -AndroidUtilities.dp(13) : AndroidUtilities.dp(13)) * (progressHalf));
textPaint.setAlpha((int) (255 * (1f - progressHalf)));
countOldLayout.draw(canvas);
canvas.restore();
}
if (countAnimationStableLayout != null) {
canvas.save();
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4));
textPaint.setAlpha(255);
countAnimationStableLayout.draw(canvas);
canvas.restore();
}
textPaint.setAlpha(255);
canvas.restore();
}
} else {
drawInternal(canvas);
}
}
private void updateX(float countWidth) {
if (gravity == Gravity.RIGHT) {
countLeft = getMeasuredWidth() - AndroidUtilities.dp(5.5f);
if (horizontalPadding != 0) {
countLeft -= Math.max(horizontalPadding + countWidth / 2f, countWidth);
} else {
countLeft -= countWidth;
}
} else if (gravity == Gravity.LEFT) {
countLeft = AndroidUtilities.dp(5.5f);
} else {
countLeft = (int) ((getMeasuredWidth() - countWidth) / 2f);
}
x = countLeft - AndroidUtilities.dp(5.5f);
}
private void drawInternal(Canvas canvas) {
float countTop = (getMeasuredHeight() - AndroidUtilities.dp(23)) / 2f;
updateX(countWidth);
rectF.set(x, countTop, x + countWidth + AndroidUtilities.dp(11), countTop + AndroidUtilities.dp(23));
canvas.drawRoundRect(rectF, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, circlePaint);
if (countLayout != null) {
canvas.save();
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4));
countLayout.draw(canvas);
canvas.restore();
}
}
public void setColors(String textKey, String circleKey){
this.textColorKey = textKey;
this.circleColorKey = circleKey;
}
public void setGravity(int gravity) {
this.gravity = gravity;
}
public void setReverse(boolean b) {
reverseAnimation = b;
}
}

View File

@ -0,0 +1,132 @@
package org.telegram.ui.Components;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.ActionBar.Theme;
public class CrossOutDrawable extends Drawable {
Drawable iconDrawable;
RectF rectF = new RectF();
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
final Paint xRefPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
int color;
String colorKey;
float progress;
boolean cross;
public CrossOutDrawable(Context context, int iconRes, String colorKey) {
iconDrawable = ContextCompat.getDrawable(context, iconRes);
this.colorKey = colorKey;
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(AndroidUtilities.dpf2(1.7f));
paint.setStrokeCap(Paint.Cap.ROUND);
xRefPaint.setColor(0xff000000);
xRefPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
xRefPaint.setStyle(Paint.Style.STROKE);
xRefPaint.setStrokeWidth(AndroidUtilities.dpf2(2.5f));
}
public void setCrossOut(boolean cross, boolean animated) {
this.cross = cross;
if (!animated) {
progress = cross ? 1f : 0f;
} else {
progress = cross ? 0f : 1f;
}
invalidateSelf();
}
@Override
public void draw(@NonNull Canvas canvas) {
if (cross && progress != 1f) {
progress += 16f / 150f;
invalidateSelf();
if (progress > 1f) {
progress = 1f;
}
} else if (!cross && progress != 0f) {
progress -= 16f / 150f;
invalidateSelf();
if (progress < 0) {
progress = 0;
}
}
if (progress == 0) {
iconDrawable.draw(canvas);
return;
}
int newColor = Theme.getColor(colorKey);
if (color != newColor) {
color = newColor;
paint.setColor(newColor);
}
rectF.set(iconDrawable.getBounds());
canvas.saveLayerAlpha(rectF, 255, Canvas.ALL_SAVE_FLAG);
iconDrawable.draw(canvas);
float startX = rectF.left + AndroidUtilities.dpf2(4.5f);
float startY = rectF.top + AndroidUtilities.dpf2(4.5f) - AndroidUtilities.dp(1);
float stopX = rectF.right - AndroidUtilities.dp(3);
float stopY = rectF.bottom - AndroidUtilities.dp(1) - AndroidUtilities.dp(3);
if (cross) {
stopX = startX + (stopX - startX) * progress;
stopY = startY + (stopY - startY) * progress;
} else {
startX = startX + (stopX - startX) * (1f - progress);
startY = startY + (stopY - startY) * (1f - progress);
}
canvas.drawLine(startX, startY - paint.getStrokeWidth(), stopX, stopY - paint.getStrokeWidth(), xRefPaint);
canvas.drawLine(startX, startY, stopX, stopY, paint);
canvas.restore();
}
@Override
public void setAlpha(int i) {
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
iconDrawable.setBounds(left, top, right, bottom);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
iconDrawable.setColorFilter(colorFilter);
}
@Override
public int getIntrinsicHeight() {
return iconDrawable.getIntrinsicHeight();
}
@Override
public int getIntrinsicWidth() {
return iconDrawable.getIntrinsicWidth();
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public void setColorKey(String colorKey) {
this.colorKey = colorKey;
}
}

View File

@ -0,0 +1,35 @@
package org.telegram.ui.Components;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.style.ReplacementSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.telegram.messenger.AndroidUtilities;
public class DotDividerSpan extends ReplacementSpan {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
int color;
int topPadding;
@Override
public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) {
return AndroidUtilities.dp(3);
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
if (color != paint.getColor()) {
p.setColor(paint.getColor());
}
float radius = AndroidUtilities.dpf2(3) / 2f;
canvas.drawCircle(x + radius, (bottom - top) / 2 + topPadding, radius, p);
}
public void setTopPadding(int topPadding) {
this.topPadding = topPadding;
}
}

View File

@ -8,8 +8,11 @@
package org.telegram.ui.Components;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
@ -28,6 +31,7 @@ import androidx.annotation.Nullable;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
@ -42,6 +46,7 @@ import android.widget.EditText;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
@ -65,6 +70,7 @@ public class EditTextBoldCursor extends EditText {
private Object editor;
private GradientDrawable gradientDrawable;
private SubstringLayoutAnimator hintAnimator;
private Runnable invalidateRunnable = new Runnable() {
@Override
@ -391,9 +397,26 @@ public class EditTextBoldCursor extends EditText {
}
public void setHintText(CharSequence text) {
setHintText(text, false);
}
public void setHintText(CharSequence text, boolean animated) {
if (text == null) {
text = "";
}
if (getMeasuredWidth() == 0) {
animated = false;
}
if (animated) {
if (hintAnimator == null) {
hintAnimator = new SubstringLayoutAnimator(this);
}
hintAnimator.create(hintLayout, hint, text, getPaint());
} else {
if (hintAnimator != null) {
hintAnimator.cancel();
}
}
hint = text;
if (getMeasuredWidth() != 0) {
text = TextUtils.ellipsize(text, getPaint(), getMeasuredWidth(), TextUtils.TruncateAt.END);
@ -561,7 +584,14 @@ public class EditTextBoldCursor extends EditText {
getPaint().setColor(hintColor);
getPaint().setAlpha((int) (255 * hintAlpha * (Color.alpha(hintColor) / 255.0f)));
}
hintLayout.draw(canvas);
if (hintAnimator != null && hintAnimator.animateTextChange) {
canvas.save();
canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
hintAnimator.draw(canvas, getPaint());
canvas.restore();
} else {
hintLayout.draw(canvas);
}
getPaint().setColor(oldColor);
canvas.restore();
}

View File

@ -126,11 +126,6 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not
return false;
}
@Override
public void setImeOptions(int imeOptions) {
super.setImeOptions(imeOptions);
}
@Override
protected void onLineCountChanged(int oldLineCount, int newLineCount) {
EditTextEmoji.this.onLineCountChanged(oldLineCount, newLineCount);

View File

@ -1027,6 +1027,15 @@ public class EmbedBottomSheet extends BottomSheet {
dismissInternal();
}
@Override
public void dismissInternal() {
super.dismissInternal();
if (orientationEventListener != null) {
orientationEventListener.disable();
orientationEventListener = null;
}
}
public void exitFromPip() {
if (webView == null || pipVideoView == null) {
return;

View File

@ -26,15 +26,24 @@ import org.telegram.ui.ActionBar.Theme;
public class EmptyTextProgressView extends FrameLayout {
private TextView textView;
private RadialProgressView progressBar;
private View progressView;
private boolean inLayout;
private int showAtPos;
public EmptyTextProgressView(Context context) {
this(context, null);
}
public EmptyTextProgressView(Context context, View progressView) {
super(context);
progressBar = new RadialProgressView(context);
addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
if (progressView == null) {
progressView = new RadialProgressView(context);
addView(progressView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
} else {
addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
}
this.progressView = progressView;
textView = new TextView(context);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
@ -44,7 +53,7 @@ public class EmptyTextProgressView extends FrameLayout {
textView.setText(LocaleController.getString("NoResult", R.string.NoResult));
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
progressBar.setAlpha(0f);
progressView.setAlpha(0f);
textView.setAlpha(0f);
setOnTouchListener((v, event) -> true);
@ -52,12 +61,12 @@ public class EmptyTextProgressView extends FrameLayout {
public void showProgress() {
textView.animate().alpha(0f).setDuration(150).start();
progressBar.animate().alpha(1f).setDuration(150).start();
progressView.animate().alpha(1f).setDuration(150).start();
}
public void showTextView() {
textView.animate().alpha(1f).setDuration(150).start();
progressBar.animate().alpha(0f).setDuration(150).start();
progressView.animate().alpha(0f).setDuration(150).start();
}
public void setText(String text) {
@ -69,7 +78,9 @@ public class EmptyTextProgressView extends FrameLayout {
}
public void setProgressBarColor(int color) {
progressBar.setProgressColor(color);
if (progressView instanceof RadialProgressView) {
((RadialProgressView) progressView).setProgressColor(color);
}
}
public void setTopImage(int resId) {

View File

@ -556,6 +556,7 @@ public class FilterTabsView extends FrameLayout {
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setSelected(currentTab != null && selectedTabId != -1 && currentTab.id == selectedTabId);
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK, LocaleController.getString("AccDescrOpenMenu2", R.string.AccDescrOpenMenu2)));

View File

@ -5,6 +5,7 @@ import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.SystemClock;
@ -12,6 +13,7 @@ import android.view.View;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.SharedConfig;
import org.telegram.ui.ActionBar.Theme;
public class FlickerLoadingView extends View {
@ -22,6 +24,10 @@ public class FlickerLoadingView extends View {
public final static int AUDIO_TYPE = 4;
public final static int LINKS_TYPE = 5;
public final static int USERS_TYPE = 6;
public final static int DIALOG_CELL_TYPE = 7;
public final static int CALL_LOG_TYPE = 8;
public final static int INVITE_LINKS_TYPE = 9;
public final static int USERS2_TYPE = 10;
private int gradientWidth;
private LinearGradient gradient;
@ -40,10 +46,13 @@ public class FlickerLoadingView extends View {
private boolean isSingleCell;
private int viewType;
private int paddingTop;
private int paddingLeft;
private String colorKey1 = Theme.key_windowBackgroundWhite;
private String colorKey2 = Theme.key_windowBackgroundGray;
private String colorKey3;
private int itemsCount = 1;
public void setViewType(int type) {
this.viewType = type;
@ -77,7 +86,11 @@ public class FlickerLoadingView extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isSingleCell) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getCellHeight(MeasureSpec.getSize(widthMeasureSpec)), MeasureSpec.EXACTLY));
if (itemsCount > 1 && MeasureSpec.getSize(heightMeasureSpec) > 0) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.min(MeasureSpec.getSize(heightMeasureSpec), getCellHeight(MeasureSpec.getSize(widthMeasureSpec)) * itemsCount), MeasureSpec.EXACTLY));
} else {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getCellHeight(MeasureSpec.getSize(widthMeasureSpec)), MeasureSpec.EXACTLY));
}
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@ -98,7 +111,7 @@ public class FlickerLoadingView extends View {
paint.setShader(gradient);
}
int h = 0;
int h = paddingTop;
if (useHeaderOffset) {
h += AndroidUtilities.dp(32);
if (colorKey3 != null) {
@ -106,8 +119,42 @@ public class FlickerLoadingView extends View {
}
canvas.drawRect(0,0, getMeasuredWidth(), AndroidUtilities.dp(32), colorKey3 != null ? headerPaint : paint);
}
if (getViewType() == DIALOG_TYPE) {
while (h < getMeasuredHeight()) {
if (getViewType() == DIALOG_CELL_TYPE) {
int k = 0;
while (h <= getMeasuredHeight()) {
int childH = getCellHeight(getMeasuredWidth());
int r = AndroidUtilities.dp(28);
canvas.drawCircle(checkRtl(AndroidUtilities.dp(10) + r), h + (childH >> 1), r, paint);
rectF.set(AndroidUtilities.dp(76), h + AndroidUtilities.dp(16), AndroidUtilities.dp(148), h + AndroidUtilities.dp(24));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
rectF.set(AndroidUtilities.dp(76), h + AndroidUtilities.dp(38), AndroidUtilities.dp(268), h + AndroidUtilities.dp(46));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
if (SharedConfig.useThreeLinesLayout) {
rectF.set(AndroidUtilities.dp(76), h + AndroidUtilities.dp(46 + 8), AndroidUtilities.dp(220), h + AndroidUtilities.dp(46 + 8 + 8));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
}
if (showDate) {
rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(16), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(24));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
}
h += getCellHeight(getMeasuredWidth());
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
} else if (getViewType() == DIALOG_TYPE) {
int k = 0;
while (h <= getMeasuredHeight()) {
int r = AndroidUtilities.dp(25);
canvas.drawCircle(checkRtl(AndroidUtilities.dp(9) + r), h + (AndroidUtilities.dp(78) >> 1), r, paint);
@ -126,7 +173,8 @@ public class FlickerLoadingView extends View {
}
h += getCellHeight(getMeasuredWidth());
if (isSingleCell) {
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
@ -148,7 +196,8 @@ public class FlickerLoadingView extends View {
}
}
} else if (getViewType() == 3) {
while (h < getMeasuredHeight()) {
int k = 0;
while (h <= getMeasuredHeight()) {
rectF.set(AndroidUtilities.dp(12), h + AndroidUtilities.dp(8), AndroidUtilities.dp(52), h + AndroidUtilities.dp(48));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
@ -168,12 +217,14 @@ public class FlickerLoadingView extends View {
}
h += getCellHeight(getMeasuredWidth());
if (isSingleCell) {
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
} else if (getViewType() == 4) {
while (h < getMeasuredHeight()) {
int k = 0;
while (h <= getMeasuredHeight()) {
int radius = AndroidUtilities.dp(44) >> 1;
canvas.drawCircle(checkRtl(AndroidUtilities.dp(12) + radius), h + AndroidUtilities.dp(6) + radius, radius, paint);
@ -192,12 +243,14 @@ public class FlickerLoadingView extends View {
}
h += getCellHeight(getMeasuredWidth());
if (isSingleCell) {
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
} else if (getViewType() == 5) {
while (h < getMeasuredHeight()) {
int k = 0;
while (h <= getMeasuredHeight()) {
rectF.set(AndroidUtilities.dp(10), h + AndroidUtilities.dp(11), AndroidUtilities.dp(62), h + AndroidUtilities.dp(11 + 52));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
@ -221,20 +274,22 @@ public class FlickerLoadingView extends View {
}
h += getCellHeight(getMeasuredWidth());
if (isSingleCell) {
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
} else if (getViewType() == 6) {
while (h < getMeasuredHeight()) {
} else if (getViewType() == 6 || getViewType() == USERS2_TYPE) {
int k = 0;
while (h <= getMeasuredHeight()) {
int r = AndroidUtilities.dp(23);
canvas.drawCircle(checkRtl(AndroidUtilities.dp(9) + r), h + (AndroidUtilities.dp(64) >> 1), r, paint);
canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(9) + r), h + (AndroidUtilities.dp(64) >> 1), r, paint);
rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(17), AndroidUtilities.dp(260), h + AndroidUtilities.dp(25));
rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(17), paddingLeft + AndroidUtilities.dp(260), h + AndroidUtilities.dp(25));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(39), AndroidUtilities.dp(140), h + AndroidUtilities.dp(47));
rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(39), paddingLeft + AndroidUtilities.dp(140), h + AndroidUtilities.dp(47));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
@ -245,7 +300,61 @@ public class FlickerLoadingView extends View {
}
h += getCellHeight(getMeasuredWidth());
if (isSingleCell) {
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
} else if (getViewType() == CALL_LOG_TYPE) {
int k = 0;
while (h <= getMeasuredHeight()) {
int r = AndroidUtilities.dp(23);
canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(11) + r), h + (AndroidUtilities.dp(64) >> 1), r, paint);
rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(17), paddingLeft + AndroidUtilities.dp(140), h + AndroidUtilities.dp(25));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(39), paddingLeft + AndroidUtilities.dp(260), h + AndroidUtilities.dp(47));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
if (showDate) {
rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(20), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(28));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
}
h += getCellHeight(getMeasuredWidth());
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
} else if (getViewType() == INVITE_LINKS_TYPE) {
int k = 0;
while (h <= getMeasuredHeight()) {
int childH = getCellHeight(getMeasuredWidth());
int r = AndroidUtilities.dp(32) / 2;
canvas.drawCircle(checkRtl(AndroidUtilities.dp(35)), h + (childH >> 1), r, paint);
rectF.set(AndroidUtilities.dp(72), h + AndroidUtilities.dp(16), AndroidUtilities.dp(268), h + AndroidUtilities.dp(24));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
rectF.set(AndroidUtilities.dp(72), h + AndroidUtilities.dp(38), AndroidUtilities.dp(140), h + AndroidUtilities.dp(46));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
if (showDate) {
rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(16), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(24));
checkRtl(rectF);
canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint);
}
h += getCellHeight(getMeasuredWidth());
k++;
if (isSingleCell && k >= itemsCount) {
break;
}
}
@ -289,7 +398,9 @@ public class FlickerLoadingView extends View {
}
private int getCellHeight(int width) {
if (getViewType() == DIALOG_TYPE) {
if (getViewType() == DIALOG_CELL_TYPE) {
return AndroidUtilities.dp((SharedConfig.useThreeLinesLayout ? 78 : 72) + 1);
} else if (getViewType() == DIALOG_TYPE) {
return AndroidUtilities.dp(78) + 1;
} else if (getViewType() == PHOTOS_TYPE) {
int photoWidth = (width - (AndroidUtilities.dp(2) * (getColumnsCount() - 1))) / getColumnsCount();
@ -302,6 +413,12 @@ public class FlickerLoadingView extends View {
return AndroidUtilities.dp(80);
} else if (getViewType() == USERS_TYPE) {
return AndroidUtilities.dp(64);
} else if (getViewType() == INVITE_LINKS_TYPE) {
return AndroidUtilities.dp(66);
} else if (getViewType() == USERS2_TYPE) {
return AndroidUtilities.dp(58);
} else if (getViewType() == CALL_LOG_TYPE) {
return AndroidUtilities.dp(61);
}
return 0;
}
@ -317,4 +434,18 @@ public class FlickerLoadingView extends View {
public void skipDrawItemsCount(int i) {
skipDrawItemsCount = i;
}
public void setPaddingTop(int t) {
paddingTop = t;
invalidate();
}
public void setPaddingLeft(int paddingLeft) {
this.paddingLeft = paddingLeft;
invalidate();
}
public void setItemsCount(int i) {
this.itemsCount = i;
}
}

View File

@ -2,7 +2,6 @@ package org.telegram.ui.Components;
import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.UpdateAppearance;
import androidx.annotation.NonNull;

View File

@ -12,6 +12,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -43,6 +44,7 @@ import android.widget.TextView;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.LocationController;
import org.telegram.messenger.MediaController;
@ -73,7 +75,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
private ImageView playButton;
private PlayPauseDrawable playPauseDrawable;
private TextView titleTextView;
private AudioPlayerAlert.ClippingTextViewSwitcher titleTextView;
private AudioPlayerAlert.ClippingTextViewSwitcher subtitleTextView;
private AnimatorSet animatorSet;
private BaseFragment fragment;
@ -81,6 +83,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
private FrameLayout frameLayout;
private View shadow;
private View selector;
private RLottieImageView importingImageView;
private RLottieImageView muteButton;
private RLottieDrawable muteDrawable;
private ImageView closeButton;
@ -90,6 +93,8 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
private boolean isMuted;
private int currentProgress = -1;
private MessageObject lastMessageObject;
private float topPadding;
private boolean visible;
@ -116,8 +121,9 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
};
private int animationIndex = -1;
boolean checkCallAfterAnimation;
boolean checkPlayerAfterAnimation;
private boolean checkCallAfterAnimation;
private boolean checkPlayerAfterAnimation;
private boolean checkImportAfterAnimation;
@Override
public void onAudioSettingsChanged() {
@ -135,6 +141,10 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
public boolean drawOverlayed() {
return currentStyle == 3;
}
public interface FragmentContextViewDelegate {
void onAnimation(boolean start, boolean show);
}
@ -191,13 +201,44 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
});
titleTextView = new TextView(context);
titleTextView.setMaxLines(1);
titleTextView.setLines(1);
titleTextView.setSingleLine(true);
titleTextView.setEllipsize(TextUtils.TruncateAt.END);
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
importingImageView = new RLottieImageView(context);
importingImageView.setScaleType(ImageView.ScaleType.CENTER);
importingImageView.setAutoRepeat(true);
importingImageView.setAnimation(R.raw.import_progress, 30, 30);
importingImageView.setBackground(Theme.createCircleDrawable(AndroidUtilities.dp(22), Theme.getColor(Theme.key_inappPlayerPlayPause)));
addView(importingImageView, LayoutHelper.createFrame(22, 22, Gravity.TOP | Gravity.LEFT, 7, 7, 0, 0));
titleTextView = new AudioPlayerAlert.ClippingTextViewSwitcher(context) {
@Override
protected TextView createTextView() {
TextView textView = new TextView(context);
textView.setMaxLines(1);
textView.setLines(1);
textView.setSingleLine(true);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
if (currentStyle == 0 || currentStyle == 2) {
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_inappPlayerTitle));
textView.setTypeface(Typeface.DEFAULT);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
} else if (currentStyle == 4) {
textView.setGravity(Gravity.TOP | Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_inappPlayerPerformer));
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
} else if (currentStyle == 1 || currentStyle == 3) {
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_returnToCallText));
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
}
return textView;
}
};
addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35, 0, 36, 0));
subtitleTextView = new AudioPlayerAlert.ClippingTextViewSwitcher(context) {
@ -243,6 +284,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
} else {
MediaController.getInstance().setPlaybackSpeed(isMusic, 1.8f);
}
playbackSpeedChanged(currentPlaybackSpeed <= 1);
});
updatePlaybackButton();
}
@ -291,7 +333,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
@Override
public boolean onTouchEvent(MotionEvent event) {
if (currentStyle == 3) {
if (currentStyle == 3 || currentStyle == 1) {
VoIPService service = VoIPService.getSharedInstance();
if (service == null) {
AndroidUtilities.cancelRunOnUIThread(pressRunnable);
@ -310,7 +352,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
scheduled = false;
} else if (pressed) {
isMuted = true;
if (muteDrawable.setCustomEndFrame(isMuted ? 15 : 29)) {
if (muteDrawable.setCustomEndFrame(15)) {
if (isMuted) {
muteDrawable.setCurrentFrame(0);
} else {
@ -356,12 +398,14 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
if (voIPService == null) {
return;
}
ChatObject.Call call = voIPService.groupCall;
AccountInstance accountInstance = AccountInstance.getInstance(voIPService.getAccount());
TLRPC.Chat chat = voIPService.getChat();
TLRPC.TL_groupCallParticipant participant = call.participants.get(accountInstance.getUserConfig().getClientUserId());
if (participant != null && !participant.can_self_unmute && participant.muted && !ChatObject.canManageCalls(chat)) {
return;
if (voIPService.groupCall != null) {
AccountInstance accountInstance = AccountInstance.getInstance(voIPService.getAccount());
ChatObject.Call call = voIPService.groupCall;
TLRPC.Chat chat = voIPService.getChat();
TLRPC.TL_groupCallParticipant participant = call.participants.get(accountInstance.getUserConfig().getClientUserId());
if (participant != null && !participant.can_self_unmute && participant.muted && !ChatObject.canManageCalls(chat)) {
return;
}
}
isMuted = !voIPService.isMicMute();
@ -483,12 +527,9 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
fragment.showDialog(new SharingLocationsAlert(getContext(), this::openSharingLocation));
}
} else if (currentStyle == 3) {
// long d = Theme.getFragmentContextViewWavesDrawable().getRippleFinishedDelay();
// AndroidUtilities.runOnUIThread(() -> {
if (VoIPService.getSharedInstance() != null && getContext() instanceof LaunchActivity) {
GroupCallActivity.create((LaunchActivity) getContext(), AccountInstance.getInstance(VoIPService.getSharedInstance().getAccount()));
}
// }, d);
if (VoIPService.getSharedInstance() != null && getContext() instanceof LaunchActivity) {
GroupCallActivity.create((LaunchActivity) getContext(), AccountInstance.getInstance(VoIPService.getSharedInstance().getAccount()));
}
} else if (currentStyle == 4) {
if (fragment.getParentActivity() == null) {
return;
@ -499,6 +540,11 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
return;
}
VoIPHelper.startCall(chatActivity.getMessagesController().getChat(call.chatId), false, fragment.getParentActivity());
} else if (currentStyle == 5) {
ImportingAlert importingAlert = new ImportingAlert(getContext(), (ChatActivity) fragment);
importingAlert.setOnHideListener(dialog -> checkImport(false));
fragment.showDialog(importingAlert);
checkImport(false);
}
});
}
@ -562,7 +608,9 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
} else {
if (VoIPService.getSharedInstance() != null && !VoIPService.getSharedInstance().isHangingUp() && VoIPService.getSharedInstance().getCallState() != VoIPService.STATE_WAITING_INCOMING) {
show = true;
} else if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getGroupCall() != null) {
} else if (fragment instanceof ChatActivity && fragment.getSendMessagesHelper().getImportingHistory(((ChatActivity) fragment).getDialogId()) != null && !isPlayingVoice()) {
show = true;
} else if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getGroupCall() != null && !GroupCallPip.isShowing() && !isPlayingVoice()) {
show = true;
} else {
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
@ -589,11 +637,15 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
protected void playbackSpeedChanged(boolean enabled) {
}
private void updateStyle(int style) {
if (currentStyle == style) {
return;
}
if (currentStyle == 3) {
if (currentStyle == 3 || currentStyle == 1) {
Theme.getFragmentContextViewWavesDrawable().removeParent(this);
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().unregisterStateListener(this);
@ -601,7 +653,6 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
currentStyle = style;
if (avatars != null) {
avatars.setStyle(currentStyle);
avatars.setLayoutParams(LayoutHelper.createFrame(108, getStyleHeight(), Gravity.LEFT | Gravity.TOP));
@ -613,21 +664,59 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
updatePaddings();
setTopPadding(AndroidUtilities.dp2(getStyleHeight()));
}
if (style == 0 || style == 2) {
if (style == 5) {
selector.setBackground(Theme.getSelectorDrawable(false));
frameLayout.setBackgroundColor(Theme.getColor(Theme.key_inappPlayerBackground));
frameLayout.setTag(Theme.key_inappPlayerBackground);
titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
titleTextView.setTextColor(Theme.getColor(Theme.key_inappPlayerTitle));
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_inappPlayerTitle));
textView.setTypeface(Typeface.DEFAULT);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
}
titleTextView.setTag(Theme.key_inappPlayerTitle);
subtitleTextView.setVisibility(GONE);
joinButton.setVisibility(GONE);
closeButton.setVisibility(GONE);
playButton.setVisibility(GONE);
muteButton.setVisibility(GONE);
avatars.setVisibility(GONE);
importingImageView.setVisibility(VISIBLE);
importingImageView.playAnimation();
closeButton.setContentDescription(LocaleController.getString("AccDescrClosePlayer", R.string.AccDescrClosePlayer));
if (playbackSpeedButton != null) {
playbackSpeedButton.setVisibility(GONE);
}
titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35, 0, 36, 0));
} else if (style == 0 || style == 2) {
selector.setBackground(Theme.getSelectorDrawable(false));
frameLayout.setBackgroundColor(Theme.getColor(Theme.key_inappPlayerBackground));
frameLayout.setTag(Theme.key_inappPlayerBackground);
subtitleTextView.setVisibility(GONE);
joinButton.setVisibility(GONE);
closeButton.setVisibility(VISIBLE);
playButton.setVisibility(VISIBLE);
muteButton.setVisibility(GONE);
importingImageView.setVisibility(GONE);
importingImageView.stopAnimation();
avatars.setVisibility(GONE);
titleTextView.setTypeface(Typeface.DEFAULT);
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_inappPlayerTitle));
textView.setTypeface(Typeface.DEFAULT);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
}
titleTextView.setTag(Theme.key_inappPlayerTitle);
if (style == 0) {
playButton.setLayoutParams(LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0));
titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35, 0, 36, 0));
@ -649,13 +738,22 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
subtitleTextView.setVisibility(VISIBLE);
joinButton.setVisibility(VISIBLE);
titleTextView.setTextColor(Theme.getColor(Theme.key_inappPlayerPerformer));
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setGravity(Gravity.TOP | Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_inappPlayerPerformer));
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
}
titleTextView.setTag(Theme.key_inappPlayerPerformer);
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
titleTextView.setPadding(0, 0, 0, 0);
titleTextView.setText(LocaleController.getString("VoipGroupVoiceChat", R.string.VoipGroupVoiceChat));
titleTextView.setGravity(Gravity.TOP | Gravity.LEFT);
titleTextView.setText(LocaleController.getString("VoipGroupVoiceChat", R.string.VoipGroupVoiceChat), false);
importingImageView.setVisibility(GONE);
importingImageView.stopAnimation();
avatars.setVisibility(VISIBLE);
updateAvatars(false);
@ -667,37 +765,42 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
} else if (style == 1 || style == 3) {
selector.setBackground(null);
updateCallTitle();
avatars.setVisibility(VISIBLE);
if (style == 3) {
updateGroupCallTitle();
muteButton.setVisibility(VISIBLE);
avatars.setVisibility(VISIBLE);
updateAvatars(false);
isMuted = VoIPService.getSharedInstance() != null && VoIPService.getSharedInstance().isMicMute();
muteDrawable.setCustomEndFrame(isMuted ? 15 : 29);
muteDrawable.setCurrentFrame(muteDrawable.getCustomEndFrame() - 1, false, true);
muteButton.invalidate();
frameLayout.setBackground(null);
Theme.getFragmentContextViewWavesDrawable().addParent(this);
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().registerStateListener(this);
}
invalidate();
} else {
frameLayout.setTag(Theme.key_returnToCallBackground);
titleTextView.setText(LocaleController.getString("ReturnToCall", R.string.ReturnToCall));
muteButton.setVisibility(GONE);
avatars.setVisibility(GONE);
frameLayout.setBackgroundColor(Theme.getColor(Theme.key_returnToCallBackground));
}
titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
titleTextView.setTextColor(Theme.getColor(Theme.key_returnToCallText));
updateAvatars(false);
muteButton.setVisibility(VISIBLE);
isMuted = VoIPService.getSharedInstance() != null && VoIPService.getSharedInstance().isMicMute();
muteDrawable.setCustomEndFrame(isMuted ? 15 : 29);
muteDrawable.setCurrentFrame(muteDrawable.getCustomEndFrame() - 1, false, true);
muteButton.invalidate();
frameLayout.setBackground(null);
importingImageView.setVisibility(GONE);
importingImageView.stopAnimation();
Theme.getFragmentContextViewWavesDrawable().addParent(this);
invalidate();
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_returnToCallText));
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
}
titleTextView.setTag(Theme.key_returnToCallText);
closeButton.setVisibility(GONE);
playButton.setVisibility(GONE);
subtitleTextView.setVisibility(GONE);
joinButton.setVisibility(GONE);
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 2));
titleTextView.setPadding(AndroidUtilities.dp(112), 0, AndroidUtilities.dp(112), 0);
if (playbackSpeedButton != null) {
@ -726,6 +829,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.messagePlayingDidStart);
NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.groupCallUpdated);
NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.groupCallTypingsUpdated);
NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.historyImportProgressChanged);
}
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.messagePlayingSpeedChanged);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didStartedCall);
@ -735,7 +839,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.groupCallVisibilityChanged);
}
if (currentStyle == 3) {
if (currentStyle == 3 || currentStyle == 1) {
Theme.getFragmentContextViewWavesDrawable().removeParent(this);
}
if (VoIPService.getSharedInstance() != null) {
@ -761,6 +865,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.messagePlayingDidStart);
NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.groupCallUpdated);
NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.groupCallTypingsUpdated);
NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.historyImportProgressChanged);
}
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.messagePlayingSpeedChanged);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didStartedCall);
@ -774,6 +879,8 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
if (VoIPService.getSharedInstance() != null && !VoIPService.getSharedInstance().isHangingUp() && VoIPService.getSharedInstance().getCallState() != VoIPService.STATE_WAITING_INCOMING && !GroupCallPip.isShowing()) {
checkCall(true);
} else if (fragment instanceof ChatActivity && fragment.getSendMessagesHelper().getImportingHistory(((ChatActivity) fragment).getDialogId()) != null && !isPlayingVoice()) {
checkImport(true);
} else if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getGroupCall() != null && !GroupCallPip.isShowing() && !isPlayingVoice()) {
checkCall(true);
} else {
@ -782,7 +889,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
if (currentStyle == 3) {
if (currentStyle == 3 || currentStyle == 1) {
Theme.getFragmentContextViewWavesDrawable().addParent(this);
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().registerStateListener(this);
@ -822,7 +929,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
} else if (id == NotificationCenter.messagePlayingDidStart || id == NotificationCenter.messagePlayingPlayStateChanged || id == NotificationCenter.messagePlayingDidReset || id == NotificationCenter.didEndCall) {
if (currentStyle == 3 || currentStyle == 4) {
if (currentStyle == 1 || currentStyle == 3 || currentStyle == 4) {
checkCall(false);
}
checkPlayer(false);
@ -853,13 +960,18 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
ChatObject.Call call = ((ChatActivity) fragment).getGroupCall();
if (call != null) {
if (call.call.participants_count == 0) {
subtitleTextView.setText(LocaleController.getString("MembersTalkingNobody", R.string.MembersTalkingNobody));
subtitleTextView.setText(LocaleController.getString("MembersTalkingNobody", R.string.MembersTalkingNobody), false);
} else {
subtitleTextView.setText(LocaleController.formatPluralString("Participants", call.call.participants_count));
subtitleTextView.setText(LocaleController.formatPluralString("Participants", call.call.participants_count), false);
}
}
updateAvatars(true);
}
} else if (id == NotificationCenter.historyImportProgressChanged) {
if (currentStyle == 1 || currentStyle == 3 || currentStyle == 4) {
checkCall(false);
}
checkImport(false);
} else if (id == NotificationCenter.messagePlayingSpeedChanged) {
updatePlaybackButton();
} else if (id == NotificationCenter.webRtcMicAmplitudeEvent) {
@ -994,10 +1106,17 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
String fullString = String.format(str, liveLocation, param);
int start = fullString.indexOf(liveLocation);
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(fullString);
titleTextView.setEllipsize(TextUtils.TruncateAt.END);
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setEllipsize(TextUtils.TruncateAt.END);
}
TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, Theme.getColor(Theme.key_inappPlayerPerformer));
stringBuilder.setSpan(span, start, start + liveLocation.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
titleTextView.setText(stringBuilder);
titleTextView.setText(stringBuilder, false);
} else {
checkLocationRunnable.run();
checkLocationString();
@ -1072,16 +1191,22 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
lastString = fullString;
int start = fullString.indexOf(liveLocation);
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(fullString);
titleTextView.setEllipsize(TextUtils.TruncateAt.END);
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setEllipsize(TextUtils.TruncateAt.END);
}
if (start >= 0) {
TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, Theme.getColor(Theme.key_inappPlayerPerformer));
stringBuilder.setSpan(span, start, start + liveLocation.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
titleTextView.setText(stringBuilder);
titleTextView.setText(stringBuilder, false);
}
private void checkPlayer(boolean create) {
if (visible && (currentStyle == 3 || currentStyle == 4 && !isPlayingVoice())) {
if (visible && (currentStyle == 1 || currentStyle == 3 || (currentStyle == 4 || currentStyle == 5) && !isPlayingVoice())) {
return;
}
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
@ -1091,6 +1216,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
create = true;
}
}
boolean wasVisible = visible;
if (messageObject == null || messageObject.getId() == 0 || messageObject.isVideo()) {
lastMessageObject = null;
boolean callAvailable = supportsCalls && VoIPService.getSharedInstance() != null && !VoIPService.getSharedInstance().isHangingUp() && VoIPService.getSharedInstance().getCallState() != VoIPService.STATE_WAITING_INCOMING && !GroupCallPip.isShowing();
@ -1134,9 +1260,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
checkCall(false);
} else if (checkPlayerAfterAnimation) {
checkPlayer(false);
} else if (checkImportAfterAnimation) {
checkImport(false);
}
checkCallAfterAnimation = false;
checkPlayerAfterAnimation = false;
checkImportAfterAnimation = false;
}
}
});
@ -1191,9 +1320,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
checkCall(false);
} else if (checkPlayerAfterAnimation) {
checkPlayer(false);
} else if (checkImportAfterAnimation) {
checkImport(false);
}
checkCallAfterAnimation = false;
checkPlayerAfterAnimation = false;
checkImportAfterAnimation = false;
}
}
});
@ -1220,7 +1352,15 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
titleTextView.setPadding(0, 0, AndroidUtilities.dp(44), 0);
stringBuilder = new SpannableStringBuilder(String.format("%s %s", messageObject.getMusicAuthor(), messageObject.getMusicTitle()));
titleTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
}
updatePlaybackButton();
} else {
isMusic = true;
@ -1239,46 +1379,41 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
titleTextView.setPadding(0, 0, 0, 0);
}
stringBuilder = new SpannableStringBuilder(String.format("%s - %s", messageObject.getMusicAuthor(), messageObject.getMusicTitle()));
titleTextView.setEllipsize(TextUtils.TruncateAt.END);
for (int i = 0; i < 2; i++) {
TextView textView = i == 0 ? titleTextView.getTextView() : titleTextView.getNextTextView();
if (textView == null) {
continue;
}
textView.setEllipsize(TextUtils.TruncateAt.END);
}
}
TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, Theme.getColor(Theme.key_inappPlayerPerformer));
stringBuilder.setSpan(span, 0, messageObject.getMusicAuthor().length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
titleTextView.setText(stringBuilder);
titleTextView.setText(stringBuilder, !create && wasVisible);
}
}
}
private boolean isPlayingVoice() {
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
return messageObject != null && messageObject.isVoice();
}
public void checkCall(boolean create) {
public void checkImport(boolean create) {
if (!(fragment instanceof ChatActivity) || visible && (currentStyle == 1 || currentStyle == 3)) {
return;
}
ChatActivity chatActivity = (ChatActivity) fragment;
SendMessagesHelper.ImportingHistory importingHistory = chatActivity.getSendMessagesHelper().getImportingHistory(chatActivity.getDialogId());
View fragmentView = fragment.getFragmentView();
if (!create && fragmentView != null) {
if (fragmentView.getParent() == null || ((View) fragmentView.getParent()).getVisibility() != VISIBLE) {
create = true;
}
}
boolean callAvailable;
boolean groupActive;
if (GroupCallPip.isShowing()) {
callAvailable = false;
groupActive = false;
} else {
callAvailable = !GroupCallActivity.groupCallUiVisible && supportsCalls && VoIPService.getSharedInstance() != null && !VoIPService.getSharedInstance().isHangingUp();
if (VoIPService.getSharedInstance() != null && VoIPService.getSharedInstance().groupCall != null && VoIPService.getSharedInstance().groupCall.call instanceof TLRPC.TL_groupCallDiscarded) {
callAvailable = false;
}
groupActive = false;
if (!isPlayingVoice() && !GroupCallActivity.groupCallUiVisible && supportsCalls && !callAvailable && fragment instanceof ChatActivity && ((ChatActivity) fragment).getGroupCall() != null) {
callAvailable = true;
groupActive = true;
}
Dialog dialog = chatActivity.getVisibleDialog();
if ((isPlayingVoice() || chatActivity.shouldShowImport() || dialog instanceof ImportingAlert && !((ImportingAlert) dialog).isDismissed()) && importingHistory != null) {
importingHistory = null;
}
if (!callAvailable) {
if (visible && (create && currentStyle == -1 || currentStyle == 4 || currentStyle == 3)) {
if (importingHistory == null) {
if (visible && (create && currentStyle == -1 || currentStyle == 5)) {
visible = false;
if (create) {
if (getVisibility() != GONE) {
@ -1307,15 +1442,165 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
checkCall(false);
} else if (checkPlayerAfterAnimation) {
checkPlayer(false);
} else if (checkImportAfterAnimation) {
checkImport(false);
}
checkCallAfterAnimation = false;
checkPlayerAfterAnimation = false;
checkImportAfterAnimation = false;
}
}
});
animatorSet.start();
}
} else if (currentStyle == -1 || currentStyle == 4 || currentStyle == 3) {
} else if (currentStyle == -1 || currentStyle == 5) {
visible = false;
setVisibility(GONE);
}
} else {
if (currentStyle != 5 && animatorSet != null && !create) {
checkImportAfterAnimation = true;
return;
}
int prevStyle = currentStyle;
updateStyle(5);
if (create && topPadding == 0) {
updatePaddings();
setTopPadding(AndroidUtilities.dp2(getStyleHeight()));
if (delegate != null) {
delegate.onAnimation(true, true);
delegate.onAnimation(false, true);
}
}
if (!visible) {
if (!create) {
if (animatorSet != null) {
animatorSet.cancel();
animatorSet = null;
}
animationIndex = NotificationCenter.getInstance(account).setAnimationInProgress(animationIndex, null);
animatorSet = new AnimatorSet();
if (additionalContextView != null && additionalContextView.getVisibility() == VISIBLE) {
((LayoutParams) getLayoutParams()).topMargin = -AndroidUtilities.dp(getStyleHeight() + additionalContextView.getStyleHeight());
} else {
((LayoutParams) getLayoutParams()).topMargin = -AndroidUtilities.dp(getStyleHeight());
}
if (delegate != null) {
delegate.onAnimation(true, true);
}
animatorSet.playTogether(ObjectAnimator.ofFloat(this, "topPadding", AndroidUtilities.dp2(getStyleHeight())));
animatorSet.setDuration(200);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
NotificationCenter.getInstance(account).onAnimationFinish(animationIndex);
if (animatorSet != null && animatorSet.equals(animation)) {
if (delegate != null) {
delegate.onAnimation(false, true);
}
animatorSet = null;
if (checkCallAfterAnimation) {
checkCall(false);
} else if (checkPlayerAfterAnimation) {
checkPlayer(false);
} else if (checkImportAfterAnimation) {
checkImport(false);
}
checkCallAfterAnimation = false;
checkPlayerAfterAnimation = false;
checkImportAfterAnimation = false;
}
}
});
animatorSet.start();
}
visible = true;
setVisibility(VISIBLE);
}
if (currentProgress != importingHistory.uploadProgress) {
currentProgress = importingHistory.uploadProgress;
titleTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ImportUploading", R.string.ImportUploading, importingHistory.uploadProgress)), false);
}
}
}
private boolean isPlayingVoice() {
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
return messageObject != null && messageObject.isVoice();
}
public void checkCall(boolean create) {
if (visible && currentStyle == 5 && (VoIPService.getSharedInstance() == null || VoIPService.getSharedInstance().isHangingUp())) {
return;
}
View fragmentView = fragment.getFragmentView();
if (!create && fragmentView != null) {
if (fragmentView.getParent() == null || ((View) fragmentView.getParent()).getVisibility() != VISIBLE) {
create = true;
}
}
boolean callAvailable;
boolean groupActive;
if (GroupCallPip.isShowing()) {
callAvailable = false;
groupActive = false;
} else {
callAvailable = !GroupCallActivity.groupCallUiVisible && supportsCalls && VoIPService.getSharedInstance() != null && !VoIPService.getSharedInstance().isHangingUp();
if (VoIPService.getSharedInstance() != null && VoIPService.getSharedInstance().groupCall != null && VoIPService.getSharedInstance().groupCall.call instanceof TLRPC.TL_groupCallDiscarded) {
callAvailable = false;
}
groupActive = false;
if (!isPlayingVoice() && !GroupCallActivity.groupCallUiVisible && supportsCalls && !callAvailable && fragment instanceof ChatActivity) {
ChatObject.Call call = ((ChatActivity) fragment).getGroupCall();
if (call != null && call.call.participants_count > 0) {
callAvailable = true;
groupActive = true;
}
}
}
if (!callAvailable) {
if (visible && (create && currentStyle == -1 || currentStyle == 4 || currentStyle == 3 || currentStyle == 1)) {
visible = false;
if (create) {
if (getVisibility() != GONE) {
setVisibility(GONE);
}
setTopPadding(0);
} else {
if (animatorSet != null) {
animatorSet.cancel();
animatorSet = null;
}
final int currentAccount = account;
animationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(animationIndex, null);
animatorSet = new AnimatorSet();
animatorSet.playTogether(ObjectAnimator.ofFloat(this, "topPadding", 0));
animatorSet.setDuration(220);
animatorSet.setInterpolator(CubicBezierInterpolator.DEFAULT);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
NotificationCenter.getInstance(currentAccount).onAnimationFinish(animationIndex);
if (animatorSet != null && animatorSet.equals(animation)) {
setVisibility(GONE);
animatorSet = null;
if (checkCallAfterAnimation) {
checkCall(false);
} else if (checkPlayerAfterAnimation) {
checkPlayer(false);
} else if (checkImportAfterAnimation) {
checkImport(false);
}
checkCallAfterAnimation = false;
checkPlayerAfterAnimation = false;
checkImportAfterAnimation = false;
}
}
});
animatorSet.start();
}
} else if (currentStyle == -1 || currentStyle == 4 || currentStyle == 3 || currentStyle == 1) {
visible = false;
setVisibility(GONE);
}
@ -1364,9 +1649,9 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
ChatObject.Call call = ((ChatActivity) fragment).getGroupCall();
if (call.call.participants_count == 0) {
subtitleTextView.setText(LocaleController.getString("MembersTalkingNobody", R.string.MembersTalkingNobody));
subtitleTextView.setText(LocaleController.getString("MembersTalkingNobody", R.string.MembersTalkingNobody), false);
} else {
subtitleTextView.setText(LocaleController.formatPluralString("Participants", call.call.participants_count));
subtitleTextView.setText(LocaleController.formatPluralString("Participants", call.call.participants_count), false);
}
updateAvatars(avatars.wasDraw && updateAnimated);
@ -1375,6 +1660,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
updateAvatars(currentStyle == 3);
updateStyle(3);
} else {
updateAvatars(currentStyle == 1);
updateStyle(1);
}
}
@ -1406,9 +1692,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
checkCall(false);
} else if (checkPlayerAfterAnimation) {
checkPlayer(false);
} else if (checkImportAfterAnimation) {
checkImport(false);
}
checkCallAfterAnimation = false;
checkPlayerAfterAnimation = false;
checkImportAfterAnimation = false;
}
});
animatorSet.start();
@ -1430,6 +1719,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
ChatObject.Call call;
TLRPC.User userCall;
if (avatars.transitionProgressAnimator == null) {
int currentAccount;
if (currentStyle == 4) {
@ -1441,12 +1731,15 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
call = null;
currentAccount = account;
}
userCall = null;
} else {
if (VoIPService.getSharedInstance() != null) {
call = VoIPService.getSharedInstance().groupCall;
userCall = fragment instanceof ChatActivity ? null : VoIPService.getSharedInstance().getUser();
currentAccount = VoIPService.getSharedInstance().getAccount();
} else {
call = null;
userCall = null;
currentAccount = account;
}
}
@ -1458,13 +1751,17 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
avatars.setObject(a, currentAccount, null);
}
}
avatars.commitTransition(animated);
} else if (userCall != null) {
avatars.setObject(0, currentAccount, userCall);
for (int a = 1; a < 3; a++) {
avatars.setObject(a, currentAccount, null);
}
} else {
for (int a = 0; a < 3; a++) {
avatars.setObject(a, currentAccount, null);
}
avatars.commitTransition(animated);
}
avatars.commitTransition(animated);
if (currentStyle == 4 && call != null) {
int N = Math.min(3, call.sortedParticipants.size());
@ -1510,7 +1807,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
return;
}
boolean clipped = false;
if (currentStyle == 3 && drawOverlay) {
if ((currentStyle == 3 || currentStyle == 1) && drawOverlay) {
Theme.getFragmentContextViewWavesDrawable().updateState(wasDraw);
float progress = topPadding / AndroidUtilities.dp((getStyleHeight()));
@ -1547,15 +1844,15 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
@Override
public void invalidate() {
super.invalidate();
if (currentStyle == 3) {
if (currentStyle == 3 || currentStyle == 1) {
if (getParent() != null) {
((View) getParent()).invalidate();
}
}
}
public int getCurrentStyle() {
return currentStyle;
public boolean isCallStyle() {
return currentStyle == 3 || currentStyle == 1;
}
@Override
@ -1584,35 +1881,29 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
@Override
public void onStateChanged(int state) {
updateGroupCallTitle();
updateCallTitle();
}
private void updateGroupCallTitle() {
private void updateCallTitle() {
VoIPService service = VoIPService.getSharedInstance();
if (service != null && currentStyle == 3) {
if (service != null && (currentStyle == 1 || currentStyle == 3)) {
int currentCallState = service.getCallState();
if (currentCallState == VoIPService.STATE_WAIT_INIT || currentCallState == VoIPService.STATE_WAIT_INIT_ACK || currentCallState == VoIPService.STATE_CREATING || currentCallState == VoIPService.STATE_RECONNECTING) {
titleTextView.setText(LocaleController.getString("VoipGroupConnecting", R.string. VoipGroupConnecting));
titleTextView.setText(LocaleController.getString("VoipGroupConnecting", R.string. VoipGroupConnecting), false);
} else if (service.getChat() != null) {
if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getCurrentChat() != null && ((ChatActivity) fragment).getCurrentChat().id == service.getChat().id) {
titleTextView.setText(LocaleController.getString("VoipGroupViewVoiceChat", R.string.VoipGroupViewVoiceChat));
titleTextView.setText(LocaleController.getString("VoipGroupViewVoiceChat", R.string.VoipGroupViewVoiceChat), false);
} else {
titleTextView.setText(service.getChat().title);
titleTextView.setText(service.getChat().title, false);
}
} else if (service.getUser() != null) {
TLRPC.User user = service.getUser();
if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getCurrentUser() != null && ((ChatActivity) fragment).getCurrentUser().id == user.id) {
titleTextView.setText(LocaleController.getString("ReturnToCall", R.string.ReturnToCall));
} else {
titleTextView.setText(ContactsController.formatName(user.first_name, user.last_name));
}
}
}
}
public float hotspotX;
public float hotspotY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
hotspotX = ev.getX();
hotspotY = ev.getY();
}
return super.onInterceptTouchEvent(ev);
}
}

View File

@ -1,7 +1,6 @@
package org.telegram.ui.Components;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
@ -10,12 +9,9 @@ import android.graphics.PorterDuffXfermode;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.os.SystemClock;
import android.view.View;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
@ -300,10 +296,15 @@ public class FragmentContextViewWavesDrawable {
if (currentCallState == VoIPService.STATE_WAIT_INIT || currentCallState == VoIPService.STATE_WAIT_INIT_ACK || currentCallState == VoIPService.STATE_CREATING || currentCallState == VoIPService.STATE_RECONNECTING) {
setState(FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_CONNECTING, animated);
} else {
TLRPC.TL_groupCallParticipant participant = VoIPService.getSharedInstance().groupCall.participants.get(AccountInstance.getInstance(VoIPService.getSharedInstance().getAccount()).getUserConfig().getClientUserId());
if (participant != null && !participant.can_self_unmute && participant.muted && !ChatObject.canManageCalls(VoIPService.getSharedInstance().getChat())) {
VoIPService.getSharedInstance().setMicMute(true, false, false);
setState(FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTED_BY_ADMIN, animated);
if (VoIPService.getSharedInstance().groupCall != null) {
TLRPC.TL_groupCallParticipant participant = VoIPService.getSharedInstance().groupCall.participants.get(AccountInstance.getInstance(VoIPService.getSharedInstance().getAccount()).getUserConfig().getClientUserId());
if (participant != null && !participant.can_self_unmute && participant.muted && !ChatObject.canManageCalls(VoIPService.getSharedInstance().getChat())) {
VoIPService.getSharedInstance().setMicMute(true, false, false);
setState(FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTED_BY_ADMIN, animated);
} else {
boolean isMuted = VoIPService.getSharedInstance().isMicMute();
setState(isMuted ? FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTE : FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_UNMUTE, animated);
}
} else {
boolean isMuted = VoIPService.getSharedInstance().isMicMute();
setState(isMuted ? FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTE : FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_UNMUTE, animated);

View File

@ -70,31 +70,12 @@ import java.util.HashSet;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class GroupVoipInviteAlert extends BottomSheet {
public class GroupVoipInviteAlert extends UsersAlertBase {
private FrameLayout frameLayout;
private RecyclerListView listView;
private SearchAdapter searchListViewAdapter;
private ListAdapter listViewAdapter;
private Drawable shadowDrawable;
private View shadow;
private AnimatorSet shadowAnimation;
private StickerEmptyView emptyView;
private FlickerLoadingView flickerLoadingView;
private SearchField searchView;
private RectF rect = new RectF();
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private String linkToCopy;
private int scrollOffsetY;
private final SearchAdapter searchAdapter;
private int delayResults;
private float colorProgress;
private int backgroundColor;
private TLRPC.Chat currentChat;
private TLRPC.ChatFull info;
@ -129,323 +110,37 @@ public class GroupVoipInviteAlert extends BottomSheet {
void needOpenSearch(MotionEvent ev, EditTextBoldCursor editText);
}
@SuppressWarnings("FieldCanBeLocal")
private class SearchField extends FrameLayout {
private View searchBackground;
private ImageView searchIconImageView;
private ImageView clearSearchImageView;
private CloseProgressDrawable2 progressDrawable;
private EditTextBoldCursor searchEditText;
private View backgroundView;
public SearchField(Context context) {
super(context);
searchBackground = new View(context);
searchBackground.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(18), Theme.getColor(Theme.key_voipgroup_searchBackground)));
addView(searchBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 14, 11, 14, 0));
searchIconImageView = new ImageView(context);
searchIconImageView.setScaleType(ImageView.ScaleType.CENTER);
searchIconImageView.setImageResource(R.drawable.smiles_inputsearch);
searchIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_voipgroup_searchPlaceholder), PorterDuff.Mode.MULTIPLY));
addView(searchIconImageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 16, 11, 0, 0));
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_voipgroup_searchPlaceholder), PorterDuff.Mode.MULTIPLY));
addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 11, 14, 0));
clearSearchImageView.setOnClickListener(v -> {
searchEditText.setText("");
AndroidUtilities.showKeyboard(searchEditText);
});
searchEditText = new EditTextBoldCursor(context) {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
MotionEvent e = MotionEvent.obtain(event);
e.setLocation(e.getRawX(), e.getRawY() - containerView.getTranslationY());
if (e.getAction() == MotionEvent.ACTION_UP) {
e.setAction(MotionEvent.ACTION_CANCEL);
}
listView.dispatchTouchEvent(e);
e.recycle();
return super.dispatchTouchEvent(event);
}
};
searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
searchEditText.setHintTextColor(Theme.getColor(Theme.key_voipgroup_searchPlaceholder));
searchEditText.setTextColor(Theme.getColor(Theme.key_voipgroup_searchText));
searchEditText.setBackgroundDrawable(null);
searchEditText.setPadding(0, 0, 0, 0);
searchEditText.setMaxLines(1);
searchEditText.setLines(1);
searchEditText.setSingleLine(true);
searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
searchEditText.setHint(LocaleController.getString("VoipGroupSearchMembers", R.string.VoipGroupSearchMembers));
searchEditText.setCursorColor(Theme.getColor(Theme.key_voipgroup_searchText));
searchEditText.setCursorSize(AndroidUtilities.dp(20));
searchEditText.setCursorWidth(1.5f);
addView(searchEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.LEFT | Gravity.TOP, 16 + 38, 9, 16 + 30, 0));
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
boolean show = searchEditText.length() > 0;
boolean showed = clearSearchImageView.getAlpha() != 0;
if (show != showed) {
clearSearchImageView.animate()
.alpha(show ? 1.0f : 0.0f)
.setDuration(150)
.scaleX(show ? 1.0f : 0.1f)
.scaleY(show ? 1.0f : 0.1f)
.start();
}
String text = searchEditText.getText().toString();
int oldItemsCount = listView.getAdapter() == null ? 0 : listView.getAdapter().getItemCount();
searchListViewAdapter.searchUsers(text);
if (TextUtils.isEmpty(text) && listView != null && listView.getAdapter() != listViewAdapter) {
listView.setAnimateEmptyView(false, 0);
listView.setAdapter(listViewAdapter);
listView.setAnimateEmptyView(true, 0);
if (oldItemsCount == 0) {
showItemsAnimated(0);
}
}
flickerLoadingView.setVisibility(View.VISIBLE);
}
});
searchEditText.setOnEditorActionListener((v, actionId, event) -> {
if (event != null && (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH || event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
AndroidUtilities.hideKeyboard(searchEditText);
}
return false;
});
}
public void hideKeyboard() {
AndroidUtilities.hideKeyboard(searchEditText);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
delegate.needOpenSearch(ev, searchEditText);
return super.onInterceptTouchEvent(ev);
}
@Override
protected void updateColorKeys() {
keyScrollUp = Theme.key_voipgroup_scrollUp;
keyListSelector = Theme.key_voipgroup_listSelector;
keySearchBackground = Theme.key_voipgroup_searchBackground;
keyInviteMembersBackground = Theme.key_voipgroup_inviteMembersBackground;
keyListViewBackground = Theme.key_voipgroup_listViewBackground;
keyActionBarUnscrolled = Theme.key_voipgroup_actionBarUnscrolled;
keyNameText = Theme.key_voipgroup_nameText;
keyLastSeenText = Theme.key_voipgroup_lastSeenText;
keyLastSeenTextUnscrolled = Theme.key_voipgroup_lastSeenTextUnscrolled;
keySearchPlaceholder = Theme.key_voipgroup_searchPlaceholder;
keySearchText = Theme.key_voipgroup_searchText;
keySearchIcon = Theme.key_voipgroup_mutedIcon;
keySearchIconUnscrolled = Theme.key_voipgroup_mutedIconUnscrolled;
}
public static final Property<GroupVoipInviteAlert, Float> COLOR_PROGRESS = new AnimationProperties.FloatProperty<GroupVoipInviteAlert>("colorProgress") {
@Override
public void setValue(GroupVoipInviteAlert object, float value) {
object.setColorProgress(value);
}
@Override
public Float get(GroupVoipInviteAlert object) {
return object.getColorProgress();
}
};
public GroupVoipInviteAlert(final Context context, int account, TLRPC.Chat chat, TLRPC.ChatFull chatFull, SparseArray<TLRPC.TL_groupCallParticipant> participants, HashSet<Integer> invited) {
super(context, false);
super(context, false, account);
setDimBehindAlpha(75);
currentAccount = account;
currentChat = chat;
info = chatFull;
ignoredUsers = participants;
invitedUsers = invited;
shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate();
containerView = new FrameLayout(context) {
private boolean ignoreLayout = false;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int totalHeight = MeasureSpec.getSize(heightMeasureSpec);
if (Build.VERSION.SDK_INT >= 21) {
ignoreLayout = true;
setPadding(backgroundPaddingLeft, AndroidUtilities.statusBarHeight, backgroundPaddingLeft, 0);
ignoreLayout = false;
}
int availableHeight = totalHeight - getPaddingTop();
int padding;
if (keyboardVisible) {
padding = AndroidUtilities.dp(8);
setAllowNestedScroll(false);
} else {
padding = availableHeight - (availableHeight / 5 * 3) + AndroidUtilities.dp(8);
setAllowNestedScroll(true);
}
if (listView.getPaddingTop() != padding) {
ignoreLayout = true;
listView.setPadding(0, padding, 0, 0);
ignoreLayout = false;
}
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
updateLayout();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getY() < scrollOffsetY) {
dismiss();
return true;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
return !isDismissed() && super.onTouchEvent(e);
}
@Override
public void requestLayout() {
if (ignoreLayout) {
return;
}
super.requestLayout();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
int y = scrollOffsetY - backgroundPaddingTop + AndroidUtilities.dp(6);
int top = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(13);
int height = getMeasuredHeight() + AndroidUtilities.dp(30) + backgroundPaddingTop;
int statusBarHeight = 0;
float radProgress = 1.0f;
if (Build.VERSION.SDK_INT >= 21) {
top += AndroidUtilities.statusBarHeight;
y += AndroidUtilities.statusBarHeight;
height -= AndroidUtilities.statusBarHeight;
if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight * 2) {
int diff = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight * 2 - top - backgroundPaddingTop);
top -= diff;
height += diff;
radProgress = 1.0f - Math.min(1.0f, (diff * 2) / (float) AndroidUtilities.statusBarHeight);
}
if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight) {
statusBarHeight = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight - top - backgroundPaddingTop);
}
}
shadowDrawable.setBounds(0, top, getMeasuredWidth(), height);
shadowDrawable.draw(canvas);
if (radProgress != 1.0f) {
Theme.dialogs_onlineCirclePaint.setColor(backgroundColor);
rect.set(backgroundPaddingLeft, backgroundPaddingTop + top, getMeasuredWidth() - backgroundPaddingLeft, backgroundPaddingTop + top + AndroidUtilities.dp(24));
canvas.drawRoundRect(rect, AndroidUtilities.dp(12) * radProgress, AndroidUtilities.dp(12) * radProgress, Theme.dialogs_onlineCirclePaint);
}
int w = AndroidUtilities.dp(36);
rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4));
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_voipgroup_scrollUp));
canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint);
if (statusBarHeight > 0) {
int finalColor = Color.argb(0xff, (int) (Color.red(backgroundColor) * 0.8f), (int) (Color.green(backgroundColor) * 0.8f), (int) (Color.blue(backgroundColor) * 0.8f));
Theme.dialogs_onlineCirclePaint.setColor(finalColor);
canvas.drawRect(backgroundPaddingLeft, AndroidUtilities.statusBarHeight - statusBarHeight, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight, Theme.dialogs_onlineCirclePaint);
}
canvas.restore();
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.clipRect(0, getPaddingTop(), getMeasuredWidth(), getMeasuredHeight());
super.dispatchDraw(canvas);
canvas.restore();
}
};
containerView.setWillNotDraw(false);
containerView.setClipChildren(false);
containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);
frameLayout = new FrameLayout(context);
searchView = new SearchField(context);
frameLayout.addView(searchView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
flickerLoadingView = new FlickerLoadingView(context);
flickerLoadingView.setViewType(FlickerLoadingView.USERS_TYPE);
flickerLoadingView.showDate(false);
flickerLoadingView.setUseHeaderOffset(true);
flickerLoadingView.setColors(Theme.key_voipgroup_inviteMembersBackground, Theme.key_voipgroup_searchBackground, Theme.key_voipgroup_actionBarUnscrolled);
emptyView = new StickerEmptyView(context, flickerLoadingView, StickerEmptyView.STICKER_TYPE_SEARCH);
emptyView.addView(flickerLoadingView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0,0,2,0,0));
emptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult));
emptyView.subtitle.setText(LocaleController.getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2));
emptyView.setVisibility(View.GONE);
emptyView.setAnimateLayoutChange(true);
emptyView.showProgress(true, false);
emptyView.setColors(Theme.key_voipgroup_nameText, Theme.key_voipgroup_lastSeenText, Theme.key_voipgroup_inviteMembersBackground, Theme.key_voipgroup_searchBackground);
containerView.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 58 + 4, 0, 0));
searchListViewAdapter = new SearchAdapter(context);
listView = new RecyclerListView(context) {
@Override
protected boolean allowSelectChildAtPosition(float x, float y) {
return y >= scrollOffsetY + AndroidUtilities.dp(48) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
}
@Override
public void setTranslationY(float translationY) {
super.setTranslationY(translationY);
int[] ii = new int[2];
getLocationInWindow(ii);
}
@Override
protected boolean emptyViewIsVisible() {
if (getAdapter() == null) {
return false;
}
return getAdapter().getItemCount() <= 2;
}
};
listView.setTag(13);
listView.setPadding(0, 0, 0, AndroidUtilities.dp(48));
listView.setClipToPadding(false);
listView.setHideIfEmpty(false);
listView.setSelectorDrawableColor(Theme.getColor(Theme.key_voipgroup_listSelector));
FillLastLinearLayoutManager layoutManager = new FillLastLinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false, AndroidUtilities.dp(8), listView);
layoutManager.setBind(false);
listView.setLayoutManager(layoutManager);
listView.setHorizontalScrollBarEnabled(false);
listView.setVerticalScrollBarEnabled(false);
containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0));
listView.setAdapter(listViewAdapter = new ListAdapter(context));
currentChat = chat;
info = chatFull;
ignoredUsers = participants;
invitedUsers = invited;
listView.setOnItemClickListener((view, position) -> {
if (position == addNewRow) {
delegate.copyInviteLink();
@ -458,89 +153,18 @@ public class GroupVoipInviteAlert extends BottomSheet {
delegate.inviteUser(cell.getUserId());
}
});
listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
updateLayout();
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (scrollOffsetY + backgroundPaddingTop + AndroidUtilities.dp(13) < AndroidUtilities.statusBarHeight * 2 && listView.canScrollVertically(1)) {
View child = listView.getChildAt(0);
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findViewHolderForAdapterPosition(0);
if (holder != null && holder.itemView.getTop() > 0) {
listView.smoothScrollBy(0, holder.itemView.getTop());
}
}
}
}
});
FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.TOP | Gravity.LEFT);
frameLayoutParams.topMargin = AndroidUtilities.dp(58);
shadow = new View(context);
shadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine));
shadow.setAlpha(0.0f);
shadow.setTag(1);
containerView.addView(shadow, frameLayoutParams);
containerView.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 58, Gravity.LEFT | Gravity.TOP));
setColorProgress(0.0f);
searchListViewAdapter = searchAdapter = new SearchAdapter(context);
listView.setAdapter(listViewAdapter = new ListAdapter(context));
loadChatParticipants(0, 200);
updateRows();
listView.setEmptyView(emptyView);
listView.setAnimateEmptyView(true, 0);
}
private float getColorProgress() {
return colorProgress;
}
private void setColorProgress(float progress) {
colorProgress = progress;
backgroundColor = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_inviteMembersBackground), Theme.getColor(Theme.key_voipgroup_listViewBackground), progress, 1.0f);
shadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor, PorterDuff.Mode.MULTIPLY));
frameLayout.setBackgroundColor(backgroundColor);
navBarColor = backgroundColor;
listView.setGlowColor(backgroundColor);
int color = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_lastSeenTextUnscrolled), Theme.getColor(Theme.key_voipgroup_lastSeenText), progress, 1.0f);
int color2 = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_mutedIconUnscrolled), Theme.getColor(Theme.key_voipgroup_mutedIcon), progress, 1.0f);//
for (int a = 0, N = listView.getChildCount(); a < N; a++) {
View child = listView.getChildAt(a);
if (child instanceof GroupCallTextCell) {
GroupCallTextCell cell = (GroupCallTextCell) child;
cell.setColors(color, color);
} else if (child instanceof GroupCallUserCell) {
GroupCallUserCell cell = (GroupCallUserCell) child;
cell.setGrayIconColor(shadow.getTag() != null ? Theme.key_voipgroup_mutedIcon : Theme.key_voipgroup_mutedIconUnscrolled, color2);
}
}
containerView.invalidate();
listView.invalidate();
container.invalidate();
setColorProgress(0.0f);
}
public void setDelegate(GroupVoipInviteAlertDelegate groupVoipInviteAlertDelegate) {
delegate = groupVoipInviteAlertDelegate;
}
private int getCurrentTop() {
if (listView.getChildCount() != 0) {
View child = listView.getChildAt(0);
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child);
if (holder != null) {
return listView.getPaddingTop() - (holder.getAdapterPosition() == 0 && child.getTop() >= 0 ? child.getTop() : 0);
}
}
return -1000;
}
private void updateRows() {
addNewRow = -1;
emptyRow = -1;
@ -581,107 +205,6 @@ public class GroupVoipInviteAlert extends BottomSheet {
lastRow = rowCount++;
}
@Override
protected boolean canDismissWithSwipe() {
return false;
}
@Override
public void dismiss() {
AndroidUtilities.hideKeyboard(searchView.searchEditText);
super.dismiss();
}
@SuppressLint("NewApi")
private void updateLayout() {
if (listView.getChildCount() <= 0) {
return;
}
View child = listView.getChildAt(0);
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child);
int top = child.getTop() - AndroidUtilities.dp(8);
int newOffset = top > 0 && holder != null && holder.getAdapterPosition() == 0 ? top : 0;
if (top >= 0 && holder != null && holder.getAdapterPosition() == 0) {
newOffset = top;
runShadowAnimation(false);
} else {
runShadowAnimation(true);
}
if (scrollOffsetY != newOffset) {
listView.setTopGlowOffset(scrollOffsetY = (int) (newOffset));
frameLayout.setTranslationY(scrollOffsetY);
emptyView.setTranslationY(scrollOffsetY);
containerView.invalidate();
}
}
private void runShadowAnimation(final boolean show) {
if (show && shadow.getTag() != null || !show && shadow.getTag() == null) {
shadow.setTag(show ? null : 1);
if (show) {
shadow.setVisibility(View.VISIBLE);
}
if (shadowAnimation != null) {
shadowAnimation.cancel();
}
shadowAnimation = new AnimatorSet();
shadowAnimation.playTogether(ObjectAnimator.ofFloat(shadow, View.ALPHA, show ? 1.0f : 0.0f));
shadowAnimation.setDuration(150);
shadowAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (shadowAnimation != null && shadowAnimation.equals(animation)) {
if (!show) {
shadow.setVisibility(View.INVISIBLE);
}
shadowAnimation = null;
}
}
@Override
public void onAnimationCancel(Animator animation) {
if (shadowAnimation != null && shadowAnimation.equals(animation)) {
shadowAnimation = null;
}
}
});
shadowAnimation.start();
}
}
private void showItemsAnimated(int from) {
if (!isShowing()) {
return;
}
listView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
listView.getViewTreeObserver().removeOnPreDrawListener(this);
int n = listView.getChildCount();
AnimatorSet animatorSet = new AnimatorSet();
for (int i = 0; i < n; i++) {
View child = listView.getChildAt(i);
int position = listView.getChildAdapterPosition(child);
if (position < from) {
continue;
}
if (position == 1 && listView.getAdapter() == searchListViewAdapter && child instanceof GraySectionCell) {
child = ((GraySectionCell) child).getTextView();
}
child.setAlpha(0);
int s = Math.min(listView.getMeasuredHeight(), Math.max(0, child.getTop()));
int delay = (int) ((s / (float) listView.getMeasuredHeight()) * 100);
ObjectAnimator a = ObjectAnimator.ofFloat(child, View.ALPHA, 0, 1f);
a.setStartDelay(delay);
a.setDuration(200);
animatorSet.playTogether(a);
}
animatorSet.start();
return true;
}
});
}
private void loadChatParticipants(int offset, int count) {
if (loadingUsers) {
return;
@ -690,7 +213,8 @@ public class GroupVoipInviteAlert extends BottomSheet {
loadChatParticipants(offset, count, true);
}
private void loadChatParticipants(int offset, int count, boolean reset) {
protected void loadChatParticipants(int offset, int count, boolean reset) {
if (!ChatObject.isChannel(currentChat)) {
loadingUsers = false;
participants.clear();
@ -1364,4 +888,13 @@ public class GroupVoipInviteAlert extends BottomSheet {
}
}
@Override
protected void search(String text) {
searchAdapter.searchUsers(text);
}
@Override
protected void onSearchViewTouched(MotionEvent ev, EditTextBoldCursor searchEditText) {
delegate.needOpenSearch(ev, searchEditText);
}
}

View File

@ -236,7 +236,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes
}
}
if (!changed) {
if (newCount != currentPhotos.size() || currentObjects.indexOf(currentObject) == -1) {
if (newCount != currentPhotos.size() || !currentObjects.contains(currentObject)) {
changed = true;
} else {
int newImageIndex = currentObjects.indexOf(currentObject);

View File

@ -11,6 +11,7 @@ package org.telegram.ui.Components;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
@ -136,12 +137,12 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega
delegate = imageUpdaterDelegate;
}
public void openMenu(boolean hasAvatar, Runnable onDeleteAvatar) {
public void openMenu(boolean hasAvatar, Runnable onDeleteAvatar, DialogInterface.OnDismissListener onDismiss) {
if (parentFragment == null || parentFragment.getParentActivity() == null) {
return;
}
if (useAttachMenu) {
openAttachMenu();
openAttachMenu(onDismiss);
return;
}
BottomSheet.Builder builder = new BottomSheet.Builder(parentFragment.getParentActivity());
@ -196,6 +197,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega
}
});
BottomSheet sheet = builder.create();
sheet.setOnHideListener(onDismiss);
parentFragment.showDialog(sheet);
if (hasAvatar) {
sheet.setItemColor(items.size() - 1, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon));
@ -296,7 +298,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega
parentFragment.presentFragment(fragment);
}
private void openAttachMenu() {
private void openAttachMenu(DialogInterface.OnDismissListener onDismissListener) {
if (parentFragment == null || parentFragment.getParentActivity() == null) {
return;
}
@ -308,6 +310,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega
AndroidUtilities.hideKeyboard(parentFragment.getFragmentView().findFocus());
}
chatAttachAlert.init();
chatAttachAlert.setOnHideListener(onDismissListener);
parentFragment.showDialog(chatAttachAlert);
}
@ -874,7 +877,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega
return;
}
uploadingVideo = (String) args[1];
parentFragment.getFileLoader().uploadFile(uploadingVideo, false, false, (int) convertingVideo.videoEditedInfo.estimatedSize, ConnectionsManager.FileTypeVideo);
parentFragment.getFileLoader().uploadFile(uploadingVideo, false, false, (int) convertingVideo.videoEditedInfo.estimatedSize, ConnectionsManager.FileTypeVideo, false);
}
}
}

View File

@ -0,0 +1,255 @@
/*
* This is the source code of Telegram for Android v. 5.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2018.
*/
package org.telegram.ui.Components;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SendMessagesHelper;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity;
public class ImportingAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate {
private TextView[] importCountTextView = new TextView[2];
private TextView percentTextView;
private LineProgressView lineProgressView;
private ChatActivity parentFragment;
private RLottieImageView imageView;
private BottomSheetCell cell;
private boolean compteled;
private RLottieDrawable completedDrawable;
private TextView[] infoTextView = new TextView[2];
public static class BottomSheetCell extends FrameLayout {
private View background;
private TextView textView;
private RLottieImageView imageView;
private LinearLayout linearLayout;
public BottomSheetCell(Context context) {
super(context);
background = new View(context);
background.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed)));
addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16));
linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
imageView = new RLottieImageView(context);
imageView.setBackground(Theme.createCircleDrawable(AndroidUtilities.dp(20), Theme.getColor(Theme.key_featuredStickers_buttonText)));
imageView.setScaleType(ImageView.ScaleType.CENTER);
imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addButton), PorterDuff.Mode.MULTIPLY));
imageView.setAnimation(R.raw.import_check, 26, 26);
imageView.setScaleX(0.8f);
imageView.setScaleY(0.8f);
linearLayout.addView(imageView, LayoutHelper.createLinear(20, 20, Gravity.CENTER_VERTICAL));
textView = new TextView(context);
textView.setLines(1);
textView.setSingleLine(true);
textView.setGravity(Gravity.CENTER_HORIZONTAL);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setGravity(Gravity.CENTER);
textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 10, 0, 0, 0));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY));
}
public void setTextColor(int color) {
textView.setTextColor(color);
}
public void setGravity(int gravity) {
textView.setGravity(gravity);
}
public void setText(CharSequence text) {
textView.setText(text);
}
}
@SuppressWarnings("FieldCanBeLocal")
private final Runnable onFinishCallback = () -> {
if (compteled) {
imageView.getAnimatedDrawable().setAutoRepeat(0);
imageView.setAnimation(completedDrawable);
imageView.playAnimation();
}
};
public ImportingAlert(final Context context, ChatActivity chatActivity) {
super(context, false);
setApplyBottomPadding(false);
setApplyTopPadding(false);
parentFragment = chatActivity;
FrameLayout frameLayout = new FrameLayout(context);
setCustomView(frameLayout);
TextView textView = new TextView(context);
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
textView.setText(LocaleController.getString("ImportImportingTitle", R.string.ImportImportingTitle));
textView.setSingleLine(true);
textView.setEllipsize(TextUtils.TruncateAt.END);
frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 17, 20, 17, 0));
completedDrawable = new RLottieDrawable(R.raw.import_finish, "" + R.raw.import_finish, AndroidUtilities.dp(120), AndroidUtilities.dp(120), false, null);
completedDrawable.setAllowDecodeSingleFrame(true);
imageView = new RLottieImageView(context);
imageView.setAutoRepeat(true);
imageView.setAnimation(R.raw.import_loop, 120, 120);
imageView.playAnimation();
frameLayout.addView(imageView, LayoutHelper.createFrame(160, 160, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 17, 79, 17, 0));
imageView.getAnimatedDrawable().setOnFinishCallback(onFinishCallback, 178);
SendMessagesHelper.ImportingHistory importingHistory = parentFragment.getSendMessagesHelper().getImportingHistory(parentFragment.getDialogId());
percentTextView = new TextView(context);
percentTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
percentTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 24);
percentTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
percentTextView.setText(String.format("%d%%", importingHistory.uploadProgress));
frameLayout.addView(percentTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 17, 262, 17, 0));
lineProgressView = new LineProgressView(getContext());
lineProgressView.setProgress(importingHistory.uploadProgress / 100.0f, false);
lineProgressView.setProgressColor(Theme.getColor(Theme.key_featuredStickers_addButton));
lineProgressView.setBackColor(Theme.getColor(Theme.key_dialogLineProgressBackground));
frameLayout.addView(lineProgressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 4, Gravity.LEFT | Gravity.TOP, 50, 307, 50, 0));
cell = new BottomSheetCell(context);
cell.setBackground(null);
cell.setText(LocaleController.getString("ImportDone", R.string.ImportDone));
cell.setVisibility(View.INVISIBLE);
cell.background.setOnClickListener(v -> dismiss());
cell.background.setPivotY(AndroidUtilities.dp(48));
cell.background.setScaleY(0.04f);
frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.LEFT | Gravity.TOP, 34, 247, 34, 0));
for (int a = 0; a < 2; a++) {
importCountTextView[a] = new TextView(context);
importCountTextView[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
importCountTextView[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
importCountTextView[a].setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
frameLayout.addView(importCountTextView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 17, 340, 17, 0));
infoTextView[a] = new TextView(context);
infoTextView[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
infoTextView[a].setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
infoTextView[a].setGravity(Gravity.CENTER_HORIZONTAL);
frameLayout.addView(infoTextView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 30, 368, 30, 44));
if (a == 0) {
infoTextView[a].setText(LocaleController.getString("ImportImportingInfo", R.string.ImportImportingInfo));
importCountTextView[a].setText(LocaleController.formatString("ImportCount", R.string.ImportCount, AndroidUtilities.formatFileSize(importingHistory.getUploadedCount()), AndroidUtilities.formatFileSize(importingHistory.getTotalCount())));
} else {
infoTextView[a].setText(LocaleController.getString("ImportDoneInfo", R.string.ImportDoneInfo));
importCountTextView[a].setText(LocaleController.getString("ImportDoneTitle", R.string.ImportDoneTitle));
infoTextView[a].setAlpha(0.0f);
infoTextView[a].setTranslationY(AndroidUtilities.dp(10));
importCountTextView[a].setAlpha(0.0f);
importCountTextView[a].setTranslationY(AndroidUtilities.dp(10));
}
}
parentFragment.getNotificationCenter().addObserver(this, NotificationCenter.historyImportProgressChanged);
}
public void setCompteled() {
compteled = true;
imageView.setAutoRepeat(false);
cell.setVisibility(View.VISIBLE);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(250);
animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT);
animatorSet.playTogether(
ObjectAnimator.ofFloat(percentTextView, View.ALPHA, 0.0f),
ObjectAnimator.ofFloat(percentTextView, View.TRANSLATION_Y, -AndroidUtilities.dp(10)),
ObjectAnimator.ofFloat(infoTextView[0], View.ALPHA, 0.0f),
ObjectAnimator.ofFloat(infoTextView[0], View.TRANSLATION_Y, -AndroidUtilities.dp(10)),
ObjectAnimator.ofFloat(importCountTextView[0], View.ALPHA, 0.0f),
ObjectAnimator.ofFloat(importCountTextView[0], View.TRANSLATION_Y, -AndroidUtilities.dp(10)),
ObjectAnimator.ofFloat(infoTextView[1], View.ALPHA, 1.0f),
ObjectAnimator.ofFloat(infoTextView[1], View.TRANSLATION_Y, 0),
ObjectAnimator.ofFloat(importCountTextView[1], View.ALPHA, 1.0f),
ObjectAnimator.ofFloat(importCountTextView[1], View.TRANSLATION_Y, 0),
ObjectAnimator.ofFloat(lineProgressView, View.ALPHA, 0),
ObjectAnimator.ofFloat(cell.linearLayout, View.TRANSLATION_Y, AndroidUtilities.dp(8), 0)
);
cell.background.animate().scaleY(1.0f).setInterpolator(new OvershootInterpolator(1.02f)).setDuration(250).start();
cell.imageView.animate().scaleY(1.0f).scaleX(1.0f).setInterpolator(new OvershootInterpolator(1.02f)).setDuration(250).start();
cell.imageView.playAnimation();
animatorSet.start();
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.historyImportProgressChanged) {
if (args.length > 1) {
dismiss();
return;
}
long dialogId = parentFragment.getDialogId();
SendMessagesHelper.ImportingHistory importingHistory = parentFragment.getSendMessagesHelper().getImportingHistory(dialogId);
if (importingHistory == null) {
setCompteled();
return;
}
if (!compteled) {
double timeToEndAnimation = (180 - imageView.getAnimatedDrawable().getCurrentFrame()) * 16.6 + 3000;
if (timeToEndAnimation >= importingHistory.timeUntilFinish) {
imageView.setAutoRepeat(false);
compteled = true;
}
}
percentTextView.setText(String.format("%d%%", importingHistory.uploadProgress));
importCountTextView[0].setText(LocaleController.formatString("ImportCount", R.string.ImportCount, AndroidUtilities.formatFileSize(importingHistory.getUploadedCount()), AndroidUtilities.formatFileSize(importingHistory.getTotalCount())));
lineProgressView.setProgress(importingHistory.uploadProgress / 100.0f, true);
}
}
@Override
public void dismissInternal() {
super.dismissInternal();
parentFragment.getNotificationCenter().removeObserver(this, NotificationCenter.historyImportProgressChanged);
}
}

View File

@ -2254,7 +2254,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
private void didWriteData(File file, long availableSize, boolean last) {
if (videoConvertFirstWrite) {
FileLoader.getInstance(currentAccount).uploadFile(file.toString(), isSecretChat, false, 1, ConnectionsManager.FileTypeVideo);
FileLoader.getInstance(currentAccount).uploadFile(file.toString(), isSecretChat, false, 1, ConnectionsManager.FileTypeVideo, false);
videoConvertFirstWrite = false;
if (last) {
FileLoader.getInstance(currentAccount).checkUploadNewDataAvailable(file.toString(), isSecretChat, availableSize, last ? file.length() : 0);

View File

@ -0,0 +1,710 @@
package org.telegram.ui.Components;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.HeaderCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Cells.UserCell;
import org.telegram.ui.ManageLinksActivity;
import org.telegram.ui.ProfileActivity;
import java.util.ArrayList;
import java.util.HashMap;
public class InviteLinkBottomSheet extends BottomSheet {
TLRPC.TL_chatInviteExported invite;
HashMap<Integer, TLRPC.User> users;
TLRPC.ChatFull info;
int creatorHeaderRow;
int creatorRow;
int dividerRow;
int divider2Row;
int usersHeaderRow;
int usersStartRow;
int usersEndRow;
int linkActionRow;
int linkInfoRow;
int loadingRow;
int emptyView;
int emptyView2;
boolean usersLoading;
boolean hasMore;
int rowCount;
Adapter adapter;
BaseFragment fragment;
private RecyclerListView listView;
private TextView titleTextView;
private AnimatorSet shadowAnimation;
private View shadow;
private int scrollOffsetY;
private boolean ignoreLayout;
private boolean permanent;
ArrayList<TLRPC.TL_chatInviteImporter> invitedUsers = new ArrayList<>();
private int chatId;
public InviteLinkBottomSheet(Context context, TLRPC.TL_chatInviteExported invite, TLRPC.ChatFull info, HashMap<Integer, TLRPC.User> users, BaseFragment fragment, int chatId, boolean permanent) {
super(context, false);
this.invite = invite;
this.users = users;
this.fragment = fragment;
this.info = info;
this.chatId = chatId;
this.permanent = permanent;
containerView = new FrameLayout(context) {
private RectF rect = new RectF();
private boolean fullHeight;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY) {
dismiss();
return true;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
return !isDismissed() && super.onTouchEvent(e);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
if (Build.VERSION.SDK_INT >= 21) {
ignoreLayout = true;
setPadding(backgroundPaddingLeft, AndroidUtilities.statusBarHeight, backgroundPaddingLeft, 0);
ignoreLayout = false;
}
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
fullHeight = true;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
updateLayout();
}
@Override
public void requestLayout() {
if (ignoreLayout) {
return;
}
super.requestLayout();
}
@Override
protected void onDraw(Canvas canvas) {
int top = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(8);
int height = getMeasuredHeight() + AndroidUtilities.dp(36) + backgroundPaddingTop;
int statusBarHeight = 0;
float radProgress = 1.0f;
if (Build.VERSION.SDK_INT >= 21) {
top += AndroidUtilities.statusBarHeight;
height -= AndroidUtilities.statusBarHeight;
if (fullHeight) {
if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight * 2) {
int diff = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight * 2 - top - backgroundPaddingTop);
top -= diff;
height += diff;
radProgress = 1.0f - Math.min(1.0f, (diff * 2) / (float) AndroidUtilities.statusBarHeight);
}
if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight) {
statusBarHeight = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight - top - backgroundPaddingTop);
}
}
}
shadowDrawable.setBounds(0, top, getMeasuredWidth(), height);
shadowDrawable.draw(canvas);
if (radProgress != 1.0f) {
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_dialogBackground));
rect.set(backgroundPaddingLeft, backgroundPaddingTop + top, getMeasuredWidth() - backgroundPaddingLeft, backgroundPaddingTop + top + AndroidUtilities.dp(24));
canvas.drawRoundRect(rect, AndroidUtilities.dp(12) * radProgress, AndroidUtilities.dp(12) * radProgress, Theme.dialogs_onlineCirclePaint);
}
if (statusBarHeight > 0) {
int color1 = Theme.getColor(Theme.key_dialogBackground);
int finalColor = Color.argb(0xff, (int) (Color.red(color1) * 0.8f), (int) (Color.green(color1) * 0.8f), (int) (Color.blue(color1) * 0.8f));
Theme.dialogs_onlineCirclePaint.setColor(finalColor);
canvas.drawRect(backgroundPaddingLeft, AndroidUtilities.statusBarHeight - statusBarHeight, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight, Theme.dialogs_onlineCirclePaint);
}
}
};
containerView.setWillNotDraw(false);
FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.TOP | Gravity.LEFT);
frameLayoutParams.topMargin = AndroidUtilities.dp(48);
shadow = new View(context);
shadow.setAlpha(0.0f);
shadow.setVisibility(View.INVISIBLE);
shadow.setTag(1);
containerView.addView(shadow, frameLayoutParams);
listView = new RecyclerListView(context) {
int lastH;
@Override
public void requestLayout() {
if (ignoreLayout) {
return;
}
super.requestLayout();
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
if (lastH != MeasureSpec.getSize(heightSpec)) {
lastH = MeasureSpec.getSize(heightSpec);
ignoreLayout = true;
listView.setPadding(0, 0, 0, 0);
ignoreLayout = false;
measure(widthSpec, View.MeasureSpec.makeMeasureSpec(heightSpec, MeasureSpec.AT_MOST));
int contentSize = getMeasuredHeight();
int padding = (int) (lastH / 5f * 2f);
if (padding < lastH - contentSize + AndroidUtilities.dp(60)) {
padding = lastH - contentSize;
}
ignoreLayout = true;
listView.setPadding(0, padding, 0, 0);
ignoreLayout = false;
measure(widthSpec, View.MeasureSpec.makeMeasureSpec(heightSpec, MeasureSpec.AT_MOST));
}
super.onMeasure(widthSpec, heightSpec);
}
};
listView.setTag(14);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
listView.setLayoutManager(layoutManager);
listView.setAdapter(adapter = new Adapter());
listView.setVerticalScrollBarEnabled(false);
listView.setClipToPadding(false);
listView.setNestedScrollingEnabled(true);
listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
updateLayout();
if (hasMore && !usersLoading) {
int lastPosition = layoutManager.findLastVisibleItemPosition();
if (rowCount - lastPosition < 10) {
loadUsers();
}
}
}
});
listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
if (position == creatorRow || (position >= usersStartRow && position < usersEndRow)) {
TLRPC.User user;
if (position == creatorRow) {
user = users.get(invite.admin_id);
} else {
TLRPC.TL_chatInviteImporter invitedUser = invitedUsers.get(position - usersStartRow);
user = users.get(invitedUser.user_id);
}
if (user != null) {
Bundle bundle = new Bundle();
bundle.putInt("user_id", user.id);
MessagesController.getInstance(UserConfig.selectedAccount).putUser(user, false);
ProfileActivity profileActivity = new ProfileActivity(bundle);
fragment.presentFragment(profileActivity);
dismiss();
}
}
}
});
containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, permanent ? 0 : 48, 0, 0));
if (!permanent) {
titleTextView = new TextView(context);
titleTextView.setLines(1);
titleTextView.setSingleLine(true);
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
titleTextView.setEllipsize(TextUtils.TruncateAt.END);
titleTextView.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
titleTextView.setGravity(Gravity.CENTER_VERTICAL);
titleTextView.setText(invite.revoked ? LocaleController.getString("RevokedLink", R.string.RevokedLink) : LocaleController.getString("InviteLink", R.string.InviteLink));
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
containerView.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.LEFT | Gravity.TOP, 0, 0, 40, 0));
}
updateRows();
loadUsers();
if (users.get(invite.admin_id) == null) {
loadCreator();
}
updateColors();
}
public void updateColors() {
if (titleTextView != null) {
titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
titleTextView.setLinkTextColor(Theme.getColor(Theme.key_dialogTextLink));
titleTextView.setHighlightColor(Theme.getColor(Theme.key_dialogLinkSelection));
}
listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow));
shadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine));
setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
int count = listView.getHiddenChildCount();
for (int i = 0; i < listView.getChildCount(); i++) {
updateColorForView(listView.getChildAt(i));
}
for (int a = 0; a < count; a++) {
updateColorForView(listView.getHiddenChildAt(a));
}
count = listView.getCachedChildCount();
for (int a = 0; a < count; a++) {
updateColorForView(listView.getCachedChildAt(a));
}
count = listView.getAttachedScrapChildCount();
for (int a = 0; a < count; a++) {
updateColorForView(listView.getAttachedScrapChildAt(a));
}
containerView.invalidate();
}
private void updateColorForView(View view) {
if (view instanceof HeaderCell) {
((HeaderCell) view).getTextView().setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
} else if (view instanceof LinkActionView){
((LinkActionView) view).updateColors();
} else if (view instanceof TextInfoPrivacyCell) {
CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), Theme.getThemedDrawable(view.getContext(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
combinedDrawable.setFullsize(true);
view.setBackground(combinedDrawable);
((TextInfoPrivacyCell) view).setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4));
} else if (view instanceof UserCell) {
((UserCell) view).update(0);
}
RecyclerView.ViewHolder holder = listView.getChildViewHolder(view);
if (holder != null){
if (holder.getItemViewType() == 7) {
Drawable shadowDrawable = Theme.getThemedDrawable(view.getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow);
Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
view.setBackgroundDrawable(combinedDrawable);
} else if (holder.getItemViewType() == 2) {
Drawable shadowDrawable = Theme.getThemedDrawable(view.getContext(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow);
Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
view.setBackgroundDrawable(combinedDrawable);
}
}
}
private void loadCreator() {
TLRPC.TL_users_getUsers req = new TLRPC.TL_users_getUsers();
req.id.add(MessagesController.getInstance(UserConfig.selectedAccount).getInputUser(invite.admin_id));
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (error == null) {
TLRPC.Vector vector = (TLRPC.Vector) response;
TLRPC.User user = (TLRPC.User) vector.objects.get(0);
users.put(invite.admin_id, user);
adapter.notifyDataSetChanged();
}
}
});
});
}
@Override
protected boolean canDismissWithSwipe() {
return false;
}
private void updateRows() {
rowCount = 0;
dividerRow = -1;
divider2Row = -1;
usersHeaderRow = -1;
usersStartRow = -1;
usersEndRow = -1;
emptyView2 = -1;
linkActionRow = -1;
linkInfoRow = -1;
if (!permanent) {
linkActionRow = rowCount++;
linkInfoRow = rowCount++;
}
creatorHeaderRow = rowCount++;
creatorRow = rowCount++;
emptyView = rowCount++;
if (invite.usage > 0) {
dividerRow = rowCount++;
usersHeaderRow = rowCount++;
if (!invitedUsers.isEmpty()) {
usersStartRow = rowCount;
rowCount += invitedUsers.size();
usersEndRow = rowCount;
} else {
loadingRow = rowCount++;
}
emptyView2 = rowCount++;
}
divider2Row = rowCount++;
adapter.notifyDataSetChanged();
}
private class Adapter extends RecyclerListView.SelectionAdapter {
@Override
public int getItemViewType(int position) {
if (position == creatorHeaderRow) {
return 0;
} else if (position == creatorRow || position >= usersStartRow && position < usersEndRow) {
return 1;
} else if (position == dividerRow) {
return 2;
} else if (position == linkActionRow) {
return 3;
} else if (position == linkInfoRow) {
return 4;
} else if (position == loadingRow) {
return 5;
} else if (position == emptyView || position == emptyView2) {
return 6;
} else if (position == divider2Row) {
return 7;
}
return 0;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
Context context = parent.getContext();
switch (viewType) {
default:
case 0:
view = new HeaderCell(context);
break;
case 1:
view = new UserCell(context, 12, 0, true);
break;
case 2:
view = new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray));
break;
case 3:
LinkActionView linkActionView = new LinkActionView(context, fragment, InviteLinkBottomSheet.this, chatId, false);
view = linkActionView;
linkActionView.setDelegate(new LinkActionView.Delegate() {
@Override
public void revokeLink() {
if (fragment instanceof ManageLinksActivity) {
((ManageLinksActivity) fragment).revokeLink(invite);
}
dismiss();
}
@Override
public void editLink() {
if (fragment instanceof ManageLinksActivity) {
((ManageLinksActivity) fragment).editLink(invite);
}
dismiss();
}
@Override
public void removeLink() {
if (fragment instanceof ManageLinksActivity) {
((ManageLinksActivity) fragment).deleteLink(invite);
}
dismiss();
}
});
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
break;
case 4:
view = new TextInfoPrivacyCell(context);
CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
combinedDrawable.setFullsize(true);
view.setBackground(combinedDrawable);
break;
case 5:
FlickerLoadingView flickerLoadingView = new FlickerLoadingView(context);
flickerLoadingView.setIsSingleCell(true);
flickerLoadingView.setViewType(FlickerLoadingView.USERS2_TYPE);
flickerLoadingView.showDate(false);
view = flickerLoadingView;
break;
case 6:
view = new View(context) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(5), MeasureSpec.EXACTLY));
}
};
break;
case 7:
view = new ShadowSectionCell(context, 12);
Drawable shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow);
Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
view.setBackgroundDrawable(combinedDrawable);
break;
}
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new RecyclerListView.Holder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0:
HeaderCell headerCell = (HeaderCell) holder.itemView;
if (position == creatorHeaderRow) {
headerCell.setText(LocaleController.getString("LinkCreatedeBy", R.string.LinkCreatedeBy));
} else if (position == usersHeaderRow) {
headerCell.setText(LocaleController.formatPluralString("PeopleJoined", invite.usage));
}
break;
case 1:
UserCell userCell = (UserCell) holder.itemView;
TLRPC.User user;
String role = null;
String status = null;
if (position == creatorRow) {
user = users.get(invite.admin_id);
if (user != null) {
status = LocaleController.formatDateAudio(invite.date, false);
}
if (info != null && user != null) {
for (int i = 0; i < info.participants.participants.size(); i++) {
if (info.participants.participants.get(i).user_id == user.id) {
TLRPC.ChatParticipant part = info.participants.participants.get(i);
if (part instanceof TLRPC.TL_chatChannelParticipant) {
TLRPC.ChannelParticipant channelParticipant = ((TLRPC.TL_chatChannelParticipant) part).channelParticipant;
if (!TextUtils.isEmpty(channelParticipant.rank)) {
role = channelParticipant.rank;
} else {
if (channelParticipant instanceof TLRPC.TL_channelParticipantCreator) {
role = LocaleController.getString("ChannelCreator", R.string.ChannelCreator);
} else if (channelParticipant instanceof TLRPC.TL_channelParticipantAdmin) {
role = LocaleController.getString("ChannelAdmin", R.string.ChannelAdmin);
} else {
role = null;
}
}
} else {
if (part instanceof TLRPC.TL_chatParticipantCreator) {
role = LocaleController.getString("ChannelCreator", R.string.ChannelCreator);
} else if (part instanceof TLRPC.TL_chatParticipantAdmin) {
role = LocaleController.getString("ChannelAdmin", R.string.ChannelAdmin);
} else {
role = null;
}
}
break;
}
}
}
} else {
TLRPC.TL_chatInviteImporter invitedUser = invitedUsers.get(position - usersStartRow);
user = users.get(invitedUser.user_id);
}
userCell.setAdminRole(role);
userCell.setData(user, null, status, 0, false);
break;
case 3:
LinkActionView actionView = (LinkActionView) holder.itemView;
actionView.setUsers(0, null);
actionView.setLink(invite.link);
actionView.setRevoke(invite.revoked);
break;
case 4:
TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView;
if (invite.revoked) {
privacyCell.setText(LocaleController.getString("LinkIsNoActive", R.string.LinkIsNoActive));
} else if (invite.expired) {
privacyCell.setText(LocaleController.getString("LinkIsExpired", R.string.LinkIsExpired));
} else if (invite.expire_date > 0) {
privacyCell.setText(LocaleController.formatString("LinkExpiresIn", R.string.LinkExpiresIn, LocaleController.formatDateAudio(invite.expire_date, false)));
} else {
privacyCell.setText(null);
}
break;
}
}
@Override
public int getItemCount() {
return rowCount;
}
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
int position = holder.getAdapterPosition();
if (position == creatorRow || (position >= usersStartRow && position < usersEndRow)) {
return true;
}
return false;
}
}
private void updateLayout() {
if (listView.getChildCount() <= 0) {
listView.setTopGlowOffset(scrollOffsetY = listView.getPaddingTop());
titleTextView.setTranslationY(scrollOffsetY);
shadow.setTranslationY(scrollOffsetY);
containerView.invalidate();
return;
}
View child = listView.getChildAt(0);
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child);
int top = child.getTop();
int newOffset = 0;
if (top >= 0 && holder != null && holder.getAdapterPosition() == 0) {
newOffset = top;
runShadowAnimation(false);
} else {
runShadowAnimation(true);
}
if (scrollOffsetY != newOffset) {
listView.setTopGlowOffset(scrollOffsetY = newOffset);
if (titleTextView != null) {
titleTextView.setTranslationY(scrollOffsetY);
}
shadow.setTranslationY(scrollOffsetY);
containerView.invalidate();
}
}
private void runShadowAnimation(final boolean show) {
if (show && shadow.getTag() != null || !show && shadow.getTag() == null) {
shadow.setTag(show ? null : 1);
if (show) {
shadow.setVisibility(View.VISIBLE);
}
if (shadowAnimation != null) {
shadowAnimation.cancel();
}
shadowAnimation = new AnimatorSet();
shadowAnimation.playTogether(ObjectAnimator.ofFloat(shadow, View.ALPHA, show ? 1.0f : 0.0f));
shadowAnimation.setDuration(150);
shadowAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (shadowAnimation != null && shadowAnimation.equals(animation)) {
if (!show) {
shadow.setVisibility(View.INVISIBLE);
}
shadowAnimation = null;
}
}
@Override
public void onAnimationCancel(Animator animation) {
if (shadowAnimation != null && shadowAnimation.equals(animation)) {
shadowAnimation = null;
}
}
});
shadowAnimation.start();
}
}
public void loadUsers() {
if (invite.usage <= 0 || usersLoading) {
return;
}
TLRPC.TL_messages_getChatInviteImporters req = new TLRPC.TL_messages_getChatInviteImporters();
req.link = invite.link;
req.peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(-chatId);
if (invitedUsers.isEmpty()) {
req.offset_user = new TLRPC.TL_inputUserEmpty();
} else {
TLRPC.TL_chatInviteImporter invitedUser = invitedUsers.get(invitedUsers.size() - 1);
req.offset_user = MessagesController.getInstance(currentAccount).getInputUser(users.get(invitedUser.user_id));
req.offset_date = invitedUser.date;
}
usersLoading = true;
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> {
AndroidUtilities.runOnUIThread(() -> {
if (error == null) {
TLRPC.TL_messages_chatInviteImporters inviteImporters = (TLRPC.TL_messages_chatInviteImporters) response;
invitedUsers.addAll(inviteImporters.importers);
for (int i = 0; i < inviteImporters.users.size(); i++) {
TLRPC.User user = inviteImporters.users.get(i);
users.put(user.id, user);
}
hasMore = invitedUsers.size() < inviteImporters.count;
updateRows();
}
usersLoading = false;
});
});
}
}

View File

@ -11,6 +11,7 @@ package org.telegram.ui.Components;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
@ -31,6 +32,8 @@ public class LineProgressView extends View {
private static DecelerateInterpolator decelerateInterpolator;
private static Paint progressPaint;
private RectF rect = new RectF();
public LineProgressView(Context context) {
super(context);
@ -104,12 +107,14 @@ public class LineProgressView extends View {
progressPaint.setColor(backColor);
progressPaint.setAlpha((int) (255 * animatedAlphaValue));
int start = (int) (getWidth() * animatedProgressValue);
canvas.drawRect(start, 0, getWidth(), getHeight(), progressPaint);
rect.set(0, 0, getWidth(), getHeight());
canvas.drawRoundRect(rect, getHeight() / 2, getHeight() / 2, progressPaint);
}
progressPaint.setColor(progressColor);
progressPaint.setAlpha((int)(255 * animatedAlphaValue));
canvas.drawRect(0, 0, getWidth() * animatedProgressValue, getHeight(), progressPaint);
progressPaint.setAlpha((int) (255 * animatedAlphaValue));
rect.set(0, 0, getWidth() * animatedProgressValue, getHeight());
canvas.drawRoundRect(rect, getHeight() / 2, getHeight() / 2, progressPaint);
updateAnimation();
}
}

Some files were not shown because too many files have changed in this diff Show More