From f338a88eb4c48348378fb9575fa6b63ff80bbec3 Mon Sep 17 00:00:00 2001 From: DrKLO Date: Fri, 8 Feb 2019 05:30:32 +0300 Subject: [PATCH] Update to 5.3.1 --- TMessagesProj/build.gradle | 4 +- TMessagesProj/jni/Android.mk | 353 +--- TMessagesProj/jni/jni.c | 4 +- TMessagesProj/jni/libtgvoip | 2 +- .../src/main/assets/bluebubbles.attheme | Bin 28839 -> 30901 bytes .../telegram/messenger/AndroidUtilities.java | 155 ++ .../org/telegram/messenger/BuildVars.java | 4 +- .../telegram/messenger/FileRefController.java | 10 +- .../org/telegram/messenger/ImageLoader.java | 159 +- .../org/telegram/messenger/ImageReceiver.java | 150 +- .../telegram/messenger/LocaleController.java | 23 +- .../telegram/messenger/MediaController.java | 21 +- .../org/telegram/messenger/MessageObject.java | 57 +- .../messenger/MessagesController.java | 161 +- .../telegram/messenger/MessagesStorage.java | 26 +- .../messenger/NotificationCenter.java | 1 + .../telegram/messenger/SecretChatHelper.java | 6 +- .../messenger/SendMessagesHelper.java | 58 +- .../org/telegram/messenger/Utilities.java | 3 + .../messenger/time/FastDatePrinter.java | 45 +- .../telegram/tgnet/ConnectionsManager.java | 41 +- .../main/java/org/telegram/tgnet/TLRPC.java | 194 +- .../ui/ActionBar/ActionBarLayout.java | 8 +- .../telegram/ui/ActionBar/AlertDialog.java | 5 +- .../telegram/ui/ActionBar/SimpleTextView.java | 147 +- .../java/org/telegram/ui/ActionBar/Theme.java | 44 +- .../telegram/ui/Adapters/DialogsAdapter.java | 4 + .../ui/Adapters/DialogsSearchAdapter.java | 1 + .../telegram/ui/Adapters/StickersAdapter.java | 2 +- .../java/org/telegram/ui/ArticleViewer.java | 39 +- .../telegram/ui/Cells/AudioPlayerCell.java | 7 + .../org/telegram/ui/Cells/ChatActionCell.java | 19 +- .../telegram/ui/Cells/ChatMessageCell.java | 210 ++- .../telegram/ui/Cells/ContextLinkCell.java | 6 +- .../org/telegram/ui/Cells/DialogCell.java | 4 + .../telegram/ui/Cells/DrawerProfileCell.java | 2 +- .../telegram/ui/Cells/PaymentInfoCell.java | 2 +- .../ui/Cells/SharedPhotoVideoCell.java | 4 +- .../java/org/telegram/ui/Cells/UserCell.java | 89 +- .../org/telegram/ui/Cells/WallpaperCell.java | 91 +- .../java/org/telegram/ui/ChatActivity.java | 12 +- .../org/telegram/ui/ChatEditActivity.java | 4 +- .../org/telegram/ui/ChatSettingsActivity.java | 519 ------ .../org/telegram/ui/ChatUsersActivity.java | 8 +- .../telegram/ui/Components/AlertsCreator.java | 13 +- .../ui/Components/BackupImageView.java | 26 +- .../ui/Components/EditTextBoldCursor.java | 2 + .../ui/Components/GroupCreateSpan.java | 2 +- .../ui/Components/GroupedPhotosListView.java | 4 +- .../org/telegram/ui/Components/LinkPath.java | 18 +- .../ui/Components/MediaActionDrawable.java | 27 +- .../ui/Components/RadialProgress2.java | 16 +- .../telegram/ui/Components/ShareAlert.java | 502 +++--- .../Components/SizeNotifierFrameLayout.java | 8 +- .../ui/Components/TermsOfServiceView.java | 14 +- .../ui/Components/ThemeEditorView.java | 2 +- .../org/telegram/ui/Components/UndoView.java | 21 +- .../Components/WallpaperParallaxEffect.java | 4 +- .../ui/Components/WallpaperUpdater.java | 12 +- .../org/telegram/ui/ContactsActivity.java | 13 +- .../java/org/telegram/ui/DialogsActivity.java | 18 +- .../java/org/telegram/ui/LaunchActivity.java | 170 +- .../java/org/telegram/ui/LoginActivity.java | 7 +- .../org/telegram/ui/NewContactActivity.java | 14 +- .../NotificationsCustomSettingsActivity.java | 112 +- .../ui/NotificationsSettingsActivity.java | 118 +- .../org/telegram/ui/PhotoPickerActivity.java | 15 +- .../java/org/telegram/ui/PhotoViewer.java | 12 +- .../java/org/telegram/ui/ProfileActivity.java | 7 +- .../ui/ProfileNotificationsActivity.java | 166 +- .../org/telegram/ui/SettingsActivity.java | 2 +- .../java/org/telegram/ui/ThemeActivity.java | 683 ++++++- .../org/telegram/ui/WallpaperActivity.java | 1602 ++++++++++++++--- .../telegram/ui/WallpapersListActivity.java | 1210 ++++++++++--- .../src/main/res/values-ar/strings.xml | 203 ++- .../src/main/res/values-de/strings.xml | 81 +- .../src/main/res/values-es/strings.xml | 73 +- .../src/main/res/values-it/strings.xml | 107 +- .../src/main/res/values-ko/strings.xml | 419 +++-- .../src/main/res/values-nl/strings.xml | 69 +- .../src/main/res/values-pt-rBR/strings.xml | 109 +- TMessagesProj/src/main/res/values/strings.xml | 75 +- 82 files changed, 5853 insertions(+), 2807 deletions(-) delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ChatSettingsActivity.java diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 2ea726af4..13e954910 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -111,7 +111,7 @@ android { } } - defaultConfig.versionCode = 1478 + defaultConfig.versionCode = 1497 sourceSets.debug { manifest.srcFile 'config/debug/AndroidManifest.xml' @@ -252,7 +252,7 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 27 - versionName "5.2.1" + versionName "5.3.1" vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] diff --git a/TMessagesProj/jni/Android.mk b/TMessagesProj/jni/Android.mk index f8b65d557..f7129d885 100755 --- a/TMessagesProj/jni/Android.mk +++ b/TMessagesProj/jni/Android.mk @@ -1,4 +1,5 @@ -LOCAL_PATH := $(call my-dir) +MY_LOCAL_PATH := $(call my-dir) +LOCAL_PATH := $(MY_LOCAL_PATH) LOCAL_MODULE := avutil @@ -78,351 +79,8 @@ endif include $(PREBUILT_STATIC_LIBRARY) -include $(CLEAR_VARS) - -LOCAL_MODULE := voip -LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -finline-functions -ffast-math -Os -fno-strict-aliasing -O3 -frtti -D__STDC_LIMIT_MACROS -Wno-unknown-pragmas -LOCAL_CFLAGS := -O3 -DUSE_KISS_FFT -fexceptions -DWEBRTC_APM_DEBUG_DUMP=0 -DWEBRTC_POSIX -DWEBRTC_ANDROID -D__STDC_LIMIT_MACROS -DFIXED_POINT -DWEBRTC_NS_FLOAT - -MY_DIR := libtgvoip - -LOCAL_C_INCLUDES := jni/opus/include jni/boringssl/include/ jni/libtgvoip/webrtc_dsp/ - -ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI),armeabi-v7a arm64-v8a)) -CC_NEON := cc.neon -LOCAL_CFLAGS += -DWEBRTC_HAS_NEON -else -CC_NEON := cc -endif - -LOCAL_SRC_FILES := \ -./libtgvoip/logging.cpp \ -./libtgvoip/VoIPController.cpp \ -./libtgvoip/VoIPGroupController.cpp \ -./libtgvoip/Buffers.cpp \ -./libtgvoip/BlockingQueue.cpp \ -./libtgvoip/audio/AudioInput.cpp \ -./libtgvoip/os/android/AudioInputOpenSLES.cpp \ -./libtgvoip/MediaStreamItf.cpp \ -./libtgvoip/audio/AudioOutput.cpp \ -./libtgvoip/OpusEncoder.cpp \ -./libtgvoip/os/android/AudioOutputOpenSLES.cpp \ -./libtgvoip/JitterBuffer.cpp \ -./libtgvoip/OpusDecoder.cpp \ -./libtgvoip/os/android/OpenSLEngineWrapper.cpp \ -./libtgvoip/os/android/AudioInputAndroid.cpp \ -./libtgvoip/os/android/AudioOutputAndroid.cpp \ -./libtgvoip/EchoCanceller.cpp \ -./libtgvoip/CongestionControl.cpp \ -./libtgvoip/VoIPServerConfig.cpp \ -./libtgvoip/audio/Resampler.cpp \ -./libtgvoip/NetworkSocket.cpp \ -./libtgvoip/os/posix/NetworkSocketPosix.cpp \ -./libtgvoip/PacketReassembler.cpp \ -./libtgvoip/MessageThread.cpp \ -./libtgvoip/json11.cpp \ -./libtgvoip/audio/AudioIO.cpp \ -./libtgvoip/video/VideoRenderer.cpp \ -./libtgvoip/video/VideoSource.cpp \ -./libtgvoip/os/android/VideoSourceAndroid.cpp \ -./libtgvoip/os/android/VideoRendererAndroid.cpp - -# WebRTC signal processing - -LOCAL_SRC_FILES += \ -./libtgvoip/webrtc_dsp/system_wrappers/source/field_trial.cc \ -./libtgvoip/webrtc_dsp/system_wrappers/source/metrics.cc \ -./libtgvoip/webrtc_dsp/system_wrappers/source/cpu_features.cc \ -./libtgvoip/webrtc_dsp/absl/strings/internal/memutil.cc \ -./libtgvoip/webrtc_dsp/absl/strings/string_view.cc \ -./libtgvoip/webrtc_dsp/absl/strings/ascii.cc \ -./libtgvoip/webrtc_dsp/absl/types/bad_optional_access.cc \ -./libtgvoip/webrtc_dsp/absl/types/optional.cc \ -./libtgvoip/webrtc_dsp/absl/base/internal/raw_logging.cc \ -./libtgvoip/webrtc_dsp/absl/base/internal/throw_delegate.cc \ -./libtgvoip/webrtc_dsp/rtc_base/race_checker.cc \ -./libtgvoip/webrtc_dsp/rtc_base/strings/string_builder.cc \ -./libtgvoip/webrtc_dsp/rtc_base/memory/aligned_malloc.cc \ -./libtgvoip/webrtc_dsp/rtc_base/timeutils.cc \ -./libtgvoip/webrtc_dsp/rtc_base/platform_file.cc \ -./libtgvoip/webrtc_dsp/rtc_base/string_to_number.cc \ -./libtgvoip/webrtc_dsp/rtc_base/thread_checker_impl.cc \ -./libtgvoip/webrtc_dsp/rtc_base/stringencode.cc \ -./libtgvoip/webrtc_dsp/rtc_base/stringutils.cc \ -./libtgvoip/webrtc_dsp/rtc_base/checks.cc \ -./libtgvoip/webrtc_dsp/rtc_base/platform_thread.cc \ -./libtgvoip/webrtc_dsp/rtc_base/criticalsection.cc \ -./libtgvoip/webrtc_dsp/rtc_base/platform_thread_types.cc \ -./libtgvoip/webrtc_dsp/rtc_base/event.cc \ -./libtgvoip/webrtc_dsp/rtc_base/event_tracer.cc \ -./libtgvoip/webrtc_dsp/rtc_base/logging_webrtc.cc \ -./libtgvoip/webrtc_dsp/third_party/rnnoise/src/rnn_vad_weights.cc \ -./libtgvoip/webrtc_dsp/third_party/rnnoise/src/kiss_fft.cc \ -./libtgvoip/webrtc_dsp/api/audio/audio_frame.cc \ -./libtgvoip/webrtc_dsp/api/audio/echo_canceller3_config.cc \ -./libtgvoip/webrtc_dsp/api/audio/echo_canceller3_factory.cc \ -./libtgvoip/webrtc_dsp/modules/third_party/fft/fft.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filterbanks.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/transform.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_filter.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filter_functions.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/decode.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lattice.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/intialize.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_tables.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/entropy_coding.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac_vad.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/crc.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/decode_bwe.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c \ -./libtgvoip/webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/rms_level.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/echo_detector/normalized_covariance_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/echo_detector/moving_max.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/echo_detector/circular_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/echo_detector/mean_variance_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/splitting_filter.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/gain_control_impl.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/ns/nsx_core.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/ns/noise_suppression_x.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/ns/nsx_core_c.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/ns/ns_core.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/ns/noise_suppression.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/audio_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/typing_detection.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/include/audio_processing_statistics.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/include/audio_generator_factory.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/include/aec_dump.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/include/audio_processing.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/include/config.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/interpolated_gain_curve.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/agc2_common.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/gain_applier.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/adaptive_agc.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/limiter.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/saturation_protector.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features_internal.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/rnn.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/features_extraction.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/fft_util.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/rnn_vad/lp_residual.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator_agc.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/vector_float_frame.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/noise_level_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/agc2_testing_common.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/fixed_digital_level_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/fixed_gain_controller.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/vad_with_level.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/limiter_db_gain_curve.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/down_sampler.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/signal_classifier.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/noise_spectrum_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/compute_interpolated_gain_curve.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/biquad_filter.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/transient/moving_moments.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/transient/wpd_tree.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/transient/wpd_node.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/transient/transient_suppressor.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/transient/transient_detector.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/low_cut_filter.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/level_estimator_impl.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/three_band_filter_bank.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec/echo_cancellation.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec/aec_resampler.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec/aec_core.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/voice_detection_impl.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/echo_cancellation_impl.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/gain_control_for_experimental_agc.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc/agc.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc/loudness_histogram.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc/agc_manager_direct.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc/legacy/analog_agc.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc/legacy/digital_agc.c \ -./libtgvoip/webrtc_dsp/modules/audio_processing/agc/utility.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/audio_processing_impl.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/audio_generator/file_audio_generator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/gain_controller2.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/residual_echo_detector.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/noise_suppression_impl.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aecm/aecm_core.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aecm/aecm_core_c.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aecm/echo_control_mobile.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_reverb_model.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/reverb_model_fallback.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/echo_remover_metrics.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/matched_filter_lag_aggregator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer2.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/echo_path_variability.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/frame_blocker.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/subtractor.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/aec3_fft.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/fullband_erle_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/suppression_filter.$(CC_NEON) \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/block_processor.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/subband_erle_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_delay_controller_metrics.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/vector_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/erl_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/aec_state.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/adaptive_fir_filter.$(CC_NEON) \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_delay_controller.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/skew_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/echo_path_delay_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/block_framer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/erle_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/reverb_model.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/cascaded_biquad_filter.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/subtractor_output.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/stationarity_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_signal_analyzer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/subtractor_output_analyzer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/suppression_gain.$(CC_NEON) \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/echo_audibility.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/block_processor_metrics.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/moving_average.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/reverb_model_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/aec3_common.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/residual_echo_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/matched_filter.$(CC_NEON) \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/reverb_decay_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/render_delay_controller2.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/suppression_gain_limiter.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/main_filter_update_gain.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/echo_remover.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/downsampled_render_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/matrix_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/block_processor2.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/echo_canceller3.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/block_delay_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/fft_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/comfort_noise_generator.$(CC_NEON) \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/shadow_filter_update_gain.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/filter_analyzer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/reverb_frequency_response.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec3/decimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/echo_control_mobile_impl.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/logging/apm_data_dumper.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/voice_activity_detector.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/standalone_vad.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/pitch_internal.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/vad_circular_buffer.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/vad_audio_proc.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/pole_zero_filter.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/pitch_based_vad.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/vad/gmm.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/utility/ooura_fft.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/utility/delay_estimator_wrapper.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/utility/delay_estimator.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/utility/block_mean_calculator.cc \ -./libtgvoip/webrtc_dsp/common_audio/window_generator.cc \ -./libtgvoip/webrtc_dsp/common_audio/channel_buffer.cc \ -./libtgvoip/webrtc_dsp/common_audio/fir_filter_factory.cc \ -./libtgvoip/webrtc_dsp/common_audio/wav_header.cc \ -./libtgvoip/webrtc_dsp/common_audio/real_fourier_ooura.cc \ -./libtgvoip/webrtc_dsp/common_audio/audio_util.cc \ -./libtgvoip/webrtc_dsp/common_audio/resampler/push_sinc_resampler.cc \ -./libtgvoip/webrtc_dsp/common_audio/resampler/resampler.cc \ -./libtgvoip/webrtc_dsp/common_audio/resampler/push_resampler.cc \ -./libtgvoip/webrtc_dsp/common_audio/resampler/sinc_resampler.cc \ -./libtgvoip/webrtc_dsp/common_audio/resampler/sinusoidal_linear_chirp_source.cc \ -./libtgvoip/webrtc_dsp/common_audio/wav_file.cc \ -./libtgvoip/webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.c \ -./libtgvoip/webrtc_dsp/common_audio/third_party/fft4g/fft4g.c \ -./libtgvoip/webrtc_dsp/common_audio/audio_converter.cc \ -./libtgvoip/webrtc_dsp/common_audio/real_fourier.cc \ -./libtgvoip/webrtc_dsp/common_audio/sparse_fir_filter.cc \ -./libtgvoip/webrtc_dsp/common_audio/smoothing_filter.cc \ -./libtgvoip/webrtc_dsp/common_audio/fir_filter_c.cc \ -./libtgvoip/webrtc_dsp/common_audio/ring_buffer.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/complex_fft.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/filter_ma_fast_q12.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/levinson_durbin.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/dot_product_with_scale.cc \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/auto_corr_to_refl_coef.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/resample_by_2_internal.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/energy.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/downsample_fast.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/splitting_filter1.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/filter_ar_fast_q12.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/spl_init.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/lpc_to_refl_coef.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/cross_correlation.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/division_operations.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/auto_correlation.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/get_scaling_square.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/resample.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/min_max_operations.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/refl_coef_to_lpc.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/filter_ar.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/vector_scaling_operations.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/resample_fractional.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/real_fft.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/ilbc_specific_functions.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/complex_bit_reverse.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/randomization_functions.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/copy_set_operations.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/resample_by_2.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/get_hanning_window.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/resample_48khz.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/spl_inl.c \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/spl_sqrt.c \ -./libtgvoip/webrtc_dsp/common_audio/vad/vad_sp.c \ -./libtgvoip/webrtc_dsp/common_audio/vad/vad.cc \ -./libtgvoip/webrtc_dsp/common_audio/vad/webrtc_vad.c \ -./libtgvoip/webrtc_dsp/common_audio/vad/vad_filterbank.c \ -./libtgvoip/webrtc_dsp/common_audio/vad/vad_core.c \ -./libtgvoip/webrtc_dsp/common_audio/vad/vad_gmm.c - -ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI),armeabi-v7a arm64-v8a)) -LOCAL_SRC_FILES += \ -./libtgvoip/webrtc_dsp/modules/audio_processing/ns/nsx_core_neon.c.neon \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec/aec_core_neon.cc.neon \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aecm/aecm_core_neon.cc.neon \ -./libtgvoip/webrtc_dsp/modules/audio_processing/utility/ooura_fft_neon.cc.neon \ -./libtgvoip/webrtc_dsp/common_audio/fir_filter_neon.cc.neon \ -./libtgvoip/webrtc_dsp/common_audio/resampler/sinc_resampler_neon.cc.neon \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/downsample_fast_neon.c.neon \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/min_max_operations_neon.c.neon \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/cross_correlation_neon.c.neon -endif - -ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) -LOCAL_SRC_FILES += \ -./libtgvoip/webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_arm.S.neon \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/complex_bit_reverse_arm.S.neon \ -./libtgvoip/webrtc_dsp/common_audio/signal_processing/filter_ar_fast_q12_armv7.S.neon -endif - -ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI),x86 x86_64)) -LOCAL_SRC_FILES += \ -./libtgvoip/webrtc_dsp/modules/audio_processing/aec/aec_core_sse2.cc \ -./libtgvoip/webrtc_dsp/modules/audio_processing/utility/ooura_fft_sse2.cc \ -./libtgvoip/webrtc_dsp/common_audio/fir_filter_sse.cc \ -./libtgvoip/webrtc_dsp/common_audio/resampler/sinc_resampler_sse.cc -endif - -include $(BUILD_STATIC_LIBRARY) +include $(MY_LOCAL_PATH)/libtgvoip/Android.mk +LOCAL_PATH := $(MY_LOCAL_PATH) # restore local path after include include $(CLEAR_VARS) @@ -602,7 +260,7 @@ LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USE LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math -D__STDC_CONSTANT_MACROS LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -Os -funroll-loops -std=c++11 -LOCAL_LDLIBS := -ljnigraphics -llog -lz -latomic -lOpenSLES -lEGL -lGLESv2 -landroid +LOCAL_LDLIBS := -ljnigraphics -llog -lz -latomic -lEGL -lGLESv2 -landroid LOCAL_STATIC_LIBRARIES := webp sqlite tgnet avformat avcodec avresample avutil voip flac LOCAL_SRC_FILES := \ @@ -879,7 +537,6 @@ LOCAL_SRC_FILES += \ ./exoplayer/flac_parser.cc \ ./exoplayer/opus_jni.cc \ ./exoplayer/ffmpeg_jni.cc \ -./libtgvoip/client/android/tg_voip_jni.cpp \ ./fast-edge.cpp \ ./genann.c \ ./secureid_ocr.cpp diff --git a/TMessagesProj/jni/jni.c b/TMessagesProj/jni/jni.c index 81144c3a0..d84d2fe9f 100644 --- a/TMessagesProj/jni/jni.c +++ b/TMessagesProj/jni/jni.c @@ -164,9 +164,9 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_aesCbcEncryption(JNIEnv *en } JNIEXPORT jstring Java_org_telegram_messenger_Utilities_readlink(JNIEnv *env, jclass class, jstring path) { - static char buf[1000]; + static char buf[PATH_MAX + 1]; const char *fileName = (*env)->GetStringUTFChars(env, path, NULL); - ssize_t result = readlink(fileName, buf, 999); + ssize_t result = readlink(fileName, buf, PATH_MAX); jstring value = 0; if (result != -1) { buf[result] = '\0'; diff --git a/TMessagesProj/jni/libtgvoip b/TMessagesProj/jni/libtgvoip index 564eada17..fc13464b3 160000 --- a/TMessagesProj/jni/libtgvoip +++ b/TMessagesProj/jni/libtgvoip @@ -1 +1 @@ -Subproject commit 564eada171b3fb97a9740c30899d617b98fe1714 +Subproject commit fc13464b35aeb373844bafc7a9a33b18ca7afa3b diff --git a/TMessagesProj/src/main/assets/bluebubbles.attheme b/TMessagesProj/src/main/assets/bluebubbles.attheme index 85851aff2ad09b337e57ae13443d9b7a62e34891..5a9026106a8a6006450183c9868d5d655e8ccf09 100644 GIT binary patch literal 30901 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 Ih~-TDKU#*+LI3~& literal 28839 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 4096) { + return true; + } String newPath = Utilities.readlink(pathString); if (newPath == null || newPath.equals(pathString)) { break; } pathString = newPath; + tries++; + if (tries >= 10) { + return true; + } } if (pathString != null) { try { @@ -2383,4 +2392,150 @@ public class AndroidUtilities { return sb.toString(); } } + + public static float[] RGBtoHSB(int r, int g, int b) { + float hue, saturation, brightness; + float[] hsbvals = new float[3]; + int cmax = (r > g) ? r : g; + if (b > cmax) { + cmax = b; + } + int cmin = (r < g) ? r : g; + if (b < cmin) { + cmin = b; + } + + brightness = ((float) cmax) / 255.0f; + if (cmax != 0) { + saturation = ((float) (cmax - cmin)) / ((float) cmax); + } else { + saturation = 0; + } + if (saturation == 0) { + hue = 0; + } else { + float redc = ((float) (cmax - r)) / ((float) (cmax - cmin)); + float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin)); + float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin)); + if (r == cmax) { + hue = bluec - greenc; + } else if (g == cmax) { + hue = 2.0f + redc - bluec; + } else { + hue = 4.0f + greenc - redc; + } + hue = hue / 6.0f; + if (hue < 0) { + hue = hue + 1.0f; + } + } + hsbvals[0] = hue; + hsbvals[1] = saturation; + hsbvals[2] = brightness; + return hsbvals; + } + + public static int HSBtoRGB(float hue, float saturation, float brightness) { + int r = 0, g = 0, b = 0; + if (saturation == 0) { + r = g = b = (int) (brightness * 255.0f + 0.5f); + } else { + float h = (hue - (float) Math.floor(hue)) * 6.0f; + float f = h - (float) java.lang.Math.floor(h); + float p = brightness * (1.0f - saturation); + float q = brightness * (1.0f - saturation * f); + float t = brightness * (1.0f - (saturation * (1.0f - f))); + switch ((int) h) { + case 0: + r = (int) (brightness * 255.0f + 0.5f); + g = (int) (t * 255.0f + 0.5f); + b = (int) (p * 255.0f + 0.5f); + break; + case 1: + r = (int) (q * 255.0f + 0.5f); + g = (int) (brightness * 255.0f + 0.5f); + b = (int) (p * 255.0f + 0.5f); + break; + case 2: + r = (int) (p * 255.0f + 0.5f); + g = (int) (brightness * 255.0f + 0.5f); + b = (int) (t * 255.0f + 0.5f); + break; + case 3: + r = (int) (p * 255.0f + 0.5f); + g = (int) (q * 255.0f + 0.5f); + b = (int) (brightness * 255.0f + 0.5f); + break; + case 4: + r = (int) (t * 255.0f + 0.5f); + g = (int) (p * 255.0f + 0.5f); + b = (int) (brightness * 255.0f + 0.5f); + break; + case 5: + r = (int) (brightness * 255.0f + 0.5f); + g = (int) (p * 255.0f + 0.5f); + b = (int) (q * 255.0f + 0.5f); + break; + } + } + return 0xff000000 | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); + } + + public static int getPatternColor(int color) { + float hsb[] = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color)); + if (hsb[1] > 0.0f || (hsb[2] < 1.0f && hsb[2] > 0.0f)) { + hsb[1] = Math.min(1.0f, hsb[1] + 0.05f + 0.1f * (1.0f - hsb[1])); + } + if (hsb[2] > 0.5f) { + hsb[2] = Math.max(0.0f, hsb[2] * 0.65f); + } else { + hsb[2] = Math.max(0.0f, Math.min(1.0f, 1.0f - hsb[2] * 0.65f)); + } + return HSBtoRGB(hsb[0], hsb[1], hsb[2]) & 0x66ffffff; + } + + public static int getPatternSideColor(int color) { + float hsb[] = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color)); + hsb[1] = Math.min(1.0f, hsb[1] + 0.05f); + if (hsb[2] > 0.5f) { + hsb[2] = Math.max(0.0f, hsb[2] * 0.90f); + } else{ + hsb[2] = Math.max(0.0f, hsb[2] * 0.90f); + } + return HSBtoRGB(hsb[0], hsb[1], hsb[2]) | 0xff000000; + } + + public static String getWallPaperUrl(Object object, int currentAccount) { + String link; + if (object instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; + link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/bg/" + wallPaper.slug; + StringBuilder modes = new StringBuilder(); + if (wallPaper.settings != null) { + if (wallPaper.settings.blur) { + modes.append("blur"); + } + if (wallPaper.settings.motion) { + if (modes.length() > 0) { + modes.append("+"); + } + modes.append("motion"); + } + } + if (modes.length() > 0) { + link += "?mode=" + modes.toString(); + } + } else if (object instanceof WallpapersListActivity.ColorWallpaper) { + WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) object; + String color = String.format("%02x%02x%02x", (byte) (wallPaper.color >> 16) & 0xff, (byte) (wallPaper.color >> 8) & 0xff, (byte) (wallPaper.color & 0xff)).toLowerCase(); + if (wallPaper.pattern != null) { + link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/bg/" + wallPaper.pattern.slug + "?intensity=" + (int) (wallPaper.intensity * 100) + "&bg_color=" + color; + } else { + link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/bg/" + color; + } + } else { + link = null; + } + return link; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index a43d6646e..b57f7fa1c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -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 = false; - public static int BUILD_VERSION = 1478; - public static String BUILD_VERSION_STRING = "5.2.0"; + public static int BUILD_VERSION = 1497; + public static String BUILD_VERSION_STRING = "5.3.0"; public static int APP_ID = 0; //obtain your own APP_ID at https://core.telegram.org/api/obtaining_api_id public static String APP_HASH = ""; //obtain your own APP_HASH at https://core.telegram.org/api/obtaining_api_id public static String HOCKEY_APP_HASH = "your-hockeyapp-api-key-here"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 17a48451b..adaefed8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -86,7 +86,7 @@ public class FileRefController { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) parentObject; return "wallpaper" + wallPaper.id; } - return null; + return parentObject != null ? "" + parentObject : null; } @SuppressWarnings("unchecked") @@ -598,21 +598,21 @@ public class FileRefController { } else if (response instanceof TLRPC.TL_account_wallPapers) { TLRPC.TL_account_wallPapers accountWallPapers = (TLRPC.TL_account_wallPapers) response; for (int i = 0, size10 = accountWallPapers.wallpapers.size(); i < size10; i++) { - result = getFileReference(accountWallPapers.wallpapers.get(i).document, requester.location); + result = getFileReference(((TLRPC.TL_wallPaper) accountWallPapers.wallpapers.get(i)).document, requester.location); if (result != null) { break; } } if (result != null && cache) { - MessagesStorage.getInstance(currentAccount).putWallpapers(accountWallPapers.wallpapers, true); + MessagesStorage.getInstance(currentAccount).putWallpapers(accountWallPapers.wallpapers, 1); } } else if (response instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) response; result = getFileReference(wallPaper.document, requester.location); if (result != null && cache) { - ArrayList wallpapers = new ArrayList<>(); + ArrayList wallpapers = new ArrayList<>(); wallpapers.add(wallPaper); - MessagesStorage.getInstance(currentAccount).putWallpapers(wallpapers, false); + MessagesStorage.getInstance(currentAccount).putWallpapers(wallpapers, 0); } } else if (response instanceof TLRPC.Vector) { TLRPC.Vector vector = (TLRPC.Vector) response; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index cb57e39ae..a8b329f3d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -286,7 +286,7 @@ public class ImageLoader { public ArtworkLoadTask(CacheImage cacheImage) { this.cacheImage = cacheImage; - Uri uri = Uri.parse(cacheImage.httpUrl); + Uri uri = Uri.parse((String) cacheImage.location); small = uri.getQueryParameter("s") != null; } @@ -294,7 +294,8 @@ public class ImageLoader { ByteArrayOutputStream outbuf = null; InputStream httpConnectionStream = null; try { - URL downloadUrl = new URL(cacheImage.httpUrl.replace("athumb://", "https://")); + String location = (String) cacheImage.location; + URL downloadUrl = new URL(location.replace("athumb://", "https://")); httpConnection = (HttpURLConnection) downloadUrl.openConnection(); httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1"); httpConnection.setConnectTimeout(5000); @@ -437,10 +438,11 @@ public class ImageLoader { if (!isCancelled()) { try { - if (cacheImage.httpUrl.startsWith("https://static-maps") || cacheImage.httpUrl.startsWith("https://maps.googleapis")) { + String location = (String) cacheImage.location; + if (location.startsWith("https://static-maps") || location.startsWith("https://maps.googleapis")) { int provider = MessagesController.getInstance(cacheImage.currentAccount).mapProvider; if (provider == 3 || provider == 4) { - WebFile webFile = testWebFile.get(cacheImage.httpUrl); + WebFile webFile = testWebFile.get(location); if (webFile != null) { TLRPC.TL_upload_getWebFile req = new TLRPC.TL_upload_getWebFile(); req.location = webFile.location; @@ -453,7 +455,7 @@ public class ImageLoader { } } - URL downloadUrl = new URL(overrideUrl != null ? overrideUrl : cacheImage.httpUrl); + URL downloadUrl = new URL(overrideUrl != null ? overrideUrl : location); httpConnection = (HttpURLConnection) downloadUrl.openConnection(); httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1"); //httpConnection.addRequestProperty("Referer", "google.com"); @@ -927,23 +929,24 @@ public class ImageLoader { } else { try { String mediaThumbPath = null; - if (cacheImage.httpUrl != null) { - if (cacheImage.httpUrl.startsWith("thumb://")) { - int idx = cacheImage.httpUrl.indexOf(":", 8); + if (cacheImage.location instanceof String) { + String location = (String) cacheImage.location; + if (location.startsWith("thumb://")) { + int idx = location.indexOf(":", 8); if (idx >= 0) { - mediaId = Long.parseLong(cacheImage.httpUrl.substring(8, idx)); + mediaId = Long.parseLong(location.substring(8, idx)); mediaIsVideo = false; - mediaThumbPath = cacheImage.httpUrl.substring(idx + 1); + mediaThumbPath = location.substring(idx + 1); } canDeleteFile = false; - } else if (cacheImage.httpUrl.startsWith("vthumb://")) { - int idx = cacheImage.httpUrl.indexOf(":", 9); + } else if (location.startsWith("vthumb://")) { + int idx = location.indexOf(":", 9); if (idx >= 0) { - mediaId = Long.parseLong(cacheImage.httpUrl.substring(9, idx)); + mediaId = Long.parseLong(location.substring(9, idx)); mediaIsVideo = true; } canDeleteFile = false; - } else if (!cacheImage.httpUrl.startsWith("http")) { + } else if (!location.startsWith("http")) { canDeleteFile = false; } } @@ -969,6 +972,7 @@ public class ImageLoader { float h_filter = 0; boolean blur = false; boolean checkInversion = false; + boolean force8888 = false; if (cacheImage.filter != null) { String args[] = cacheImage.filter.split("_"); if (args.length >= 2) { @@ -981,6 +985,9 @@ public class ImageLoader { if (cacheImage.filter.contains("i")) { checkInversion = true; } + if (cacheImage.filter.contains("f")) { + force8888 = true; + } if (w_filter != 0 && h_filter != 0) { opts.inJustDecodeBounds = true; @@ -1057,7 +1064,7 @@ public class ImageLoader { } } - if (cacheImage.filter == null || blur || cacheImage.httpUrl != null) { + if (force8888 || cacheImage.filter == null || blur || cacheImage.location instanceof String) { opts.inPreferredConfig = Bitmap.Config.ARGB_8888; } else { opts.inPreferredConfig = Bitmap.Config.RGB_565; @@ -1240,7 +1247,7 @@ public class ImageLoader { protected String filter; protected String ext; protected SecureDocument secureDocument; - protected TLObject location; + protected Object location; protected boolean animatedFile; protected boolean selfThumb; @@ -1250,7 +1257,6 @@ public class ImageLoader { protected File tempFilePath; protected File encryptionKeyPath; - protected String httpUrl; protected ArtworkLoadTask artworkTask; protected HttpImageTask httpTask; protected CacheOutTask cacheTask; @@ -1916,7 +1922,7 @@ public class ImageLoader { imageLoadQueue.postRunnable(() -> forceLoadingImages.remove(key)); } - private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final String ext, final TLObject imageLocation, final String httpLocation, final String filter, final int size, final int cacheType, final int thumb) { + private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final String ext, final Object imageLocation, final String filter, final int size, final int cacheType, final int thumb) { if (imageReceiver == null || url == null || key == null) { return; } @@ -1933,7 +1939,7 @@ public class ImageLoader { final boolean finalIsNeedsQualityThumb = imageReceiver.isNeedsQualityThumb(); final Object parentObject = imageReceiver.getParentObject(); final boolean shouldGenerateQualityThumb = imageReceiver.isShouldGenerateQualityThumb(); - final int currentAccount = imageReceiver.getcurrentAccount(); + final int currentAccount = imageReceiver.getCurrentAccount(); final boolean currentKeyQuality = imageReceiver.isCurrentKeyQuality(); imageLoadQueue.postRunnable(() -> { boolean added = false; @@ -1970,21 +1976,22 @@ public class ImageLoader { File cacheFile = null; boolean cacheFileExists = false; - if (httpLocation != null) { - if (!httpLocation.startsWith("http") && !httpLocation.startsWith("athumb")) { + if (imageLocation instanceof String) { + String location = (String) imageLocation; + if (!location.startsWith("http") && !location.startsWith("athumb")) { onlyCache = true; - if (httpLocation.startsWith("thumb://")) { - int idx = httpLocation.indexOf(":", 8); + if (location.startsWith("thumb://")) { + int idx = location.indexOf(":", 8); if (idx >= 0) { - cacheFile = new File(httpLocation.substring(idx + 1)); + cacheFile = new File(location.substring(idx + 1)); } - } else if (httpLocation.startsWith("vthumb://")) { - int idx = httpLocation.indexOf(":", 9); + } else if (location.startsWith("vthumb://")) { + int idx = location.indexOf(":", 9); if (idx >= 0) { - cacheFile = new File(httpLocation.substring(idx + 1)); + cacheFile = new File(location.substring(idx + 1)); } } else { - cacheFile = new File(httpLocation); + cacheFile = new File(location); } } } else if (thumb == 0 && currentKeyQuality) { @@ -2036,14 +2043,17 @@ public class ImageLoader { if (thumb != 2) { boolean isEncrypted = imageLocation instanceof TLRPC.TL_documentEncrypted || imageLocation instanceof TLRPC.TL_fileEncryptedLocation; CacheImage img = new CacheImage(); - if (httpLocation != null && !httpLocation.startsWith("vthumb") && !httpLocation.startsWith("thumb")) { - String trueExt = getHttpUrlExtension(httpLocation, "jpg"); - if (trueExt.equals("mp4") || trueExt.equals("gif")) { - img.animatedFile = true; - } - } else if (imageLocation instanceof WebFile && MessageObject.isGifDocument((WebFile) imageLocation) || + if (imageLocation instanceof WebFile && MessageObject.isGifDocument((WebFile) imageLocation) || imageLocation instanceof TLRPC.Document && (MessageObject.isGifDocument((TLRPC.Document) imageLocation) || MessageObject.isRoundVideoDocument((TLRPC.Document) imageLocation))) { img.animatedFile = true; + } else if (imageLocation instanceof String) { + String location = (String) imageLocation; + if (!location.startsWith("vthumb") && !location.startsWith("thumb")) { + String trueExt = getHttpUrlExtension(location, "jpg"); + if (trueExt.equals("mp4") || trueExt.equals("gif")) { + img.animatedFile = true; + } + } } if (cacheFile == null) { @@ -2053,7 +2063,7 @@ public class ImageLoader { img.secureDocument = (SecureDocument) imageLocation; onlyCache = img.secureDocument.secureFile.dc_id == Integer.MIN_VALUE; cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); - } else if (cacheType != 0 || size <= 0 || httpLocation != null || isEncrypted) { + } else if (cacheType != 0 || size <= 0 || imageLocation instanceof String || isEncrypted) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); if (cacheFile.exists()) { cacheFileExists = true; @@ -2076,7 +2086,7 @@ public class ImageLoader { img.selfThumb = thumb != 0; img.key = key; img.filter = filter; - img.httpUrl = httpLocation; + img.location = imageLocation; img.ext = ext; img.currentAccount = currentAccount; if (cacheType == 2) { @@ -2095,9 +2105,24 @@ public class ImageLoader { } } else { img.url = url; - img.location = imageLocation; + imageLoadingByUrl.put(url, img); - if (httpLocation == null) { + if (imageLocation instanceof String) { + String location = (String) imageLocation; + String file = Utilities.MD5(location); + File cacheDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE); + img.tempFilePath = new File(cacheDir, file + "_temp.jpg"); + img.finalFilePath = cacheFile; + if (location.startsWith("athumb")) { + img.artworkTask = new ArtworkLoadTask(img); + artworkTasks.add(img.artworkTask); + runArtworkTasks(false); + } else { + img.httpTask = new HttpImageTask(img, size); + httpTasks.add(img.httpTask); + runHttpTasks(false); + } + } else { if (imageLocation instanceof TLRPC.FileLocation) { TLRPC.FileLocation location = (TLRPC.FileLocation) imageLocation; int localCacheType = cacheType; @@ -2122,20 +2147,6 @@ public class ImageLoader { if (imageReceiver.isForceLoding()) { forceLoadingImages.put(img.key, 0); } - } else { - String file = Utilities.MD5(httpLocation); - File cacheDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE); - img.tempFilePath = new File(cacheDir, file + "_temp.jpg"); - img.finalFilePath = cacheFile; - if (httpLocation.startsWith("athumb")) { - img.artworkTask = new ArtworkLoadTask(img); - artworkTasks.add(img.artworkTask); - runArtworkTasks(false); - } else { - img.httpTask = new HttpImageTask(img, size); - httpTasks.add(img.httpTask); - runHttpTasks(false); - } } } } @@ -2177,14 +2188,12 @@ public class ImageLoader { boolean qualityThumb = false; Object parentObject = imageReceiver.getParentObject(); - TLObject thumbLocation = imageReceiver.getThumbLocation(); - TLObject imageLocation = imageReceiver.getImageLocation(); + Object thumbLocation = imageReceiver.getThumbLocation(); + Object imageLocation = imageReceiver.getImageLocation(); if (imageLocation == null && imageReceiver.isNeedsQualityThumb() && imageReceiver.isCurrentKeyQuality() && parentObject instanceof MessageObject) { imageLocation = ((MessageObject) parentObject).getDocument(); qualityThumb = true; } - String httpLocation = imageReceiver.getHttpImageLocation(); - boolean saveImageToCache = false; String url = null; @@ -2195,11 +2204,12 @@ public class ImageLoader { if (ext == null) { ext = "jpg"; } - if (httpLocation != null) { - key = Utilities.MD5(httpLocation); - url = key + "." + getHttpUrlExtension(httpLocation, "jpg"); - } else if (imageLocation != null) { - if (imageLocation instanceof TLRPC.FileLocation) { + if (imageLocation != null) { + if (imageLocation instanceof String) { + String location = (String) imageLocation; + key = Utilities.MD5(location); + url = key + "." + getHttpUrlExtension(location, "jpg"); + } else if (imageLocation instanceof TLRPC.FileLocation) { TLRPC.FileLocation location = (TLRPC.FileLocation) imageLocation; key = location.volume_id + "_" + location.local_id; url = key + "." + ext; @@ -2266,17 +2276,21 @@ public class ImageLoader { } } - if (thumbLocation instanceof TLRPC.FileLocation) { + if (thumbLocation instanceof String) { + String location = (String) thumbLocation; + thumbKey = Utilities.MD5(location); + thumbUrl = thumbKey + "." + getHttpUrlExtension(location, "jpg"); + } else if (thumbLocation instanceof TLRPC.FileLocation) { TLRPC.FileLocation location = (TLRPC.FileLocation) thumbLocation; thumbKey = location.volume_id + "_" + location.local_id; + thumbUrl = thumbKey + "." + ext; } else if (thumbLocation instanceof TLRPC.TL_photoStrippedSize) { TLRPC.TL_photoStrippedSize location = (TLRPC.TL_photoStrippedSize) thumbLocation; thumbKey = "stripped" + FileRefController.getKeyForParentObject(parentObject); + thumbUrl = thumbKey + "." + ext; } else if (thumbLocation instanceof TLRPC.TL_photoSize) { TLRPC.TL_photoSize photoSize = (TLRPC.TL_photoSize) thumbLocation; thumbKey = photoSize.location.volume_id + "_" + photoSize.location.local_id; - } - if (thumbKey != null) { thumbUrl = thumbKey + "." + ext; } @@ -2289,17 +2303,20 @@ public class ImageLoader { thumbKey += "@" + thumbFilter; } - if (httpLocation != null) { - createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, null, thumbFilter, 0, 1, thumbSet ? 2 : 1); - createLoadOperationForImageReceiver(imageReceiver, key, url, ext, null, httpLocation, filter, 0, 1, 0); + int cacheType; + int thumbCacheType; + if (imageLocation instanceof String) { + cacheType = 1; + thumbCacheType = 1; } else { - int cacheType = imageReceiver.getCacheType(); + cacheType = imageReceiver.getCacheType(); if (cacheType == 0 && saveImageToCache) { cacheType = 1; } - createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, null, thumbFilter, 0, cacheType == 0 ? 1 : cacheType, thumbSet ? 2 : 1); - createLoadOperationForImageReceiver(imageReceiver, key, url, ext, imageLocation, null, filter, imageReceiver.getSize(), cacheType, 0); + thumbCacheType = cacheType == 0 ? 1 : cacheType; } + createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, thumbFilter, 0, thumbCacheType, thumbSet ? 2 : 1); + createLoadOperationForImageReceiver(imageReceiver, key, url, ext, imageLocation, filter, imageReceiver.getSize(), cacheType, 0); } private void httpFileLoadError(final String location) { @@ -2353,7 +2370,7 @@ public class ImageLoader { cacheImage.currentAccount = img.currentAccount; cacheImage.finalFilePath = finalFile; cacheImage.key = key; - cacheImage.httpUrl = img.httpUrl; + cacheImage.location = img.location; cacheImage.selfThumb = thumb; cacheImage.ext = img.ext; cacheImage.encryptionKeyPath = img.encryptionKeyPath; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index c4a89958b..fc00d3bd9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -77,11 +77,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } private class SetImageBackup { - public TLObject fileLocation; - public String httpUrl; + public Object fileLocation; public String filter; public Drawable thumb; - public TLObject thumbLocation; + public Object thumbLocation; public String thumbFilter; public int size; public int cacheType; @@ -102,14 +101,13 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private SetImageBackup setImageBackup; - private TLObject currentImageLocation; + private Object currentImageLocation; private String currentKey; private String currentThumbKey; - private String currentHttpUrl; private String currentFilter; private String currentThumbFilter; private String currentExt; - private TLObject currentThumbLocation; + private Object currentThumbLocation; private int currentSize; private int currentCacheType; private Drawable currentImage; @@ -180,41 +178,41 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } public void setImage(TLObject path, String filter, Drawable thumb, String ext, Object parentObject, int cacheType) { - setImage(path, null, filter, thumb, null, null, 0, ext, parentObject, cacheType); + setImage(path, filter, thumb, null, null, 0, ext, parentObject, cacheType); } public void setImage(TLObject path, String filter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { - setImage(path, null, filter, thumb, null, null, size, ext, parentObject, cacheType); + setImage(path, filter, thumb, null, null, size, ext, parentObject, cacheType); } public void setImage(String httpUrl, String filter, Drawable thumb, String ext, int size) { - setImage(null, httpUrl, filter, thumb, null, null, size, ext, null, 1); + setImage(httpUrl, filter, thumb, null, null, size, ext, null, 1); } public void setImage(TLObject fileLocation, String filter, TLObject thumbLocation, String thumbFilter, String ext, Object parentObject, int cacheType) { - setImage(fileLocation, null, filter, null, thumbLocation, thumbFilter, 0, ext, parentObject, cacheType); + setImage(fileLocation, filter, null, thumbLocation, thumbFilter, 0, ext, parentObject, cacheType); } public void setImage(TLObject fileLocation, String filter, TLObject thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { - setImage(fileLocation, null, filter, null, thumbLocation, thumbFilter, size, ext, parentObject, cacheType); + setImage(fileLocation, filter, null, thumbLocation, thumbFilter, size, ext, parentObject, cacheType); } - public void setImage(TLObject fileLocation, String httpUrl, String filter, Drawable thumb, TLObject thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { + public void setImage(Object fileLocation, String filter, Drawable thumb, Object thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { if (setImageBackup != null) { setImageBackup.fileLocation = null; - setImageBackup.httpUrl = null; setImageBackup.thumbLocation = null; setImageBackup.thumb = null; } - if ((fileLocation == null && httpUrl == null && thumbLocation == null) + if ((fileLocation == null && thumbLocation == null) || (fileLocation != null && !(fileLocation instanceof TLRPC.TL_fileLocation) && !(fileLocation instanceof TLRPC.TL_fileEncryptedLocation) && !(fileLocation instanceof TLRPC.TL_document) && !(fileLocation instanceof WebFile) && !(fileLocation instanceof TLRPC.TL_documentEncrypted) && !(fileLocation instanceof TLRPC.PhotoSize) - && !(fileLocation instanceof SecureDocument))) { + && !(fileLocation instanceof SecureDocument) + && !(fileLocation instanceof String))) { for (int a = 0; a < 3; a++) { recycleBitmap(null, a); } @@ -223,7 +221,6 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentThumbKey = null; currentThumbFilter = null; currentImageLocation = null; - currentHttpUrl = null; currentFilter = null; currentParentObject = null; currentCacheType = 0; @@ -249,38 +246,37 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return; } - if (!(thumbLocation instanceof TLRPC.PhotoSize) && !(thumbLocation instanceof TLRPC.TL_fileLocation) && !(thumbLocation instanceof TLRPC.TL_fileEncryptedLocation)) { + if (!(thumbLocation instanceof String) && !(thumbLocation instanceof TLRPC.PhotoSize) && !(thumbLocation instanceof TLRPC.TL_fileLocation) && !(thumbLocation instanceof TLRPC.TL_fileEncryptedLocation)) { thumbLocation = null; } String key = null; - if (fileLocation != null) { - if (fileLocation instanceof SecureDocument) { - SecureDocument document = (SecureDocument) fileLocation; - key = document.secureFile.dc_id + "_" + document.secureFile.id; - } else if (fileLocation instanceof TLRPC.FileLocation) { - TLRPC.FileLocation location = (TLRPC.FileLocation) fileLocation; - key = location.volume_id + "_" + location.local_id; - } else if (fileLocation instanceof TLRPC.TL_photoStrippedSize) { - TLRPC.TL_photoStrippedSize location = (TLRPC.TL_photoStrippedSize) fileLocation; - key = "stripped" + FileRefController.getKeyForParentObject(parentObject); - } else if (fileLocation instanceof TLRPC.PhotoSize) { - TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) fileLocation; - key = photoSize.location.volume_id + "_" + photoSize.location.local_id; - } else if (fileLocation instanceof WebFile) { - WebFile location = (WebFile) fileLocation; - key = Utilities.MD5(location.url); + if (fileLocation instanceof SecureDocument) { + SecureDocument document = (SecureDocument) fileLocation; + key = document.secureFile.dc_id + "_" + document.secureFile.id; + } else if (fileLocation instanceof TLRPC.FileLocation) { + TLRPC.FileLocation location = (TLRPC.FileLocation) fileLocation; + key = location.volume_id + "_" + location.local_id; + } else if (fileLocation instanceof TLRPC.TL_photoStrippedSize) { + TLRPC.TL_photoStrippedSize location = (TLRPC.TL_photoStrippedSize) fileLocation; + key = "stripped" + FileRefController.getKeyForParentObject(parentObject); + } else if (fileLocation instanceof TLRPC.TL_photoSize || fileLocation instanceof TLRPC.TL_photoCachedSize) { + TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) fileLocation; + key = photoSize.location.volume_id + "_" + photoSize.location.local_id; + } else if (fileLocation instanceof WebFile) { + WebFile location = (WebFile) fileLocation; + key = Utilities.MD5(location.url); + } else if (fileLocation instanceof TLRPC.Document) { + TLRPC.Document location = (TLRPC.Document) fileLocation; + if (location.dc_id != 0) { + key = location.dc_id + "_" + location.id; } else { - TLRPC.Document location = (TLRPC.Document) fileLocation; - if (location.dc_id != 0) { - key = location.dc_id + "_" + location.id; - } else { - fileLocation = null; - } + fileLocation = null; } - } else if (httpUrl != null) { - key = Utilities.MD5(httpUrl); + } else if (fileLocation instanceof String) { + key = Utilities.MD5((String) fileLocation); } + currentKeyQuality = false; if (key == null && needsQualityThumb && parentObject instanceof MessageObject) { TLRPC.Document document = ((MessageObject) parentObject).getDocument(); @@ -309,9 +305,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } else if (thumbLocation instanceof TLRPC.TL_photoStrippedSize) { TLRPC.TL_photoStrippedSize location = (TLRPC.TL_photoStrippedSize) thumbLocation; thumbKey = "stripped" + FileRefController.getKeyForParentObject(parentObject); - } else if (thumbLocation instanceof TLRPC.PhotoSize) { + } else if (thumbLocation instanceof TLRPC.TL_photoSize || thumbLocation instanceof TLRPC.TL_photoCachedSize) { TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) thumbLocation; thumbKey = photoSize.location.volume_id + "_" + photoSize.location.local_id; + } else if (thumbLocation instanceof String) { + thumbKey = Utilities.MD5((String) thumbLocation); } if (thumbKey != null && thumbFilter != null) { thumbKey += "@" + thumbFilter; @@ -364,7 +362,6 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentKey = key; currentExt = ext; currentImageLocation = fileLocation; - currentHttpUrl = httpUrl; currentFilter = filter; currentThumbFilter = thumbFilter; currentSize = size; @@ -504,14 +501,12 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentImage = null; currentThumbFilter = null; currentImageLocation = null; - currentHttpUrl = null; currentFilter = null; currentSize = 0; currentCacheType = 0; bitmapShader = null; if (setImageBackup != null) { setImageBackup.fileLocation = null; - setImageBackup.httpUrl = null; setImageBackup.thumbLocation = null; setImageBackup.thumb = null; } @@ -541,12 +536,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } public void onDetachedFromWindow() { - if (currentImageLocation != null || currentHttpUrl != null || currentThumbLocation != null || staticThumb != null) { + if (currentImageLocation != null || currentThumbLocation != null || staticThumb != null) { if (setImageBackup == null) { setImageBackup = new SetImageBackup(); } setImageBackup.fileLocation = currentImageLocation; - setImageBackup.httpUrl = currentHttpUrl; setImageBackup.filter = currentFilter; setImageBackup.thumb = staticThumb; setImageBackup.thumbLocation = currentThumbLocation; @@ -562,8 +556,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg public boolean onAttachedToWindow() { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didReplacedPhotoInMemCache); - if (setImageBackup != null && (setImageBackup.fileLocation != null || setImageBackup.httpUrl != null || setImageBackup.thumbLocation != null || setImageBackup.thumb != null)) { - setImage(setImageBackup.fileLocation, setImageBackup.httpUrl, setImageBackup.filter, setImageBackup.thumb, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.size, setImageBackup.ext, setImageBackup.parentObject, setImageBackup.cacheType); + if (setImageBackup != null && (setImageBackup.fileLocation != null || setImageBackup.thumbLocation != null || setImageBackup.thumb != null)) { + setImage(setImageBackup.fileLocation, setImageBackup.filter, setImageBackup.thumb, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.size, setImageBackup.ext, setImageBackup.parentObject, setImageBackup.cacheType); return true; } return false; @@ -667,19 +661,21 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg bitmapH /= scale; drawRegion.set(imageX + (imageW - bitmapW) / 2, imageY + (imageH - bitmapH) / 2, imageX + (imageW + bitmapW) / 2, imageY + (imageH + bitmapH) / 2); bitmapDrawable.setBounds(drawRegion); - try { - bitmapDrawable.setAlpha(alpha); - bitmapDrawable.draw(canvas); - } catch (Exception e) { - if (bitmapDrawable == currentImage && currentKey != null) { - ImageLoader.getInstance().removeImage(currentKey); - currentKey = null; - } else if (bitmapDrawable == currentThumb && currentThumbKey != null) { - ImageLoader.getInstance().removeImage(currentThumbKey); - currentThumbKey = null; + if (isVisible) { + try { + bitmapDrawable.setAlpha(alpha); + bitmapDrawable.draw(canvas); + } catch (Exception e) { + if (bitmapDrawable == currentImage && currentKey != null) { + ImageLoader.getInstance().removeImage(currentKey); + currentKey = null; + } else if (bitmapDrawable == currentThumb && currentThumbKey != null) { + ImageLoader.getInstance().removeImage(currentThumbKey); + currentThumbKey = null; + } + setImage(currentImageLocation, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentParentObject, currentCacheType); + FileLog.e(e); } - setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentParentObject, currentCacheType); - FileLog.e(e); } canvas.restore(); } else { @@ -726,7 +722,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().removeImage(currentThumbKey); currentThumbKey = null; } - setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentParentObject, currentCacheType); + setImage(currentImageLocation, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentParentObject, currentCacheType); FileLog.e(e); } } @@ -766,7 +762,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().removeImage(currentThumbKey); currentThumbKey = null; } - setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentParentObject, currentCacheType); + setImage(currentImageLocation, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentParentObject, currentCacheType); FileLog.e(e); } } @@ -1033,7 +1029,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } public boolean hasImage() { - return currentImage != null || currentThumb != null || currentKey != null || currentHttpUrl != null || staticThumb != null; + return currentImage != null || currentThumb != null || currentKey != null || staticThumb != null; } public boolean hasBitmapImage() { @@ -1044,10 +1040,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return currentImage != null; } + public boolean hasStaticThumb() { + return staticThumb != null; + } + public void setAspectFit(boolean value) { isAspectFit = value; } + public boolean isAspectFit() { + return isAspectFit; + } + public void setParentView(View view) { parentView = view; if (currentImage instanceof AnimatedFileDrawable) { @@ -1143,18 +1147,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return currentSize; } - public TLObject getImageLocation() { + public Object getImageLocation() { return currentImageLocation; } - public TLObject getThumbLocation() { + public Object getThumbLocation() { return currentThumbLocation; } - public String getHttpImageLocation() { - return currentHttpUrl; - } - public int getCacheType() { return currentCacheType; } @@ -1203,7 +1203,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return currentKeyQuality; } - public int getcurrentAccount() { + public int getCurrentAccount() { return currentAccount; } @@ -1424,20 +1424,20 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg String oldKey = (String) args[0]; if (currentKey != null && currentKey.equals(oldKey)) { currentKey = (String) args[1]; - currentImageLocation = (TLObject) args[2]; + currentImageLocation = args[2]; } if (currentThumbKey != null && currentThumbKey.equals(oldKey)) { currentThumbKey = (String) args[1]; - currentThumbLocation = (TLObject) args[2]; + currentThumbLocation = args[2]; } if (setImageBackup != null) { if (currentKey != null && currentKey.equals(oldKey)) { currentKey = (String) args[1]; - currentImageLocation = (TLObject) args[2]; + currentImageLocation = args[2]; } if (currentThumbKey != null && currentThumbKey.equals(oldKey)) { currentThumbKey = (String) args[1]; - currentThumbLocation = (TLObject) args[2]; + currentThumbLocation = args[2]; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index e89b91420..8ed50a750 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -53,9 +53,7 @@ public class LocaleController { public FastDateFormat formatterDay; public FastDateFormat formatterWeek; public FastDateFormat formatterDayMonth; - public FastDateFormat formatterMonth; public FastDateFormat formatterYear; - public FastDateFormat formatterMonthYear; public FastDateFormat formatterYearMax; public FastDateFormat formatterStats; public FastDateFormat formatterBannedUntil; @@ -1426,14 +1424,12 @@ public class LocaleController { nameDisplayOrder = lang.equals("ko") ? 2 : 1; formatterDayMonth = createFormatter(locale, getStringInternal("formatterMonth", R.string.formatterMonth), "dd MMM"); - formatterMonth = createFormatter(locale, getStringInternal("formatterMonthName", R.string.formatterMonthName), "LLLL"); formatterYear = createFormatter(locale, getStringInternal("formatterYear", R.string.formatterYear), "dd.MM.yy"); formatterYearMax = createFormatter(locale, getStringInternal("formatterYearMax", R.string.formatterYearMax), "dd.MM.yyyy"); chatDate = createFormatter(locale, getStringInternal("chatDate", R.string.chatDate), "d MMMM"); chatFullDate = createFormatter(locale, getStringInternal("chatFullDate", R.string.chatFullDate), "d MMMM yyyy"); formatterWeek = createFormatter(locale, getStringInternal("formatterWeek", R.string.formatterWeek), "EEE"); formatterScheduleDay = createFormatter(locale, getStringInternal("formatDateScheduleDay", R.string.formatDateScheduleDay), "EEE MMM d"); - formatterMonthYear = createFormatter(locale, getStringInternal("formatterMonthYear2", R.string.formatterMonthYear2), "LLLL yyyy"); formatterDay = createFormatter(lang.toLowerCase().equals("ar") || lang.toLowerCase().equals("ko") ? locale : Locale.US, is24HourFormat ? getStringInternal("formatterDay24H", R.string.formatterDay24H) : getStringInternal("formatterDay12H", R.string.formatterDay12H), is24HourFormat ? "HH:mm" : "h:mm a"); formatterStats = createFormatter(locale, is24HourFormat ? getStringInternal("formatterStats24H", R.string.formatterStats24H) : getStringInternal("formatterStats12H", R.string.formatterStats12H), is24HourFormat ? "MMM dd yyyy, HH:mm" : "MMM dd yyyy, h:mm a"); formatterBannedUntil = createFormatter(locale, is24HourFormat ? getStringInternal("formatterBannedUntil24H", R.string.formatterBannedUntil24H) : getStringInternal("formatterBannedUntil12H", R.string.formatterBannedUntil12H), is24HourFormat ? "MMM dd yyyy, HH:mm" : "MMM dd yyyy, h:mm a"); @@ -1451,11 +1447,26 @@ public class LocaleController { int year = rightNow.get(Calendar.YEAR); rightNow.setTimeInMillis(date); int dateYear = rightNow.get(Calendar.YEAR); + int month = rightNow.get(Calendar.MONTH); + final String[] months = new String[]{ + LocaleController.getString("January", R.string.January), + LocaleController.getString("February", R.string.February), + LocaleController.getString("March", R.string.March), + LocaleController.getString("April", R.string.April), + LocaleController.getString("May", R.string.May), + LocaleController.getString("June", R.string.June), + LocaleController.getString("July", R.string.July), + LocaleController.getString("August", R.string.August), + LocaleController.getString("September", R.string.September), + LocaleController.getString("October", R.string.October), + LocaleController.getString("November", R.string.November), + LocaleController.getString("December", R.string.December) + }; if (year == dateYear) { - return getInstance().formatterMonth.format(new Date(date)); + return months[month]; } else { - return getInstance().formatterMonthYear.format(new Date(date)); + return months[month] + " " + dateYear; } } catch (Exception e) { FileLog.e(e); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index d326ab22d..28bd9ef7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -357,6 +357,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, private static Runnable refreshGalleryRunnable; public static AlbumEntry allMediaAlbumEntry; public static AlbumEntry allPhotosAlbumEntry; + public static AlbumEntry allVideosAlbumEntry; private static Runnable broadcastPhotosRunnable; private boolean isPaused = false; @@ -3026,6 +3027,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, SparseArray mediaAlbums = new SparseArray<>(); SparseArray photoAlbums = new SparseArray<>(); AlbumEntry allPhotosAlbum = null; + AlbumEntry allVideosAlbum = null; AlbumEntry allMediaAlbum = null; String cameraFolder = null; try { @@ -3139,10 +3141,22 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, (int) (duration / 1000), true); + if (allVideosAlbum == null) { + allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideos", R.string.AllVideos), photoEntry); + int index = 0; + if (allMediaAlbum != null) { + index++; + } + if (allPhotosAlbum != null) { + index++; + } + mediaAlbumsSorted.add(index, allVideosAlbum); + } if (allMediaAlbum == null) { allMediaAlbum = new AlbumEntry(0, LocaleController.getString("AllMedia", R.string.AllMedia), photoEntry); mediaAlbumsSorted.add(0, allMediaAlbum); } + allVideosAlbum.addPhoto(photoEntry); allMediaAlbum.addPhoto(photoEntry); AlbumEntry albumEntry = mediaAlbums.get(bucketId); @@ -3182,24 +3196,25 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return 0; }); } - broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, mediaCameraAlbumId, allMediaAlbum, allPhotosAlbum, 0); + broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, mediaCameraAlbumId, allMediaAlbum, allPhotosAlbum, allVideosAlbum, 0); }); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } - private static void broadcastNewPhotos(final int guid, final ArrayList mediaAlbumsSorted, final ArrayList photoAlbumsSorted, final Integer cameraAlbumIdFinal, final AlbumEntry allMediaAlbumFinal, final AlbumEntry allPhotosAlbumFinal, int delay) { + private static void broadcastNewPhotos(final int guid, final ArrayList mediaAlbumsSorted, final ArrayList photoAlbumsSorted, final Integer cameraAlbumIdFinal, final AlbumEntry allMediaAlbumFinal, final AlbumEntry allPhotosAlbumFinal, final AlbumEntry allVideosAlbumFinal, int delay) { if (broadcastPhotosRunnable != null) { AndroidUtilities.cancelRunOnUIThread(broadcastPhotosRunnable); } AndroidUtilities.runOnUIThread(broadcastPhotosRunnable = () -> { if (PhotoViewer.getInstance().isVisible()) { - broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal, allMediaAlbumFinal, allPhotosAlbumFinal, 1000); + broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal, allMediaAlbumFinal, allPhotosAlbumFinal, allVideosAlbumFinal, 1000); return; } broadcastPhotosRunnable = null; allPhotosAlbumEntry = allPhotosAlbumFinal; allMediaAlbumEntry = allMediaAlbumFinal; + allVideosAlbumEntry = allVideosAlbumFinal; for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { NotificationCenter.getInstance(a).postNotificationName(NotificationCenter.albumsDidLoad, guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index a85f4d555..73af5e6bf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -9,6 +9,7 @@ package org.telegram.messenger; import android.graphics.Typeface; +import android.net.Uri; import android.os.Build; import android.text.Layout; import android.text.Spannable; @@ -2314,6 +2315,10 @@ public class MessageObject { return false; } + public void resetLayout() { + layoutCreated = false; + } + public String getMimeType() { if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { return messageOwner.media.document.mime_type; @@ -3098,14 +3103,32 @@ public class MessageObject { } public int getMaxMessageTextWidth() { - int maxWidth; - generatedWithMinSize = AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() : AndroidUtilities.displaySize.x; - maxWidth = generatedWithMinSize - AndroidUtilities.dp(needDrawAvatarInternal() && !isOutOwner() ? 132 : 80); - if (needDrawShareButton() && !isOutOwner()) { - maxWidth -= AndroidUtilities.dp(10); + int maxWidth = 0; + if (AndroidUtilities.isTablet() && eventId != 0) { + generatedWithMinSize = AndroidUtilities.dp(530); + } else { + generatedWithMinSize = AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() : AndroidUtilities.displaySize.x; } - if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - maxWidth -= AndroidUtilities.dp(10); + if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage != null && "telegram_background".equals(messageOwner.media.webpage.type)) { + try { + Uri uri = Uri.parse(messageOwner.media.webpage.url); + if (uri.getQueryParameter("bg_color") != null) { + maxWidth = AndroidUtilities.dp(220); + } else if (uri.getLastPathSegment().length() == 6) { + maxWidth = AndroidUtilities.dp(200); + } + } catch (Exception ignore) { + + } + } + if (maxWidth == 0) { + maxWidth = generatedWithMinSize - AndroidUtilities.dp(needDrawAvatarInternal() && !isOutOwner() ? 132 : 80); + if (needDrawShareButton() && !isOutOwner()) { + maxWidth -= AndroidUtilities.dp(10); + } + if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { + maxWidth -= AndroidUtilities.dp(10); + } } return maxWidth; } @@ -4342,6 +4365,26 @@ public class MessageObject { return messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage != null && "telegram_background".equals(messageOwner.media.webpage.type); } + public int getMediaExistanceFlags() { + int flags = 0; + if (attachPathExists) { + flags |= 1; + } + if (mediaExists) { + flags |= 2; + } + return flags; + } + + public void applyMediaExistanceFlags(int flags) { + if (flags == -1) { + checkMediaExistance(); + } else { + attachPathExists = (flags & 1) != 0; + mediaExists = (flags & 2) != 0; + } + } + public void checkMediaExistance() { File cacheFile = null; attachPathExists = false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 281bcb123..69d3a7f90 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -64,6 +64,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter public ArrayList dialogsForward = new ArrayList<>(); public ArrayList dialogsServerOnly = new ArrayList<>(); public ArrayList dialogsGroupsOnly = new ArrayList<>(); + public ArrayList dialogsChannelsOnly = new ArrayList<>(); + public ArrayList dialogsUsersOnly = new ArrayList<>(); public int unreadUnmutedDialogs; public int nextDialogsCacheOffset; public ConcurrentHashMap dialogs_read_inbox_max = new ConcurrentHashMap<>(100, 1.0f, 2); @@ -189,6 +191,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter private boolean offlineSent; private String uploadingAvatar; + private String uploadingWallpaper; + private boolean uploadingWallpaperBlurred; + private boolean uploadingWallpaperMotion; + public boolean enableJoined; public String linkPrefix; public int maxGroupCount; @@ -689,11 +695,52 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } }); + } else if (uploadingWallpaper != null && uploadingWallpaper.equals(location)) { + TLRPC.TL_account_uploadWallPaper req = new TLRPC.TL_account_uploadWallPaper(); + req.file = file; + req.mime_type = "image/jpeg"; + final TLRPC.TL_wallPaperSettings settings = new TLRPC.TL_wallPaperSettings(); + settings.blur = uploadingWallpaperBlurred; + settings.motion = uploadingWallpaperMotion; + req.settings = settings; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) response; + File path = new File(ApplicationLoader.getFilesDirFixed(), uploadingWallpaperBlurred ? "wallpaper_original.jpg" : "wallpaper.jpg"); + if (wallPaper != null) { + try { + AndroidUtilities.copyFile(path, FileLoader.getPathToAttach(wallPaper.document, true)); + } catch (Exception ignore) { + + } + } + AndroidUtilities.runOnUIThread(() -> { + if (uploadingWallpaper != null && wallPaper != null) { + wallPaper.settings = settings; + wallPaper.flags |= 4; + SharedPreferences preferences = getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putLong("selectedBackground2", wallPaper.id); + editor.commit(); + ArrayList wallpapers = new ArrayList<>(); + wallpapers.add(wallPaper); + MessagesStorage.getInstance(currentAccount).putWallpapers(wallpapers, 2); + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 320); + if (image != null) { + String newKey = image.location.volume_id + "_" + image.location.local_id + "@100_100"; + String oldKey = Utilities.MD5(path.getAbsolutePath()) + "@100_100"; + ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, image.location, false); + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.wallpapersNeedReload, wallPaper.id); + } + }); + }); } } else if (id == NotificationCenter.FileDidFailUpload) { final String location = (String) args[0]; if (uploadingAvatar != null && uploadingAvatar.equals(location)) { uploadingAvatar = null; + } else if (uploadingWallpaper != null && uploadingWallpaper.equals(location)) { + uploadingWallpaper = null; } } else if (id == NotificationCenter.messageReceivedByServer) { Integer msgId = (Integer) args[0]; @@ -762,6 +809,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogsServerOnly.clear(); dialogsForward.clear(); dialogsGroupsOnly.clear(); + dialogsChannelsOnly.clear(); + dialogsUsersOnly.clear(); dialogMessagesByIds.clear(); dialogMessagesByRandomIds.clear(); channelAdmins.clear(); @@ -829,6 +878,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter registeringForPush = false; getDifferenceFirstSync = true; uploadingAvatar = null; + uploadingWallpaper = null; statusRequest = 0; statusSettingState = 0; @@ -2185,6 +2235,83 @@ public class MessagesController implements NotificationCenter.NotificationCenter FileLoader.getInstance(currentAccount).uploadFile(uploadingAvatar, false, true, ConnectionsManager.FileTypePhoto); } + public void saveWallpaperToServer(File path, long wallPaperId, long accessHash, boolean isBlurred, boolean isMotion, int backgroundColor, float intesity, boolean install, long taskId) { + if (uploadingWallpaper != null) { + File finalPath = new File(ApplicationLoader.getFilesDirFixed(), uploadingWallpaperBlurred ? "wallpaper_original.jpg" : "wallpaper.jpg"); + if (path != null && (path.getAbsolutePath().equals(uploadingWallpaper) || path.equals(finalPath))) { + uploadingWallpaperMotion = isMotion; + uploadingWallpaperBlurred = isBlurred; + return; + } + FileLoader.getInstance(currentAccount).cancelUploadFile(uploadingWallpaper, false); + uploadingWallpaper = null; + } + if (path != null) { + uploadingWallpaper = path.getAbsolutePath(); + uploadingWallpaperMotion = isMotion; + uploadingWallpaperBlurred = isBlurred; + FileLoader.getInstance(currentAccount).uploadFile(uploadingWallpaper, false, true, ConnectionsManager.FileTypePhoto); + } else if (accessHash != 0) { + TLRPC.TL_inputWallPaper inputWallPaper = new TLRPC.TL_inputWallPaper(); + inputWallPaper.id = wallPaperId; + inputWallPaper.access_hash = accessHash; + + TLRPC.TL_wallPaperSettings settings = new TLRPC.TL_wallPaperSettings(); + settings.blur = isBlurred; + settings.motion = isMotion; + if (backgroundColor != 0) { + settings.background_color = backgroundColor; + settings.flags |= 1; + settings.intensity = (int) (intesity * 100); + settings.flags |= 8; + } + + TLObject req; + if (install) { + TLRPC.TL_account_installWallPaper request = new TLRPC.TL_account_installWallPaper(); + request.wallpaper = inputWallPaper; + request.settings = settings; + req = request; + } else { + TLRPC.TL_account_saveWallPaper request = new TLRPC.TL_account_saveWallPaper(); + request.wallpaper = inputWallPaper; + request.settings = settings; + req = request; + } + + final long newTaskId; + if (taskId != 0) { + newTaskId = taskId; + } else { + NativeByteBuffer data = null; + try { + data = new NativeByteBuffer(44); + data.writeInt32(12); + data.writeInt64(wallPaperId); + data.writeInt64(accessHash); + data.writeBool(isBlurred); + data.writeBool(isMotion); + data.writeInt32(backgroundColor); + data.writeDouble(intesity); + data.writeBool(install); + } catch (Exception e) { + FileLog.e(e); + } + newTaskId = MessagesStorage.getInstance(currentAccount).createPendingTask(data); + } + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + if (!install && uploadingWallpaper != null) { + SharedPreferences preferences = getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putLong("selectedBackground2", wallPaperId); + editor.commit(); + } + }); + } + } + public void markChannelDialogMessageAsDeleted(ArrayList messages, final int channelId) { MessageObject obj = dialogMessage.get((long) -channelId); if (obj != null) { @@ -2381,6 +2508,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } dialogsGroupsOnly.remove(dialog); + dialogsChannelsOnly.remove(dialog); + dialogsUsersOnly.remove(dialog); dialogsForward.remove(dialog); dialogs_dict.remove(did); dialogs_read_inbox_max.remove(did); @@ -4265,6 +4394,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); + final SparseArray enc_chats_dict; final LongSparseArray new_dialogMessage = new LongSparseArray<>(); final SparseArray usersDict = new SparseArray<>(); final SparseArray chatsDict = new SparseArray<>(); @@ -4277,6 +4407,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter TLRPC.Chat c = dialogsRes.chats.get(a); chatsDict.put(c.id, c); } + if (encChats != null) { + enc_chats_dict = new SparseArray<>(); + for (int a = 0, N = encChats.size(); a < N; a++) { + TLRPC.EncryptedChat encryptedChat = encChats.get(a); + enc_chats_dict.put(encryptedChat.id, encryptedChat); + } + } else { + enc_chats_dict = null; + } if (loadType == 1) { nextDialogsCacheOffset = offset + count; } @@ -4365,6 +4504,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (d.id == 0) { continue; } + int lower_id = (int) d.id; + int high_id = (int) (d.id >> 32); + if (lower_id == 0 && enc_chats_dict != null) { + if (enc_chats_dict.get(high_id) == null) { + continue; + } + } if (proxyDialogId != 0 && proxyDialogId == d.id) { proxyDialog = d; } @@ -6457,7 +6603,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter long[] ids = corrected.valueAt(a); int oldId = (int) ids[1]; SendMessagesHelper.getInstance(currentAccount).processSentMessage(oldId); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L, -1); } }); } @@ -6703,7 +6849,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter long[] ids = corrected.valueAt(a); int oldId = (int) ids[1]; SendMessagesHelper.getInstance(currentAccount).processSentMessage(oldId); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L, -1); } }); } @@ -9593,6 +9739,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogs.remove(dialog); dialogsServerOnly.remove(dialog); dialogsGroupsOnly.remove(dialog); + dialogsChannelsOnly.remove(dialog); + dialogsUsersOnly.remove(dialog); dialogsForward.remove(dialog); dialogs_dict.remove(dialog.id); dialogs_read_inbox_max.remove(dialog.id); @@ -9711,6 +9859,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter public void sortDialogs(SparseArray chatsDict) { dialogsServerOnly.clear(); dialogsGroupsOnly.clear(); + dialogsChannelsOnly.clear(); + dialogsUsersOnly.clear(); dialogsForward.clear(); unreadUnmutedDialogs = 0; boolean selfAdded = false; @@ -9740,6 +9890,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (chat != null && (chat.megagroup && (chat.admin_rights != null && (chat.admin_rights.post_messages || chat.admin_rights.add_admins)) || chat.creator)) { dialogsGroupsOnly.add(d); } + if (chat != null && chat.megagroup) { + + } else { + dialogsChannelsOnly.add(d); + } } else if (lower_id < 0) { if (chatsDict != null) { TLRPC.Chat chat = chatsDict.get(-lower_id); @@ -9750,6 +9905,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } dialogsGroupsOnly.add(d); + } else if (lower_id > 0) { + dialogsUsersOnly.add(d); } } if (proxyDialog != null && d.id == proxyDialog.id && isLeftProxyChannel) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index ab046fcf1..5397ecc74 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -1013,6 +1013,17 @@ public class MessagesStorage { AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).markMessageAsRead(mid, channelId, inputChannel, ttl, taskId)); break; } + case 12: { + long wallPaperId = data.readInt64(false); + long accessHash = data.readInt64(false); + boolean isBlurred = data.readBool(false); + boolean isMotion = data.readBool(false); + int backgroundColor = data.readInt32(false); + float intesity = (float) data.readDouble(false); + boolean install = data.readBool(false); + AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).saveWallpaperToServer(null, wallPaperId, accessHash, isBlurred, isMotion, backgroundColor, intesity, install, taskId)); + break; + } } data.reuse(); } @@ -1333,28 +1344,28 @@ public class MessagesStorage { }); } - public void putWallpapers(final ArrayList wallPapers, boolean replace) { + public void putWallpapers(final ArrayList wallPapers, int action) { storageQueue.postRunnable(() -> { try { - if (replace) { + if (action == 1) { database.executeFast("DELETE FROM wallpapers2 WHERE 1").stepThis().dispose(); } database.beginTransaction(); SQLitePreparedStatement state; - if (replace) { + if (action != 0) { state = database.executeFast("REPLACE INTO wallpapers2 VALUES(?, ?, ?)"); } else { state = database.executeFast("UPDATE wallpapers2 SET data = ? WHERE uid = ?"); } for (int a = 0, N = wallPapers.size(); a < N; a++) { - TLRPC.TL_wallPaper wallPaper = wallPapers.get(a); + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) wallPapers.get(a); state.requery(); NativeByteBuffer data = new NativeByteBuffer(wallPaper.getObjectSize()); wallPaper.serializeToStream(data); - if (replace) { + if (action != 0) { state.bindLong(1, wallPaper.id); state.bindByteBuffer(2, data); - state.bindInteger(3, a); + state.bindInteger(3, action == 2 ? -1 : a); } else { state.bindByteBuffer(1, data); state.bindLong(2, wallPaper.id); @@ -1379,7 +1390,7 @@ public class MessagesStorage { while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { - TLRPC.TL_wallPaper wallPaper = TLRPC.TL_wallPaper.TLdeserialize(data, data.readInt32(false), false); + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) TLRPC.WallPaper.TLdeserialize(data, data.readInt32(false), false); data.reuse(); if (wallPaper != null) { wallPapers.add(wallPaper); @@ -7292,7 +7303,6 @@ public class MessagesStorage { if (!encryptedToLoad.isEmpty()) { getEncryptedChatsInternal(TextUtils.join(",", encryptedToLoad), encryptedChats, usersToLoad); } - if (!chatsToLoad.isEmpty()) { getChatsInternal(TextUtils.join(",", chatsToLoad), dialogs.chats); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 17564927c..8b0e000bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -134,6 +134,7 @@ public class NotificationCenter { public static final int pushMessagesUpdated = totalEvents++; public static final int stopEncodingService = totalEvents++; public static final int wallpapersDidLoad = totalEvents++; + public static final int wallpapersNeedReload = totalEvents++; public static final int didReceiveSmsCode = totalEvents++; public static final int didReceiveCall = totalEvents++; public static final int emojiDidLoad = totalEvents++; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index 438c08239..2fbb38a42 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -704,8 +704,12 @@ public class SecretChatHelper { if (isSecretVisibleMessage(newMsgObj)) { newMsgObj.date = res.date; } + int existFlags; if (newMsg != null && res.file instanceof TLRPC.TL_encryptedFile) { updateMediaPaths(newMsg, res.file, req, originalPath); + existFlags = newMsg.getMediaExistanceFlags(); + } else { + existFlags = 0; } MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { if (isSecretInvisibleMessage(newMsgObj)) { @@ -714,7 +718,7 @@ public class SecretChatHelper { MessagesStorage.getInstance(currentAccount).updateMessageStateAndId(newMsgObj.random_id, newMsgObj.id, newMsgObj.id, res.date, false, 0); AndroidUtilities.runOnUIThread(() -> { newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags); SendMessagesHelper.getInstance(currentAccount).processSentMessage(newMsgObj.id); if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj)) { SendMessagesHelper.getInstance(currentAccount).stopVideoService(attachPath); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 3c0b1251f..8c61c5b6f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -981,10 +981,15 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter return; } if (messageObject.messageOwner.media != null && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty) && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice)) { + HashMap params = null; + if ((int) did == 0 && messageObject.messageOwner.to_id != null && (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photo || messageObject.messageOwner.media.document instanceof TLRPC.TL_document)) { + params = new HashMap<>(); + params.put("parentObject", "sent_" + messageObject.messageOwner.to_id.channel_id + "_" + messageObject.getId()); + } if (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photo) { - sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, null, messageObject.messageOwner.media.ttl_seconds, messageObject); + sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, messageObject.messageOwner.media.ttl_seconds, messageObject); } else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_document) { - sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, null, messageObject.messageOwner.media.ttl_seconds, messageObject); + sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, messageObject.messageOwner.media.ttl_seconds, messageObject); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo) { sendMessage(messageObject.messageOwner.media, did, messageObject.replyMessageObject, null, null); } else if (messageObject.messageOwner.media.phone_number != null) { @@ -1438,6 +1443,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter final ArrayList sentMessages = new ArrayList<>(); sentMessages.add(message); updateMediaPaths(msgObj1, message, message.id, null, true); + int existFlags = msgObj1.getMediaExistanceFlags(); newMsgObj1.id = message.id; sentCount++; MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { @@ -1446,7 +1452,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(() -> { newMsgObj1.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; DataQuery.getInstance(currentAccount).increasePeerRaiting(peer); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, message.id, message, peer, 0L); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, message.id, message, peer, 0L, existFlags); processSentMessage(oldId); removeFromSendingMessages(oldId); }); @@ -3078,7 +3084,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.originalPath = originalPath; delayedMessage.sendEncryptedRequest = reqSend; delayedMessage.obj = newMsgObj; - delayedMessage.parentObject = parentObject; + if (params != null && params.containsKey("parentObject")) { + delayedMessage.parentObject = params.get("parentObject"); + } else { + delayedMessage.parentObject = parentObject; + } delayedMessage.performMediaUpload = true; } if (!TextUtils.isEmpty(path) && path.startsWith("http")) { @@ -3138,7 +3148,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.sendEncryptedRequest = reqSend; delayedMessage.originalPath = originalPath; delayedMessage.obj = newMsgObj; - delayedMessage.parentObject = parentObject; + if (params != null && params.containsKey("parentObject")) { + delayedMessage.parentObject = params.get("parentObject"); + } else { + delayedMessage.parentObject = parentObject; + } delayedMessage.performMediaUpload = true; } delayedMessage.videoEditedInfo = videoEditedInfo; @@ -3202,7 +3216,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.sendEncryptedRequest = reqSend; delayedMessage.type = 2; delayedMessage.obj = newMsgObj; - delayedMessage.parentObject = parentObject; + if (params != null && params.containsKey("parentObject")) { + delayedMessage.parentObject = params.get("parentObject"); + } else { + delayedMessage.parentObject = parentObject; + } delayedMessage.encryptedChat = encryptedChat; delayedMessage.performMediaUpload = true; if (path != null && path.length() > 0 && path.startsWith("http")) { @@ -3378,7 +3396,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } if (!file.exists()) { putToDelayedMessages(FileLoader.getAttachFileName(message.location), message); - FileLoader.getInstance(currentAccount).loadFile(message.location, message, "jpg", 0, 2, 0); + FileLoader.getInstance(currentAccount).loadFile(message.location, message.parentObject, "jpg", 0, 2, 0); return; } } @@ -3454,7 +3472,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter File file = new File(location); if (!file.exists()) { putToDelayedMessages(FileLoader.getAttachFileName(document), message); - FileLoader.getInstance(currentAccount).loadFile(document, message, 2, 0); + FileLoader.getInstance(currentAccount).loadFile(document, message.parentObject, 2, 0); return; } } @@ -3496,7 +3514,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter File file = new File(location); if (!file.exists()) { putToDelayedMessages(FileLoader.getAttachFileName(document), message); - FileLoader.getInstance(currentAccount).loadFile(document, message, 2, 0); + FileLoader.getInstance(currentAccount).loadFile(document, message.parentObject, 2, 0); return; } } @@ -3820,6 +3838,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter final ArrayList sentMessages = new ArrayList<>(); final String attachPath = newMsgObj.attachPath; final long grouped_id; + final int existFlags; Integer id = newIds.get(newMsgObj.random_id); if (id != null) { @@ -3827,6 +3846,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (message != null) { sentMessages.add(message); updateMediaPaths(msgObj, message, message.id, originalPath, false); + existFlags = msgObj.getMediaExistanceFlags(); newMsgObj.id = message.id; if ((newMsgObj.flags & TLRPC.MESSAGE_FLAG_MEGAGROUP) != 0) { message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; @@ -3851,13 +3871,13 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (!isSentError) { StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, 1); newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags); MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { MessagesStorage.getInstance(currentAccount).updateMessageStateAndId(newMsgObj.random_id, oldId, newMsgObj.id, 0, false, newMsgObj.to_id.channel_id); MessagesStorage.getInstance(currentAccount).putMessages(sentMessages, true, false, false, 0); AndroidUtilities.runOnUIThread(() -> { DataQuery.getInstance(currentAccount).increasePeerRaiting(newMsgObj.dialog_id); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags); processSentMessage(oldId); removeFromSendingMessages(oldId); }); @@ -4012,9 +4032,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter final boolean isBroadcast = req instanceof TLRPC.TL_messages_sendBroadcast; final ArrayList sentMessages = new ArrayList<>(); final String attachPath = newMsgObj.attachPath; + final int existFlags; if (response instanceof TLRPC.TL_updateShortSentMessage) { final TLRPC.TL_updateShortSentMessage res = (TLRPC.TL_updateShortSentMessage) response; updateMediaPaths(msgObj, null, res.id, null, false); + existFlags = msgObj.getMediaExistanceFlags(); newMsgObj.local_id = newMsgObj.id = res.id; newMsgObj.date = res.date; newMsgObj.entities = res.entities; @@ -4064,11 +4086,15 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } message.unread = value < message.id; updateMediaPaths(msgObj, message, message.id, originalPath, false); + existFlags = msgObj.getMediaExistanceFlags(); newMsgObj.id = message.id; } else { isSentError = true; + existFlags = 0; } Utilities.stageQueue.postRunnable(() -> MessagesController.getInstance(currentAccount).processUpdates(updates, false)); + } else { + existFlags = 0; } if (MessageObject.isLiveLocationMessage(newMsgObj)) { @@ -4078,7 +4104,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (!isSentError) { StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, 1); newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.id), newMsgObj, newMsgObj.dialog_id, 0L); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.id), newMsgObj, newMsgObj.dialog_id, 0L, existFlags); MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { MessagesStorage.getInstance(currentAccount).updateMessageStateAndId(newMsgObj.random_id, oldId, (isBroadcast ? oldId : newMsgObj.id), 0, false, newMsgObj.to_id.channel_id); MessagesStorage.getInstance(currentAccount).putMessages(sentMessages, true, false, isBroadcast, 0); @@ -4099,7 +4125,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); } DataQuery.getInstance(currentAccount).increasePeerRaiting(newMsgObj.dialog_id); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.id), newMsgObj, newMsgObj.dialog_id, 0L); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.id), newMsgObj, newMsgObj.dialog_id, 0L, existFlags); processSentMessage(oldId); removeFromSendingMessages(oldId); }); @@ -4569,6 +4595,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter case "opus": document.mime_type = "audio/opus"; break; + case "mp3": + document.mime_type = "audio/mpeg"; + break; + case "m4a": + document.mime_type = "audio/m4a"; + break; case "ogg": document.mime_type = "audio/ogg"; break; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index bf985d757..1ad27e7a3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -68,6 +68,9 @@ public class Utilities { public static native void stackBlurBitmap(Bitmap bitmap, int radius); public static Bitmap blurWallpaper(Bitmap src) { + if (src == null) { + return null; + } Bitmap b; if (src.getHeight() > src.getWidth()) { b = Bitmap.createBitmap(Math.round(450f * src.getWidth() / src.getHeight()), 450, Bitmap.Config.ARGB_8888); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/time/FastDatePrinter.java b/TMessagesProj/src/main/java/org/telegram/messenger/time/FastDatePrinter.java index a73c5d962..db8faeaa5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/time/FastDatePrinter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/time/FastDatePrinter.java @@ -16,10 +16,12 @@ */ package org.telegram.messenger.time; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; + import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; -import java.lang.reflect.Method; import java.text.DateFormat; import java.text.DateFormatSymbols; import java.text.FieldPosition; @@ -167,49 +169,14 @@ public class FastDatePrinter implements DatePrinter, Serializable { * @throws IllegalArgumentException if pattern is invalid */ - private static boolean gotMethods; - private static Method getStandAloneMonthsMethod; - private static Method getShortStandAloneMonths; - protected List parsePattern() { - if (!gotMethods) { - try { - getStandAloneMonthsMethod = DateFormatSymbols.class.getDeclaredMethod("getStandAloneMonths"); - getStandAloneMonthsMethod.setAccessible(true); - - getShortStandAloneMonths = DateFormatSymbols.class.getDeclaredMethod("getShortStandAloneMonths"); - getShortStandAloneMonths.setAccessible(true); - } catch (Throwable ignore) { - - } - gotMethods = true; - } final DateFormatSymbols symbols = new DateFormatSymbols(mLocale); final List rules = new ArrayList(); final String[] ERAs = symbols.getEras(); final String[] months = symbols.getMonths(); - String[] standaloneMonths; - if (getStandAloneMonthsMethod != null) { - try { - standaloneMonths = (String[]) getStandAloneMonthsMethod.invoke(symbols); - } catch (Throwable ignore) { - standaloneMonths = months; - } - } else { - standaloneMonths = months; - } + final String[] shortMonths = symbols.getShortMonths(); - String[] shortStandaloneMonths; - if (getShortStandAloneMonths != null) { - try { - shortStandaloneMonths = (String[]) getShortStandAloneMonths.invoke(symbols); - } catch (Throwable ignore) { - shortStandaloneMonths = shortMonths; - } - } else { - shortStandaloneMonths = shortMonths; - } final String[] weekdays = symbols.getWeekdays(); final String[] shortWeekdays = symbols.getShortWeekdays(); final String[] AmPmStrings = symbols.getAmPmStrings(); @@ -243,9 +210,9 @@ public class FastDatePrinter implements DatePrinter, Serializable { break; case 'L': // month in year (text and number) if (tokenLen >= 4) { - rule = new TextField(Calendar.MONTH, standaloneMonths); + rule = new TextField(Calendar.MONTH, months); } else if (tokenLen == 3) { - rule = new TextField(Calendar.MONTH, shortStandaloneMonths); + rule = new TextField(Calendar.MONTH, shortMonths); } else if (tokenLen == 2) { rule = TwoDigitMonthField.INSTANCE; } else { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index fb1888934..411f532e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -89,13 +89,17 @@ public class ConnectionsManager { private static class ResolvedDomain { - public String address; + public ArrayList addresses; long ttl; - public ResolvedDomain(String a, long t) { - address = a; + public ResolvedDomain(ArrayList a, long t) { + addresses = a; ttl = t; } + + public String getAddress() { + return addresses.get(Utilities.random.nextInt(addresses.size())); + } } private static ThreadLocal> dnsCache = new ThreadLocal>() { @@ -438,7 +442,7 @@ public class ConnectionsManager { }); } - public static int getInitFlags() { + public static int getInitFlags() { return 0; } @@ -492,7 +496,7 @@ public class ConnectionsManager { HashMap cache = dnsCache.get(); ResolvedDomain resolvedDomain = cache.get(domain); if (resolvedDomain != null && SystemClock.elapsedRealtime() - resolvedDomain.ttl < 5 * 60 * 1000) { - return resolvedDomain.address; + return resolvedDomain.getAddress(); } ByteArrayOutputStream outbuf = null; @@ -525,10 +529,13 @@ public class ConnectionsManager { JSONArray array = jsonObject.getJSONArray("Answer"); int len = array.length(); if (len > 0) { - String ip = array.getJSONObject(Utilities.random.nextInt(array.length())).getString("data"); - ResolvedDomain newResolvedDomain = new ResolvedDomain(ip, SystemClock.elapsedRealtime()); + ArrayList addresses = new ArrayList<>(len); + for (int a = 0; a < len; a++) { + addresses.add(array.getJSONObject(a).getString("data")); + } + ResolvedDomain newResolvedDomain = new ResolvedDomain(addresses, SystemClock.elapsedRealtime()); cache.put(domain, newResolvedDomain); - return ip; + return newResolvedDomain.getAddress(); } } catch (Throwable e) { FileLog.e(e); @@ -741,7 +748,14 @@ public class ConnectionsManager { googleDomain = "google.com"; } String domain = native_isTestBackend(currentAccount) != 0 ? "tapv2.stel.com" : MessagesController.getInstance(currentAccount).dcDomainName; - URL downloadUrl = new URL("https://" + googleDomain + "/resolve?name=" + domain + "&type=16"); + int len = Utilities.random.nextInt(116) + 13; + final String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + StringBuilder padding = new StringBuilder(len); + for (int a = 0; a < len; a++) { + padding.append(characters.charAt(Utilities.random.nextInt(characters.length()))); + } + URL downloadUrl = new URL("https://" + googleDomain + "/resolve?name=" + domain + "&type=ANY&random_padding=" + padding); URLConnection httpConnection = downloadUrl.openConnection(); httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1"); httpConnection.addRequestProperty("Host", "dns.google.com"); @@ -769,10 +783,15 @@ public class ConnectionsManager { JSONObject jsonObject = new JSONObject(new String(outbuf.toByteArray(), "UTF-8")); JSONArray array = jsonObject.getJSONArray("Answer"); - int len = array.length(); + len = array.length(); ArrayList arrayList = new ArrayList<>(len); for (int a = 0; a < len; a++) { - arrayList.add(array.getJSONObject(a).getString("data")); + JSONObject object = array.getJSONObject(a); + int type = object.getInt("type"); + if (type != 16) { + continue; + } + arrayList.add(object.getString("data")); } Collections.sort(arrayList, (o1, o2) -> { int l1 = o1.length(); diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 49dc9afd0..931656302 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -59,7 +59,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_EDITED = 0x00008000; public static final int MESSAGE_FLAG_MEGAGROUP = 0x80000000; - public static final int LAYER = 94; + public static final int LAYER = 95; public static class TL_chatBannedRights extends TLObject { public static int constructor = 0x9f120418; @@ -13537,7 +13537,7 @@ public class TLRPC { public static int constructor = 0x702b65a9; public int hash; - public ArrayList wallpapers = new ArrayList<>(); + public ArrayList wallpapers = new ArrayList<>(); public void readParams(AbstractSerializedData stream, boolean exception) { hash = stream.readInt32(exception); @@ -13550,7 +13550,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_wallPaper object = TL_wallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); + WallPaper object = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -22613,6 +22613,54 @@ public class TLRPC { } } + public static class TL_wallPaperSettings extends TLObject { + public static int constructor = 0xa12f40b8; + + public int flags; + public boolean blur; + public boolean motion; + public int background_color; + public int intensity; + + public static TL_wallPaperSettings TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_wallPaperSettings.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_wallPaperSettings", constructor)); + } else { + return null; + } + } + TL_wallPaperSettings result = new TL_wallPaperSettings(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + blur = (flags & 2) != 0; + motion = (flags & 4) != 0; + if ((flags & 1) != 0) { + background_color = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + intensity = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = blur ? (flags | 2) : (flags &~ 2); + flags = motion ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(background_color); + } + if ((flags & 8) != 0) { + stream.writeInt32(intensity); + } + } + } + public static class TL_contacts_found extends TLObject { public static int constructor = 0xb3134d9d; @@ -26823,30 +26871,78 @@ public class TLRPC { public static int constructor = 0xe317af7e; } - public static class TL_wallPaper extends TLObject { - public static int constructor = 0xf04f91ec; + public static abstract class WallPaper extends TLObject { + + public static WallPaper TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + WallPaper result = null; + switch (constructor) { + case 0xa437c3ed: + result = new TL_wallPaper(); + break; + case 0xf04f91ec: + result = new TL_wallPaper_layer94(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in WallPaper", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_wallPaper extends WallPaper { + public static int constructor = 0xa437c3ed; public long id; public int flags; public boolean creator; public boolean isDefault; + public boolean pattern; + public boolean dark; public long access_hash; public String slug; public Document document; + public TL_wallPaperSettings settings; - public static TL_wallPaper TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_wallPaper.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_wallPaper", constructor)); - } else { - return null; - } + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + flags = stream.readInt32(exception); + creator = (flags & 1) != 0; + isDefault = (flags & 2) != 0; + pattern = (flags & 8) != 0; + dark = (flags & 16) != 0; + access_hash = stream.readInt64(exception); + slug = stream.readString(exception); + document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + settings = TL_wallPaperSettings.TLdeserialize(stream, stream.readInt32(exception), exception); } - TL_wallPaper result = new TL_wallPaper(); - result.readParams(stream, exception); - return result; } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + flags = creator ? (flags | 1) : (flags &~ 1); + flags = isDefault ? (flags | 2) : (flags &~ 2); + flags = pattern ? (flags | 8) : (flags &~ 8); + flags = dark ? (flags | 16) : (flags &~ 16); + stream.writeInt32(flags); + stream.writeInt64(access_hash); + stream.writeString(slug); + document.serializeToStream(stream); + if ((flags & 4) != 0) { + settings.serializeToStream(stream); + } + } + } + + public static class TL_wallPaper_layer94 extends TL_wallPaper { + public static int constructor = 0xf04f91ec; + + public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); flags = stream.readInt32(exception); @@ -30913,30 +31009,13 @@ public class TLRPC { } } - public static class TL_account_uploadWallPaper extends TLObject { - public static int constructor = 0xc7ba9b4d; - - public InputFile file; - public String mime_type; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_wallPaper.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - file.serializeToStream(stream); - stream.writeString(mime_type); - } - } - public static class TL_account_getWallPaper extends TLObject { public static int constructor = 0xfc8ddbea; public InputWallPaper wallpaper; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_wallPaper.TLdeserialize(stream, constructor, exception); + return WallPaper.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -30945,11 +31024,31 @@ public class TLRPC { } } + public static class TL_account_uploadWallPaper extends TLObject { + public static int constructor = 0xdd853661; + + public InputFile file; + public String mime_type; + public TL_wallPaperSettings settings; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return WallPaper.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + file.serializeToStream(stream); + stream.writeString(mime_type); + settings.serializeToStream(stream); + } + } + public static class TL_account_saveWallPaper extends TLObject { - public static int constructor = 0x189581b3; + public static int constructor = 0x6c5a5b37; public InputWallPaper wallpaper; public boolean unsave; + public TL_wallPaperSettings settings; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Bool.TLdeserialize(stream, constructor, exception); @@ -30959,13 +31058,15 @@ public class TLRPC { stream.writeInt32(constructor); wallpaper.serializeToStream(stream); stream.writeBool(unsave); + settings.serializeToStream(stream); } } public static class TL_account_installWallPaper extends TLObject { - public static int constructor = 0x4a0378ce; + public static int constructor = 0xfeed5769; public InputWallPaper wallpaper; + public TL_wallPaperSettings settings; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Bool.TLdeserialize(stream, constructor, exception); @@ -30974,6 +31075,20 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); wallpaper.serializeToStream(stream); + settings.serializeToStream(stream); + } + } + + public static class TL_account_resetWallPapers extends TLObject { + public static int constructor = 0xbb3b9804; + + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); } } @@ -34398,7 +34513,14 @@ public class TLRPC { protected void writeAttachPath(AbstractSerializedData stream) { if (this instanceof TL_message_secret || this instanceof TL_message_secret_layer72) { - stream.writeString(attachPath); + String path = attachPath != null ? attachPath : ""; + if (send_state == 1 && params != null && params.size() > 0) { + for (HashMap.Entry entry : params.entrySet()) { + path = entry.getKey() + "|=|" + entry.getValue() + "||" + path; + } + path = "||" + path; + } + stream.writeString(path); } else { String path = attachPath != null ? attachPath : ""; if ((id < 0 || send_state == 3) && params != null && params.size() > 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index 3202ff22c..7d9b3e056 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -171,6 +171,7 @@ public class ActionBarLayout extends FrameLayout { private float themeAnimationValue; private boolean animateThemeAfterAnimation; private Theme.ThemeInfo animateSetThemeAfterAnimation; + private boolean animateSetThemeNightAfterAnimation; private boolean rebuildAfterAnimation; private boolean rebuildLastAfterAnimation; private boolean showLastAfterAnimation; @@ -1287,10 +1288,11 @@ public class ActionBarLayout extends FrameLayout { return themeAnimationValue; } - public void animateThemedValues(Theme.ThemeInfo theme) { + public void animateThemedValues(Theme.ThemeInfo theme, boolean nightTheme) { if (transitionAnimationInProgress || startedTracking) { animateThemeAfterAnimation = true; animateSetThemeAfterAnimation = theme; + animateSetThemeNightAfterAnimation = nightTheme; return; } if (themeAnimatorSet != null) { @@ -1324,7 +1326,7 @@ public class ActionBarLayout extends FrameLayout { } } if (i == 0) { - Theme.applyTheme(theme, true); + Theme.applyTheme(theme, nightTheme); } animateEndColors[i] = new int[themeAnimatorDescriptions[i].length]; for (int a = 0; a < themeAnimatorDescriptions[i].length; a++) { @@ -1436,7 +1438,7 @@ public class ActionBarLayout extends FrameLayout { rebuildAllFragmentViews(rebuildLastAfterAnimation, showLastAfterAnimation); rebuildAfterAnimation = false; } else if (animateThemeAfterAnimation) { - animateThemedValues(animateSetThemeAfterAnimation); + animateThemedValues(animateSetThemeAfterAnimation, animateSetThemeNightAfterAnimation); animateSetThemeAfterAnimation = null; animateThemeAfterAnimation = false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java index 9cce7aed8..e45671347 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -928,7 +928,10 @@ public class AlertDialog extends Dialog implements Drawable.Callback { } public View getButton(int type) { - return buttonsLayout.findViewWithTag(type); + if (buttonsLayout != null) { + return buttonsLayout.findViewWithTag(type); + } + return null; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java index 1b913ff3d..db7383339 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java @@ -11,8 +11,12 @@ package org.telegram.ui.ActionBar; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.os.SystemClock; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.StaticLayout; @@ -36,12 +40,28 @@ public class SimpleTextView extends View implements Drawable.Callback { private int leftDrawableTopPadding; private int rightDrawableTopPadding; + private boolean scrollNonFitText; + private boolean textDoesNotFit; + private float scrollingOffset; + private long lastUpdateTime; + private int currentScrollDelay; + private GradientDrawable fadeDrawable; + private GradientDrawable fadeDrawableBack; + private int lastWidth; + private int offsetX; private int offsetY; private int textWidth; + private int totalWidth; private int textHeight; private boolean wasLayout; + private static final int PIXELS_PER_SECOND = 50; + private static final int PIXELS_PER_SECOND_SLOW = 30; + private static final int DIST_BETWEEN_SCROLLING_TEXT = 16; + private static final int SCROLL_DELAY_MS = 500; + private static final int SCROLL_SLOWDOWN_PX = 100; + public SimpleTextView(Context context) { super(context); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); @@ -74,6 +94,18 @@ public class SimpleTextView extends View implements Drawable.Callback { } } + public void setScrollNonFitText(boolean value) { + if (scrollNonFitText == value) { + return; + } + scrollNonFitText = value; + if (scrollNonFitText) { + fadeDrawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, new int[]{0xffffffff, 0}); + fadeDrawableBack = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, new int[]{0, 0xffffffff}); + } + requestLayout(); + } + public void setGravity(int value) { gravity = value; } @@ -116,6 +148,7 @@ public class SimpleTextView extends View implements Drawable.Callback { offsetX = -AndroidUtilities.dp(8); } offsetX += getPaddingLeft(); + textDoesNotFit = textWidth > width; } } @@ -130,12 +163,17 @@ public class SimpleTextView extends View implements Drawable.Callback { width -= rightDrawable.getIntrinsicWidth(); width -= drawablePadding; } - CharSequence string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END); + CharSequence string; + if (scrollNonFitText) { + string = text; + } else { + string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END); + } /*if (layout != null && TextUtils.equals(layout.getText(), string)) { calcOffset(width); return false; }*/ - layout = new StaticLayout(string, 0, string.length(), textPaint, width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); calcOffset(width); } catch (Exception ignore) { @@ -153,6 +191,11 @@ public class SimpleTextView extends View implements Drawable.Callback { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); + if (lastWidth != AndroidUtilities.displaySize.x) { + lastWidth = AndroidUtilities.displaySize.x; + scrollingOffset = 0; + currentScrollDelay = SCROLL_DELAY_MS; + } createLayout(width - getPaddingLeft() - getPaddingRight()); int finalHeight; @@ -234,6 +277,8 @@ public class SimpleTextView extends View implements Drawable.Callback { return false; } text = value; + scrollingOffset = 0; + currentScrollDelay = SCROLL_DELAY_MS; recreateLayoutMaybe(); return true; } @@ -291,32 +336,120 @@ public class SimpleTextView extends View implements Drawable.Callback { @Override protected void onDraw(Canvas canvas) { int textOffsetX = 0; + totalWidth = textWidth; if (leftDrawable != null) { + int x = (int) -scrollingOffset; int y = (textHeight - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding; - leftDrawable.setBounds(0, y, leftDrawable.getIntrinsicWidth(), y + leftDrawable.getIntrinsicHeight()); + leftDrawable.setBounds(x, y, x + leftDrawable.getIntrinsicWidth(), y + leftDrawable.getIntrinsicHeight()); leftDrawable.draw(canvas); if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) { textOffsetX += drawablePadding + leftDrawable.getIntrinsicWidth(); } + totalWidth += drawablePadding + leftDrawable.getIntrinsicWidth(); } if (rightDrawable != null) { - int x = textOffsetX + textWidth + drawablePadding; + int x = textOffsetX + textWidth + drawablePadding + (int) -scrollingOffset; int y = (textHeight - rightDrawable.getIntrinsicHeight()) / 2 + rightDrawableTopPadding; rightDrawable.setBounds(x, y, x + rightDrawable.getIntrinsicWidth(), y + rightDrawable.getIntrinsicHeight()); rightDrawable.draw(canvas); + totalWidth += drawablePadding + rightDrawable.getIntrinsicWidth(); } + int nextScrollX = totalWidth + AndroidUtilities.dp(DIST_BETWEEN_SCROLLING_TEXT); + + if (scrollingOffset != 0) { + if (leftDrawable != null) { + int x = (int) -scrollingOffset + nextScrollX; + int y = (textHeight - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding; + leftDrawable.setBounds(x, y, x + leftDrawable.getIntrinsicWidth(), y + leftDrawable.getIntrinsicHeight()); + leftDrawable.draw(canvas); + } + if (rightDrawable != null) { + int x = textOffsetX + textWidth + drawablePadding + (int) -scrollingOffset + nextScrollX; + int y = (textHeight - rightDrawable.getIntrinsicHeight()) / 2 + rightDrawableTopPadding; + rightDrawable.setBounds(x, y, x + rightDrawable.getIntrinsicWidth(), y + rightDrawable.getIntrinsicHeight()); + rightDrawable.draw(canvas); + } + } + if (layout != null) { - if (offsetX + textOffsetX != 0 || offsetY != 0) { + if (offsetX + textOffsetX != 0 || offsetY != 0 || scrollingOffset != 0) { canvas.save(); - canvas.translate(offsetX + textOffsetX, offsetY); + canvas.translate(offsetX + textOffsetX - scrollingOffset, offsetY); + if (scrollingOffset != 0) { + //canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); + } } layout.draw(canvas); - if (offsetX + textOffsetX != 0 || offsetY != 0) { + if (scrollingOffset != 0) { + canvas.translate(nextScrollX, 0); + layout.draw(canvas); + } + if (offsetX + textOffsetX != 0 || offsetY != 0 || scrollingOffset != 0) { canvas.restore(); } + if (scrollNonFitText && textDoesNotFit) { + if (scrollingOffset < AndroidUtilities.dp(10)) { + fadeDrawable.setAlpha((int) (255 * (scrollingOffset / AndroidUtilities.dp(10)))); + } else if (scrollingOffset > totalWidth + AndroidUtilities.dp(DIST_BETWEEN_SCROLLING_TEXT) - AndroidUtilities.dp(10)) { + float dist = scrollingOffset - (totalWidth + AndroidUtilities.dp(DIST_BETWEEN_SCROLLING_TEXT) - AndroidUtilities.dp(10)); + fadeDrawable.setAlpha((int) (255 * (1.0f - dist / AndroidUtilities.dp(10)))); + } else { + fadeDrawable.setAlpha(255); + } + fadeDrawable.setBounds(0, 0, AndroidUtilities.dp(6), getMeasuredHeight()); + fadeDrawable.draw(canvas); + + fadeDrawableBack.setBounds(getMeasuredWidth() - AndroidUtilities.dp(6), 0, getMeasuredWidth(), getMeasuredHeight()); + fadeDrawableBack.draw(canvas); + } + updateScrollAnimation(); } } + @Override + public void setBackgroundColor(int color) { + if (scrollNonFitText) { + if (fadeDrawable != null) { + fadeDrawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + fadeDrawableBack.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + } + } else { + super.setBackgroundColor(color); + } + } + + private void updateScrollAnimation() { + if (!scrollNonFitText || !textDoesNotFit) { + return; + } + long newUpdateTime = SystemClock.uptimeMillis(); + long dt = newUpdateTime - lastUpdateTime; + if (dt > 17) { + dt = 17; + } + if (currentScrollDelay > 0) { + currentScrollDelay -= dt; + } else { + int totalDistance = totalWidth + AndroidUtilities.dp(DIST_BETWEEN_SCROLLING_TEXT); + float pixelsPerSecond; + if (scrollingOffset < AndroidUtilities.dp(SCROLL_SLOWDOWN_PX)) { + pixelsPerSecond = PIXELS_PER_SECOND_SLOW + (PIXELS_PER_SECOND - PIXELS_PER_SECOND_SLOW) * (scrollingOffset / AndroidUtilities.dp(SCROLL_SLOWDOWN_PX)); + } else if (scrollingOffset >= totalDistance - AndroidUtilities.dp(SCROLL_SLOWDOWN_PX)) { + float dist = scrollingOffset - (totalDistance - AndroidUtilities.dp(SCROLL_SLOWDOWN_PX)); + pixelsPerSecond = PIXELS_PER_SECOND - (PIXELS_PER_SECOND - PIXELS_PER_SECOND_SLOW) * (dist / AndroidUtilities.dp(SCROLL_SLOWDOWN_PX)); + } else { + pixelsPerSecond = PIXELS_PER_SECOND; + } + scrollingOffset += dt / 1000.0f * AndroidUtilities.dp(pixelsPerSecond); + lastUpdateTime = newUpdateTime; + if (scrollingOffset > totalDistance) { + scrollingOffset = 0; + currentScrollDelay = SCROLL_DELAY_MS; + } + } + invalidate(); + } + @Override public void invalidateDrawable(Drawable who) { if (who == leftDrawable) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index 83c1128d1..bd50a3b2d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -105,6 +105,10 @@ public class Theme { return name; } + public boolean isDark() { + return "Dark".equals(name) || "Dark Blue".equals(name); + } + public static ThemeInfo createWithJson(JSONObject object) { if (object == null) { return null; @@ -302,6 +306,7 @@ public class Theme { private static Drawable themedWallpaper; private static int themedWallpaperFileOffset; private static boolean isWallpaperMotion; + private static boolean isPatternWallpaper; public static Paint dividerPaint; public static Paint linkSelectionPaint; @@ -1563,9 +1568,9 @@ public class Theme { defaultColors.put(key_player_actionBarItems, 0xff8a8a8a); defaultColors.put(key_player_background, 0xffffffff); defaultColors.put(key_player_time, 0xff8c9296); - defaultColors.put(key_player_progressBackground, 0x19000000); - defaultColors.put(key_player_progressCachedBackground, 0x19000000); - defaultColors.put(key_player_progress, 0xff23afef); + defaultColors.put(key_player_progressBackground, 0xffe9eff5); + defaultColors.put(key_player_progressCachedBackground, 0xffe9eff5); + defaultColors.put(key_player_progress, 0xff4b9fe3); defaultColors.put(key_player_placeholder, 0xffa8a8a8); defaultColors.put(key_player_placeholderBackground, 0xfff0f0f0); defaultColors.put(key_player_button, 0xff333333); @@ -2268,8 +2273,8 @@ public class Theme { applyTheme(themeInfo, true, true, false); } - public static void applyTheme(ThemeInfo themeInfo, boolean animated) { - applyTheme(themeInfo, true, true, animated); + public static void applyTheme(ThemeInfo themeInfo, boolean nightTheme) { + applyTheme(themeInfo, true, true, nightTheme); } public static void applyTheme(ThemeInfo themeInfo, boolean save, boolean removeWallpaperOverride, final boolean nightTheme) { @@ -2547,12 +2552,12 @@ public class Theme { if (night) { if (currentTheme != currentNightTheme) { lastThemeSwitchTime = SystemClock.elapsedRealtime(); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentNightTheme); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentNightTheme, true); } } else { if (currentTheme != currentDayTheme) { lastThemeSwitchTime = SystemClock.elapsedRealtime(); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentDayTheme); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentDayTheme, true); } } } @@ -3698,6 +3703,7 @@ public class Theme { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); boolean overrideTheme = preferences.getBoolean("overrideThemeWallpaper", false); isWallpaperMotion = preferences.getBoolean("selectedBackgroundMotion", false); + isPatternWallpaper = preferences.getLong("selectedPattern", 0) != 0; if (!overrideTheme) { Integer backgroundColor = currentColors.get(key_chat_wallpaper); if (backgroundColor != null) { @@ -3737,13 +3743,17 @@ public class Theme { int selectedColor = 0; try { long selectedBackground = getSelectedBackgroundId(); + long selectedPattern = preferences.getLong("selectedPattern", 0); selectedColor = preferences.getInt("selectedColor", 0); - if (selectedColor == 0) { - if (selectedBackground == DEFAULT_BACKGROUND_ID) { - wallpaper = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.background_hd); - isCustomTheme = false; + if (selectedBackground == DEFAULT_BACKGROUND_ID) { + wallpaper = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.background_hd); + isCustomTheme = false; + } else if (selectedBackground == -1 || selectedBackground < -100 || selectedBackground > 0) { + if (selectedColor != 0 && selectedPattern == 0) { + wallpaper = new ColorDrawable(selectedColor); } else { File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"); + long len = toFile.length(); if (toFile.exists()) { wallpaper = Drawable.createFromPath(toFile.getAbsolutePath()); isCustomTheme = true; @@ -3849,7 +3859,19 @@ public class Theme { } } + public static Drawable getCachedWallpaperNonBlocking() { + if (themedWallpaper != null) { + return themedWallpaper; + } else { + return wallpaper; + } + } + public static boolean isWallpaperMotion() { return isWallpaperMotion; } + + public static boolean isPatternWallpaper() { + return isPatternWallpaper; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index 2070a717f..92ce33f70 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -104,6 +104,10 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { return MessagesController.getInstance(currentAccount).dialogsGroupsOnly; } else if (dialogsType == 3) { return MessagesController.getInstance(currentAccount).dialogsForward; + } else if (dialogsType == 4) { + return MessagesController.getInstance(currentAccount).dialogsUsersOnly; + } else if (dialogsType == 5) { + return MessagesController.getInstance(currentAccount).dialogsChannelsOnly; } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index 98b599a0c..dbc2d0a1f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -1031,6 +1031,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { }); view = horizontalListView; innerListView = horizontalListView; + break; } if (viewType == 5) { view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(86))); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java index 0af3abcba..abe78b4f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -178,7 +178,7 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement a--; } } - lastSticker = emoji.toString().trim(); + lastSticker = emoji.toString();/*.trim();*/ if (!Emoji.isValidEmoji(originalEmoji) && !Emoji.isValidEmoji(lastSticker)) { if (visible) { visible = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 2563caa55..1a14c7f32 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -486,7 +486,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg circleSize = AndroidUtilities.dp(5); gapSize = AndroidUtilities.dp(2); sideSide = AndroidUtilities.dp(17); - lineSize = (getMeasuredWidth() - circleSize * fontSizeCount - gapSize * 8 - sideSide * 2) / (fontSizeCount - 1); + lineSize = (getMeasuredWidth() - circleSize * fontSizeCount - gapSize * 2 * (fontSizeCount - 1) - sideSide * 2) / (fontSizeCount - 1); } @Override @@ -1481,6 +1481,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg pageSwitchAnimation.playTogether(ObjectAnimator.ofFloat(listView[0], View.TRANSLATION_X, AndroidUtilities.dp(56), 0), ObjectAnimator.ofFloat(listView[0], View.ALPHA, 0.0f, 1.0f)); } else if (order == -1) { + listView[0].setAlpha(1.0f); + listView[0].setTranslationX(0.0f); pageSwitchAnimation.playTogether(ObjectAnimator.ofFloat(listView[1], View.TRANSLATION_X, 0, AndroidUtilities.dp(56)), ObjectAnimator.ofFloat(listView[1], View.ALPHA, 1.0f, 0.0f)); } @@ -2401,9 +2403,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg int end = spanned.getSpanEnd(innerSpans[a]); textPath.setCurrentLayout(result, start, 0); int shift = innerSpans[a].getTextPaint() != null ? innerSpans[a].getTextPaint().baselineShift : 0; - if (shift != 0) { - markPath.setBaselineShift(shift + AndroidUtilities.dp(shift > 0 ? 5 : -2)); - } + textPath.setBaselineShift(shift != 0 ? shift + AndroidUtilities.dp(shift > 0 ? 5 : -2) : 0); result.getSelectionPath(start, end, textPath); } textPath.setAllowReset(true); @@ -2421,9 +2421,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg int end = spanned.getSpanEnd(innerSpans[a]); markPath.setCurrentLayout(result, start, 0); int shift = innerSpans[a].getTextPaint() != null ? innerSpans[a].getTextPaint().baselineShift : 0; - if (shift != 0) { - markPath.setBaselineShift(shift + AndroidUtilities.dp(shift > 0 ? 5 : -2)); - } + markPath.setBaselineShift(shift != 0 ? shift + AndroidUtilities.dp(shift > 0 ? 5 : -2) : 0); result.getSelectionPath(start, end, markPath); } markPath.setAllowReset(true); @@ -3906,6 +3904,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg containerView.setTranslationX(0); containerView.setTranslationY(0); listView[0].setTranslationY(0); + listView[0].setTranslationX(0.0f); + listView[1].setTranslationX(0.0f); listView[0].setAlpha(1.0f); windowView.setInnerTranslationX(0); @@ -5711,6 +5711,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } else { imageView.setImage(null, null, thumb, "80_80_b", 0, null, currentPage, 1); } + imageView.setAspectFit(isGif); buttonX = (int) (imageView.getImageX() + (imageView.getImageWidth() - size) / 2.0f); buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f); radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); @@ -5751,8 +5752,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (currentBlock == null) { return; } - if (!imageView.hasBitmapImage() || imageView.getcurrentAccount() != 1.0f) { - canvas.drawRect(imageView.getImageX(), imageView.getImageY(), imageView.getImageX2(), imageView.getImageY2(), photoBackgroundPaint); + if (!imageView.hasBitmapImage() || imageView.getCurrentAlpha() != 1.0f) { + canvas.drawRect(imageView.getDrawRegion(), photoBackgroundPaint); } imageView.draw(canvas); if (imageView.getVisible()) { @@ -9186,7 +9187,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (currentBlock == null) { return; } - if (!imageView.hasBitmapImage() || imageView.getcurrentAccount() != 1.0f) { + if (!imageView.hasBitmapImage() || imageView.getCurrentAlpha() != 1.0f) { canvas.drawRect(imageView.getImageX(), imageView.getImageY(), imageView.getImageX2(), imageView.getImageY2(), photoBackgroundPaint); } imageView.draw(canvas); @@ -11071,14 +11072,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg size[0] = -1; } TLRPC.PhotoSize thumbLocation = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 80); - imageReceiver.setImage(fileLocation, null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, thumbLocation, "b", size[0], null, currentPage, 1); + imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, thumbLocation, "b", size[0], null, currentPage, 1); } else if (isMediaVideo(index)) { if (!(fileLocation.location instanceof TLRPC.TL_fileLocationUnavailable)) { ImageReceiver.BitmapHolder placeHolder = null; if (currentThumb != null && imageReceiver == centerImage) { placeHolder = currentThumb; } - imageReceiver.setImage(null, null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, fileLocation, "b", 0, null, currentPage, 1); + imageReceiver.setImage(null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, fileLocation, "b", 0, null, currentPage, 1); } else { imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder)); } @@ -11191,7 +11192,12 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg xPos += ((WindowInsets) lastInsets).getSystemWindowInsetLeft(); } float yPos = ((AndroidUtilities.displaySize.y + AndroidUtilities.statusBarHeight) - height) / 2.0f; - int clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + int clipHorizontal; + if (object.imageReceiver.isAspectFit()) { + clipHorizontal = 0; + } else { + clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + } int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); int coords2[] = new int[2]; @@ -11358,7 +11364,12 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (object != null) { object.imageReceiver.setVisible(false, true); - int clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + int clipHorizontal; + if (object.imageReceiver.isAspectFit()) { + clipHorizontal = 0; + } else { + clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + } int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); int coords2[] = new int[2]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java index 1b40e5e7b..a08bd4370 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java @@ -120,9 +120,16 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + radialProgress.onDetachedFromWindow(); DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + radialProgress.onAttachedToWindow(); + } + public MessageObject getMessageObject() { return currentMessageObject; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index 18a80695d..3c377780b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -36,11 +36,20 @@ import org.telegram.ui.Components.AvatarDrawable; public class ChatActionCell extends BaseCell { public interface ChatActionCellDelegate { - void didClickedImage(ChatActionCell cell); - void didLongPressed(ChatActionCell cell); - void needOpenUserProfile(int uid); - void didPressedBotButton(MessageObject messageObject, TLRPC.KeyboardButton button); - void didPressedReplyMessage(ChatActionCell cell, int id); + default void didClickedImage(ChatActionCell cell) { + } + + default void didLongPressed(ChatActionCell cell) { + } + + default void needOpenUserProfile(int uid) { + } + + default void didPressedBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { + } + + default void didPressedReplyMessage(ChatActionCell cell, int id) { + } } private URLSpan pressedLink; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 9654db915..daa0c573d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -16,12 +16,15 @@ import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; +import android.net.Uri; import android.os.Build; import android.text.Layout; import android.text.Spannable; @@ -91,23 +94,59 @@ import java.util.Locale; public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate, ImageReceiver.ImageReceiverDelegate, DownloadController.FileDownloadProgressListener { public interface ChatMessageCellDelegate { - void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user); - void didPressViaBot(ChatMessageCell cell, String username); - void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId); - void didPressCancelSendButton(ChatMessageCell cell); - void didLongPress(ChatMessageCell cell); - void didPressReplyMessage(ChatMessageCell cell, int id); - void didPressUrl(MessageObject messageObject, CharacterStyle url, boolean longPress); - void needOpenWebView(String url, String title, String description, String originalUrl, int w, int h); - void didPressImage(ChatMessageCell cell); - void didPressShare(ChatMessageCell cell); - void didPressOther(ChatMessageCell cell); - void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button); - void didPressVoteButton(ChatMessageCell cell, TLRPC.TL_pollAnswer button); - void didPressInstantButton(ChatMessageCell cell, int type); - boolean isChatAdminCell(int uid); - boolean needPlayMessage(MessageObject messageObject); - boolean canPerformActions(); + default void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user) { + } + + default void didPressViaBot(ChatMessageCell cell, String username) { + } + + default void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId) { + } + + default void didPressCancelSendButton(ChatMessageCell cell) { + } + + default void didLongPress(ChatMessageCell cell) { + } + + default void didPressReplyMessage(ChatMessageCell cell, int id) { + } + + default void didPressUrl(MessageObject messageObject, CharacterStyle url, boolean longPress) { + } + + default void needOpenWebView(String url, String title, String description, String originalUrl, int w, int h) { + } + + default void didPressImage(ChatMessageCell cell) { + } + + default void didPressShare(ChatMessageCell cell) { + } + + default void didPressOther(ChatMessageCell cell) { + } + + default void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { + } + + default void didPressVoteButton(ChatMessageCell cell, TLRPC.TL_pollAnswer button) { + } + + default void didPressInstantButton(ChatMessageCell cell, int type) { + } + + default boolean isChatAdminCell(int uid) { + return false; + } + + default boolean needPlayMessage(MessageObject messageObject) { + return false; + } + + default boolean canPerformActions() { + return false; + } } private final static int DOCUMENT_ATTACH_TYPE_NONE = 0; @@ -210,6 +249,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private StaticLayout instantViewLayout; private boolean drawInstantView; private int drawInstantViewType; + private int imageBackgroundColor; + private int imageBackgroundSideColor; + private int imageBackgroundSideWidth; private boolean drawJoinGroupView; private boolean drawJoinChannelView; private int instantTextX; @@ -244,6 +286,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private WebFile currentWebFile; private boolean addedForTest; + private boolean hasEmbed; + + private boolean checkOnlyButtonPressed; private int buttonX; private int buttonY; private int buttonState; @@ -824,7 +869,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate miniButtonPressed = 1; invalidate(); return true; - } else if (drawPhotoImage && drawImageButton && buttonState != -1 && (photoImage.isInsideImage(x, y) || x >= buttonX && x <= buttonX + AndroidUtilities.dp(48) && y >= buttonY && y <= buttonY + AndroidUtilities.dp(48))) { + } else if (drawPhotoImage && drawImageButton && buttonState != -1 && (!checkOnlyButtonPressed && photoImage.isInsideImage(x, y) || x >= buttonX && x <= buttonX + AndroidUtilities.dp(48) && y >= buttonY && y <= buttonY + AndroidUtilities.dp(48))) { buttonPressed = 1; return true; } else if (drawInstantView) { @@ -1825,6 +1870,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate protected void onDetachedFromWindow() { super.onDetachedFromWindow(); attachedToWindow = false; + radialProgress.onDetachedFromWindow(); avatarImage.onDetachedFromWindow(); replyImageReceiver.onDetachedFromWindow(); locationImageReceiver.onDetachedFromWindow(); @@ -1841,6 +1887,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate super.onAttachedToWindow(); attachedToWindow = true; setTranslationX(0); + radialProgress.onAttachedToWindow(); avatarImage.onAttachedToWindow(); avatarImage.setParentView((View) getParent()); replyImageReceiver.onAttachedToWindow(); @@ -2132,7 +2179,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setShouldGenerateQualityThumb(true); } currentPhotoFilter = "86_86_b"; - photoImage.setImage(currentPhotoObject, null, "86_86", null, currentPhotoObjectThumb, currentPhotoFilter, 0, null, messageObject, 1); + photoImage.setImage(currentPhotoObject, "86_86", null, currentPhotoObjectThumb, currentPhotoFilter, 0, null, messageObject, 1); } return width; } @@ -2316,7 +2363,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawShareButton = checkNeedDrawShareButton(messageObject); replyNameLayout = null; adminLayout = null; + checkOnlyButtonPressed = false; replyTextLayout = null; + hasEmbed = false; replyNameWidth = 0; replyTextWidth = 0; viaWidth = 0; @@ -2386,7 +2435,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawInstantView = false; drawInstantViewType = 0; drawForwardedName = false; + imageBackgroundColor = 0; + imageBackgroundSideColor = 0; mediaBackground = false; + photoImage.setAlpha(1.0f); if (messageChanged || dataChanged) { pollButtons.clear(); } @@ -2397,6 +2449,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setShouldGenerateQualityThumb(false); photoImage.setAllowDecodeSingleFrame(false); photoImage.setRoundRadius(AndroidUtilities.dp(3)); + photoImage.setColorFilter(null); if (messageChanged) { firstVisibleBlockNum = 0; @@ -2439,6 +2492,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate hasInvoicePreview = messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice; hasLinkPreview = messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPage; drawInstantView = hasLinkPreview && messageObject.messageOwner.media.webpage.cached_page != null; + hasEmbed = hasLinkPreview && !TextUtils.isEmpty(messageObject.messageOwner.media.webpage.embed_url); boolean slideshow = false; String siteName = hasLinkPreview ? messageObject.messageOwner.media.webpage.site_name : null; String webpageType = hasLinkPreview ? messageObject.messageOwner.media.webpage.type : null; @@ -2455,6 +2509,29 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if ("telegram_background".equals(webpageType)) { drawInstantView = true; drawInstantViewType = 6; + try { + Uri url = Uri.parse(messageObject.messageOwner.media.webpage.url); + int intensity = Utilities.parseInt(url.getQueryParameter("intensity")); + String bgColor = url.getQueryParameter("bg_color"); + if (bgColor != null) { + imageBackgroundColor = Integer.parseInt(url.getQueryParameter("bg_color"), 16) | 0xff000000; + imageBackgroundSideColor = AndroidUtilities.getPatternSideColor(imageBackgroundColor); + photoImage.setColorFilter(new PorterDuffColorFilter(AndroidUtilities.getPatternColor(imageBackgroundColor), PorterDuff.Mode.SRC_IN)); + photoImage.setAlpha(intensity / 100.0f); + } else { + String color = url.getLastPathSegment(); + if (color != null && color.length() == 6) { + imageBackgroundColor = Integer.parseInt(color, 16) | 0xff000000; + currentPhotoObject = new TLRPC.TL_photoSizeEmpty(); + currentPhotoObject.type = "s"; + currentPhotoObject.w = AndroidUtilities.dp(180); + currentPhotoObject.h = AndroidUtilities.dp(150); + currentPhotoObject.location = new TLRPC.TL_fileLocationUnavailable(); + } + } + } catch (Exception ignore) { + + } } /*else if ("telegram_proxy".equals(webpageType)) { drawInstantView = true; drawInstantViewType = 4; @@ -2544,9 +2621,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasLinkPreview) { TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) messageObject.messageOwner.media.webpage; site_name = webPage.site_name; - title = webPage.title; - author = webPage.author; - description = webPage.description; + title = drawInstantViewType != 6 ? webPage.title : null; + author = drawInstantViewType != 6 ? webPage.author : null; + description = drawInstantViewType != 6 ? webPage.description : null; photo = webPage.photo; webDocument = null; document = webPage.document; @@ -2914,8 +2991,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } else if (photo != null) { - drawImageButton = type != null && type.equals("photo"); - currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, drawImageButton ? AndroidUtilities.getPhotoSize() : maxPhotoWidth, !drawImageButton); + boolean isPhoto = type != null && type.equals("photo"); + currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, isPhoto || !smallImage ? AndroidUtilities.getPhotoSize() : maxPhotoWidth, !isPhoto); + checkOnlyButtonPressed = !isPhoto; currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); if (currentPhotoObjectThumb == currentPhotoObject) { currentPhotoObjectThumb = null; @@ -2929,13 +3007,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType != DOCUMENT_ATTACH_TYPE_MUSIC && documentAttachType != DOCUMENT_ATTACH_TYPE_AUDIO && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { if (currentPhotoObject != null || webDocument != null) { - drawImageButton = type != null && (type.equals("photo") || type.equals("document") && documentAttachType != DOCUMENT_ATTACH_TYPE_STICKER || type.equals("gif") || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER); + drawImageButton = photo != null && !smallImage || type != null && (type.equals("photo") || type.equals("document") && documentAttachType != DOCUMENT_ATTACH_TYPE_STICKER || type.equals("gif") || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER); if (linkPreviewHeight != 0) { linkPreviewHeight += AndroidUtilities.dp(2); totalHeight += AndroidUtilities.dp(2); } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { + if (imageBackgroundSideColor != 0) { + maxPhotoWidth = AndroidUtilities.dp(208); + } else if (currentPhotoObject instanceof TLRPC.TL_photoSizeEmpty && currentPhotoObject.w != 0) { + maxPhotoWidth = currentPhotoObject.w; + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { if (AndroidUtilities.isTablet()) { maxPhotoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.5f); } else { @@ -2955,6 +3037,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { webDocument.size = -1; } + if (imageBackgroundSideColor != 0) { + imageBackgroundSideWidth = maxChildWidth - AndroidUtilities.dp(13); + } int width; int height; @@ -2982,6 +3067,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate height = AndroidUtilities.displaySize.y / 2; } } + if (imageBackgroundSideColor != 0) { + scale = height / (float) AndroidUtilities.dp(160); + width /= scale; + height /= scale; + } } } if (isSmallImage) { @@ -2995,7 +3085,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkPreviewHeight += height; } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER && imageBackgroundSideColor == 0) { photoImage.setImageCoords(0, 0, Math.max(maxChildWidth - AndroidUtilities.dp(13), width), height); } else { photoImage.setImageCoords(0, 0, width, height); @@ -3005,12 +3095,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhotoFilterThumb = String.format(Locale.US, "%d_%d_b", width, height); if (webDocument != null) { - photoImage.setImage(webDocument, null, currentPhotoFilter, null, null, "b1", webDocument.size, null, messageObject, 1); + photoImage.setImage(webDocument, currentPhotoFilter, null, null, "b1", webDocument.size, null, messageObject, 1); } else { if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { - photoImage.setImage(null, null, currentPhotoFilter, null, currentPhotoObject, "b1", 0, "jpg", messageObject, 1); + if (messageObject.mediaExists) { + photoImage.setImage(documentAttach, currentPhotoFilter, null, currentPhotoObject, "b1", 0, "jpg", messageObject, 1); + } else { + photoImage.setImage(null, currentPhotoFilter, null, currentPhotoObject, "b1", 0, "jpg", messageObject, 1); + } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) { - photoImage.setImage(documentAttach, null, currentPhotoFilter, null, currentPhotoObject, "b1", documentAttach.size, "webp", messageObject, 1); + photoImage.setImage(documentAttach, currentPhotoFilter, null, currentPhotoObject, "b1", documentAttach.size, "webp", messageObject, 1); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { photoImage.setNeedsQualityThumb(true); photoImage.setShouldGenerateQualityThumb(true); @@ -3660,19 +3754,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoHeight = (int) maxHeight; } documentAttachType = DOCUMENT_ATTACH_TYPE_STICKER; - availableTimeWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(14); + availableTimeWidth = photoWidth - AndroidUtilities.dp(14); backgroundWidth = photoWidth + AndroidUtilities.dp(12); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); if (messageObject.attachPathExists) { - photoImage.setImage(null, messageObject.messageOwner.attachPath, + photoImage.setImage(messageObject.messageOwner.attachPath, String.format(Locale.US, "%d_%d", photoWidth, photoHeight), null, currentPhotoObjectThumb, "b1", messageObject.messageOwner.media.document.size, "webp", messageObject, 1); } else if (messageObject.messageOwner.media.document.id != 0) { - photoImage.setImage(messageObject.messageOwner.media.document, null, + photoImage.setImage(messageObject.messageOwner.media.document, String.format(Locale.US, "%d_%d", photoWidth, photoHeight), null, currentPhotoObjectThumb, @@ -3753,6 +3847,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } + if (currentPhotoObject != null && "s".equals(currentPhotoObject.type)) { + currentPhotoObject = null; + } if (currentPhotoObject != null && currentPhotoObject == currentPhotoObjectThumb) { if (messageObject.type == 1) { @@ -4077,7 +4174,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (!messageObject.isSending() && !messageObject.isEditing() && (localFile != 0 || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) { if (localFile == 1) { - photoImage.setImage(null, messageObject.isSendError() ? null : messageObject.messageOwner.attachPath, null, null, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, messageObject, 0); + photoImage.setImage(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath, null, null, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, messageObject, 0); } else { photoImage.setImage(messageObject.messageOwner.media.document, null, currentPhotoObjectThumb, currentPhotoFilterThumb, messageObject.messageOwner.media.document.size, null, messageObject, 0); } @@ -4414,7 +4511,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate str = LocaleController.getString("InstantView", R.string.InstantView); } int mWidth = backgroundWidth - AndroidUtilities.dp(10 + 24 + 10 + 31); - instantViewLayout = new StaticLayout(TextUtils.ellipsize(str, Theme.chat_instantViewPaint, mWidth, TextUtils.TruncateAt.END), Theme.chat_instantViewPaint, mWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + instantViewLayout = new StaticLayout(TextUtils.ellipsize(str, Theme.chat_instantViewPaint, mWidth, TextUtils.TruncateAt.END), Theme.chat_instantViewPaint, mWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); instantWidth = backgroundWidth - AndroidUtilities.dp(34); totalHeight += AndroidUtilities.dp(46); if (currentMessageObject.type == 12) { @@ -4843,18 +4940,37 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkPreviewY += currentMessageObject.textHeight + AndroidUtilities.dp(4); } - if (drawPhotoImage && drawInstantView) { + if (drawPhotoImage && drawInstantView || drawInstantViewType == 6 && imageBackgroundColor != 0) { if (linkPreviewY != startY) { linkPreviewY += AndroidUtilities.dp(2); } - photoImage.setImageCoords(linkX + AndroidUtilities.dp(10), linkPreviewY, photoImage.getImageWidth(), photoImage.getImageHeight()); - if (drawImageButton) { - int size = AndroidUtilities.dp(48); - buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); - buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); - radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); + if (imageBackgroundSideColor != 0) { + int x = linkX + AndroidUtilities.dp(10); + photoImage.setImageCoords(x + (imageBackgroundSideWidth - photoImage.getImageWidth()) / 2, linkPreviewY, photoImage.getImageWidth(), photoImage.getImageHeight()); + rect.set(x, photoImage.getImageY(), x + imageBackgroundSideWidth, photoImage.getImageY2()); + Theme.chat_instantViewPaint.setColor(imageBackgroundSideColor); + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_instantViewPaint); + } else { + photoImage.setImageCoords(linkX + AndroidUtilities.dp(10), linkPreviewY, photoImage.getImageWidth(), photoImage.getImageHeight()); + } + if (imageBackgroundColor != 0) { + Theme.chat_instantViewPaint.setColor(imageBackgroundColor); + rect.set(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2()); + if (imageBackgroundSideColor != 0) { + canvas.drawRect(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2(), Theme.chat_instantViewPaint); + } else { + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_instantViewPaint); + } + } + if (drawPhotoImage && drawInstantView) { + if (drawImageButton) { + int size = AndroidUtilities.dp(48); + buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); + buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); + radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); + } + imageDrawn = photoImage.draw(canvas); } - imageDrawn = photoImage.draw(canvas); linkPreviewY += photoImage.getImageHeight() + AndroidUtilities.dp(6); } @@ -4949,7 +5065,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.restore(); Theme.chat_durationPaint.setAlpha(255); } - if (videoInfoLayout != null && (!drawPhotoImage || photoImage.getVisible())) { + if (videoInfoLayout != null && (!drawPhotoImage || photoImage.getVisible()) && imageBackgroundSideColor == 0) { int x; int y; if (hasGamePreview || hasInvoicePreview || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { @@ -5825,6 +5941,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { return MediaActionDrawable.ICON_FIRE; } + } else if (hasEmbed) { + return MediaActionDrawable.ICON_PLAY; } } } @@ -6002,7 +6120,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { if (!cancelLoading && (documentAttachType == 0 && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) || - documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.isNewGifDocument(documentAttach) && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject))) { + documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.isNewGifDocument(documentAttach) && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject))) { buttonState = 1; } else { buttonState = 0; @@ -6209,7 +6327,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.messageOwner.media.webpage.document, currentMessageObject, 0, 0); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { - FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.messageOwner.media.webpage.document, currentMessageObject, 0, 1); + photoImage.setImage(documentAttach, currentPhotoFilter, null, currentPhotoObject, "b1", 0, "jpg", currentMessageObject, 1); } } else { photoImage.setForceLoading(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java index 0fc1394b1..6308d5b84 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java @@ -276,13 +276,13 @@ public class ContextLinkCell extends View implements DownloadController.FileDown if (documentAttach != null) { linkImageView.setImage(documentAttach, null, currentPhotoObject, currentPhotoFilter, documentAttach.size, ext, parentObject, 0); } else { - linkImageView.setImage(webFile, urlLocation, null, null, currentPhotoObject, currentPhotoFilter, -1, ext, parentObject, 1); + linkImageView.setImage(webFile != null ? webFile : urlLocation, null, null, currentPhotoObject, currentPhotoFilter, -1, ext, parentObject, 1); } } else { if (currentPhotoObject != null) { linkImageView.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, currentPhotoObject.size, ext, parentObject, 0); } else { - linkImageView.setImage(webFile, urlLocation, currentPhotoFilter, null, currentPhotoObjectThumb, currentPhotoFilterThumb, -1, ext, parentObject, 1); + linkImageView.setImage(webFile != null ? webFile : urlLocation, currentPhotoFilter, null, currentPhotoObjectThumb, currentPhotoFilterThumb, -1, ext, parentObject, 1); } } drawLinkImageView = true; @@ -449,6 +449,7 @@ public class ContextLinkCell extends View implements DownloadController.FileDown if (drawLinkImageView) { linkImageView.onDetachedFromWindow(); } + radialProgress.onDetachedFromWindow(); DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); } @@ -460,6 +461,7 @@ public class ContextLinkCell extends View implements DownloadController.FileDown updateButtonState(false, false); } } + radialProgress.onAttachedToWindow(); } public MessageObject getMessageObject() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index d04c44d65..81dc4bd58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -910,6 +910,10 @@ public class DialogCell extends BaseCell { return MessagesController.getInstance(currentAccount).dialogsGroupsOnly; } else if (dialogsType == 3) { return MessagesController.getInstance(currentAccount).dialogsForward; + } else if (dialogsType == 4) { + return MessagesController.getInstance(currentAccount).dialogsUsersOnly; + } else if (dialogsType == 5) { + return MessagesController.getInstance(currentAccount).dialogsChannelsOnly; } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index 5ba025cb4..788a17cd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -120,7 +120,7 @@ public class DrawerProfileCell extends FrameLayout { shadowView.getDrawable().setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); } nameTextView.setTextColor(Theme.getColor(Theme.key_chats_menuName)); - if (Theme.isCustomTheme() && backgroundDrawable != null) { + if (Theme.isCustomTheme() && !Theme.isPatternWallpaper() && backgroundDrawable != null) { phoneTextView.setTextColor(Theme.getColor(Theme.key_chats_menuPhone)); shadowView.setVisibility(VISIBLE); if (backgroundDrawable instanceof ColorDrawable) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java index 0403db5db..3d10656b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java @@ -101,7 +101,7 @@ public class PaymentInfoCell extends FrameLayout { detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 33, LocaleController.isRTL ? 123 : 10, 0)); detailExTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 90, LocaleController.isRTL ? 123 : 10, 0)); imageView.setVisibility(VISIBLE); - imageView.getImageReceiver().setImage(WebFile.createWithWebDocument(invoice.photo), null, String.format(Locale.US, "%d_%d", width, height), null, null, null, -1, null, invoice, 1); + imageView.getImageReceiver().setImage(WebFile.createWithWebDocument(invoice.photo), String.format(Locale.US, "%d_%d", width, height), null, null, null, -1, null, invoice, 1); } else { nameTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 9, 17, 0)); detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 33, 17, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java index 0a1680d7a..8386af1e7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java @@ -175,7 +175,7 @@ public class SharedPhotoVideoCell extends FrameLayout { TLRPC.Document document = messageObject.getDocument(); TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if (thumb != null) { - imageView.setImage(null, null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, thumb, "b", null, 0, messageObject); + imageView.setImage(null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, thumb, "b", null, 0, messageObject); } else { imageView.setImageResource(R.drawable.photo_placeholder_in); } @@ -189,7 +189,7 @@ public class SharedPhotoVideoCell extends FrameLayout { } imageView.getImageReceiver().setImage(currentPhotoObject, "100_100", currentPhotoObjectThumb, "b", currentPhotoObject.size, null, messageObject, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); } else { - imageView.setImage(null, null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, currentPhotoObjectThumb, "b", null, 0, messageObject); + imageView.setImage(null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, currentPhotoObjectThumb, "b", null, 0, messageObject); } } else { videoInfoContainer.setVisibility(INVISIBLE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java index 630024399..6cee4bcd5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -35,6 +35,7 @@ import org.telegram.ui.Components.CheckBox; import org.telegram.ui.Components.CheckBoxSquare; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.NotificationsSettingsActivity; public class UserCell extends FrameLayout { @@ -48,6 +49,7 @@ public class UserCell extends FrameLayout { private AvatarDrawable avatarDrawable; private TLObject currentObject; + private TLRPC.EncryptedChat encryptedChat; private CharSequence currentName; private CharSequence currrntStatus; @@ -154,10 +156,14 @@ public class UserCell extends FrameLayout { } public void setData(TLObject object, CharSequence name, CharSequence status, int resId) { - setData(object, name, status, resId, false); + setData(object, null, name, status, resId, false); } public void setData(TLObject object, CharSequence name, CharSequence status, int resId, boolean divider) { + setData(object, null, name, status, resId, divider); + } + + public void setData(TLObject object, TLRPC.EncryptedChat ec, CharSequence name, CharSequence status, int resId, boolean divider) { if (object == null && name == null && status == null) { currrntStatus = null; currentName = null; @@ -167,6 +173,7 @@ public class UserCell extends FrameLayout { avatarImageView.setImageDrawable(null); return; } + encryptedChat = ec; currrntStatus = status; currentName = name; currentObject = object; @@ -176,6 +183,74 @@ public class UserCell extends FrameLayout { update(0); } + public void setException(NotificationsSettingsActivity.NotificationException exception, CharSequence name, boolean divider) { + String text; + boolean enabled; + boolean custom = exception.hasCustom; + int value = exception.notify; + int delta = exception.muteUntil; + if (value == 3 && delta != Integer.MAX_VALUE) { + delta -= ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + if (delta <= 0) { + if (custom) { + text = LocaleController.getString("NotificationsCustom", R.string.NotificationsCustom); + } else { + text = LocaleController.getString("NotificationsUnmuted", R.string.NotificationsUnmuted); + } + } else if (delta < 60 * 60) { + text = LocaleController.formatString("WillUnmuteIn", R.string.WillUnmuteIn, LocaleController.formatPluralString("Minutes", delta / 60)); + } else if (delta < 60 * 60 * 24) { + text = LocaleController.formatString("WillUnmuteIn", R.string.WillUnmuteIn, LocaleController.formatPluralString("Hours", (int) Math.ceil(delta / 60.0f / 60))); + } else if (delta < 60 * 60 * 24 * 365) { + text = LocaleController.formatString("WillUnmuteIn", R.string.WillUnmuteIn, LocaleController.formatPluralString("Days", (int) Math.ceil(delta / 60.0f / 60 / 24))); + } else { + text = null; + } + } else { + if (value == 0) { + enabled = true; + } else if (value == 1) { + enabled = true; + } else if (value == 2) { + enabled = false; + } else { + enabled = false; + } + if (enabled && custom) { + text = LocaleController.getString("NotificationsCustom", R.string.NotificationsCustom); + } else { + text = enabled ? LocaleController.getString("NotificationsUnmuted", R.string.NotificationsUnmuted) : LocaleController.getString("NotificationsMuted", R.string.NotificationsMuted); + } + } + if (text == null) { + text = LocaleController.getString("NotificationsOff", R.string.NotificationsOff); + } + + int lower_id = (int) exception.did; + int high_id = (int) (exception.did >> 32); + if (lower_id != 0) { + if (lower_id > 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id); + if (user != null) { + setData(user, null, name, text, 0, divider); + } + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); + if (chat != null) { + setData(chat, null, name, text, 0, divider); + } + } + } else { + TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); + if (encryptedChat != null) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); + if (user != null) { + setData(user, encryptedChat, name, text, 0, false); + } + } + } + } + public void setNameTypeface(Typeface typeface) { nameTextView.setTypeface(typeface); } @@ -232,6 +307,18 @@ public class UserCell extends FrameLayout { if (currentUser.photo != null) { photo = currentUser.photo.photo_small; } + /*if (encryptedChat != null) { + drawNameLock = true; + dialog_id = ((long) encryptedChat.id) << 32; + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); + nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - Theme.dialogs_lockDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(11); + } + nameLockTop = AndroidUtilities.dp(16.5f); + }*/ } else if (currentObject instanceof TLRPC.Chat) { currentChat = (TLRPC.Chat) currentObject; if (currentChat.photo != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java index 4af3fe7c3..8a69569db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java @@ -15,6 +15,8 @@ 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.view.Gravity; @@ -25,6 +27,7 @@ import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.MediaController; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -50,6 +53,7 @@ public class WallpaperCell extends FrameLayout { public WallpaperView(Context context) { super(context); + setWillNotDraw(false); imageView = new BackupImageView(context) { @Override @@ -112,6 +116,9 @@ public class WallpaperCell extends FrameLayout { } else { imageView.setVisibility(VISIBLE); imageView2.setVisibility(INVISIBLE); + imageView.setBackgroundDrawable(null); + imageView.getImageReceiver().setColorFilter(null); + imageView.getImageReceiver().setAlpha(1.0f); if (object instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; isSelected = wallPaper.id == selectedBackground; @@ -121,23 +128,52 @@ public class WallpaperCell extends FrameLayout { image = null; } int size = image != null ? image.size : wallPaper.document.size; - imageView.setImage(image != null ? image : wallPaper.document, "100_100", thumb, "100_100_b", "jpg", size, 1, wallPaper); - imageView.setBackgroundColor(0x5a475866); + if (wallPaper.pattern) { + imageView.setBackgroundColor(0xff000000 | wallPaper.settings.background_color); + imageView.setImage(image, "100_100", thumb, null, "jpg", size, 1, wallPaper); + imageView.getImageReceiver().setColorFilter(new PorterDuffColorFilter(AndroidUtilities.getPatternColor(wallPaper.settings.background_color), PorterDuff.Mode.SRC_IN)); + imageView.getImageReceiver().setAlpha(wallPaper.settings.intensity / 100.0f); + } else { + /*if (wallPaper.settings != null && wallPaper.settings.blur) { + imageView.setImage(null, "100_100", thumb, "100_100_b", "jpg", size, 1, wallPaper); + } else {*/ + imageView.setImage(image != null ? image : wallPaper.document, "100_100", thumb, "100_100_b", "jpg", size, 1, wallPaper); + //} + } } else if (object instanceof WallpapersListActivity.ColorWallpaper) { WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) object; + if (wallPaper.path != null) { + imageView.setImage(wallPaper.path.getAbsolutePath(), "100_100", null); + } else { + imageView.setImageBitmap(null); + imageView.setBackgroundColor(0xff000000 | wallPaper.color); + } isSelected = wallPaper.id == selectedBackground; - imageView.setImageBitmap(null); - imageView.setBackgroundColor(0xff000000 | wallPaper.color); } else if (object instanceof WallpapersListActivity.FileWallpaper) { WallpapersListActivity.FileWallpaper wallPaper = (WallpapersListActivity.FileWallpaper) object; isSelected = wallPaper.id == selectedBackground; - if (wallPaper.path != null) { + if (wallPaper.originalPath != null) { + imageView.setImage(wallPaper.originalPath.getAbsolutePath(), "100_100", null); + } else if (wallPaper.path != null) { imageView.setImage(wallPaper.path.getAbsolutePath(), "100_100", null); } else if (wallPaper.resId == Theme.THEME_BACKGROUND_ID) { imageView.setImageDrawable(Theme.getThemedWallpaper(true)); } else { imageView.setImageResource(wallPaper.thumbResId); } + } else if (object instanceof MediaController.SearchImage) { + MediaController.SearchImage wallPaper = (MediaController.SearchImage) object; + if (wallPaper.photo != null) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, 100); + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, 320); + if (image == thumb) { + image = null; + } + int size = image != null ? image.size : 0; + imageView.setImage(image, "100_100", thumb, "100_100_b", "jpg", size, 1, wallPaper); + } else { + imageView.setImage(wallPaper.thumbUrl, "100_100", null); + } } else { isSelected = false; } @@ -155,8 +191,8 @@ public class WallpaperCell extends FrameLayout { } if (animated) { animator = new AnimatorSet(); - animator.playTogether(ObjectAnimator.ofFloat(imageView, "scaleX", checked ? 0.85f : 1.0f), - ObjectAnimator.ofFloat(imageView, "scaleY", checked ? 0.85f : 1.0f)); + animator.playTogether(ObjectAnimator.ofFloat(imageView, "scaleX", checked ? 0.8875f : 1.0f), + ObjectAnimator.ofFloat(imageView, "scaleY", checked ? 0.8875f : 1.0f)); animator.setDuration(200); animator.addListener(new AnimatorListenerAdapter() { @Override @@ -178,9 +214,10 @@ public class WallpaperCell extends FrameLayout { }); animator.start(); } else { - imageView.setScaleX(checked ? 0.85f : 1.0f); - imageView.setScaleY(checked ? 0.85f : 1.0f); + imageView.setScaleX(checked ? 0.8875f : 1.0f); + imageView.setScaleY(checked ? 0.8875f : 1.0f); } + invalidate(); } @Override @@ -188,6 +225,22 @@ public class WallpaperCell extends FrameLayout { super.invalidate(); imageView.invalidate(); } + + @Override + public void clearAnimation() { + super.clearAnimation(); + if (animator != null) { + animator.cancel(); + animator = null; + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (checkBox.isChecked() || !imageView.getImageReceiver().hasBitmapImage() || imageView.getImageReceiver().getCurrentAlpha() != 1.0f) { + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); + } + } } private WallpaperView[] wallpaperViews; @@ -197,6 +250,7 @@ public class WallpaperCell extends FrameLayout { private int currentType; private Paint framePaint; private Paint circlePaint; + private Paint backgroundPaint; private Drawable checkDrawable; public WallpaperCell(Context context) { @@ -205,12 +259,10 @@ public class WallpaperCell extends FrameLayout { wallpaperViews = new WallpaperView[5]; for (int a = 0; a < wallpaperViews.length; a++) { WallpaperView wallpaperView = wallpaperViews[a] = new WallpaperView(context); + int num = a; addView(wallpaperView); - wallpaperView.setOnClickListener(v -> onWallpaperClick(wallpaperView.currentWallpaper)); - wallpaperView.setOnLongClickListener(v -> { - onWallpaperLongClick(wallpaperView.currentWallpaper); - return true; - }); + wallpaperView.setOnClickListener(v -> onWallpaperClick(wallpaperView.currentWallpaper, num)); + wallpaperView.setOnLongClickListener(v -> onWallpaperLongClick(wallpaperView.currentWallpaper, num)); } framePaint = new Paint(); @@ -219,14 +271,17 @@ public class WallpaperCell extends FrameLayout { circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); checkDrawable = context.getResources().getDrawable(R.drawable.background_selected).mutate(); + + backgroundPaint = new Paint(); + backgroundPaint.setColor(Theme.getColor(Theme.key_sharedMedia_photoPlaceholder)); } - protected void onWallpaperClick(Object wallPaper) { + protected void onWallpaperClick(Object wallPaper, int index) { } - protected void onWallpaperLongClick(Object wallPaper) { - + protected boolean onWallpaperLongClick(Object wallPaper, int index) { + return false; } @Override @@ -260,6 +315,7 @@ public class WallpaperCell extends FrameLayout { isBottom = bottom; for (int a = 0; a < wallpaperViews.length; a++) { wallpaperViews[a].setVisibility(a < columns ? VISIBLE : GONE); + wallpaperViews[a].clearAnimation(); } } @@ -267,6 +323,7 @@ public class WallpaperCell extends FrameLayout { currentType = type; if (wallpaper == null) { wallpaperViews[index].setVisibility(GONE); + wallpaperViews[index].clearAnimation(); } else { wallpaperViews[index].setVisibility(VISIBLE); wallpaperViews[index].setWallpaper(wallpaper, selectedBackground, themedWallpaper, themed); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index e51aa9961..7302df7ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -8512,6 +8512,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not obj.messageOwner.id = newMsgId; obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; obj.forceUpdate = mediaUpdated; + if (args.length >= 6) { + obj.applyMediaExistanceFlags((Integer) args[5]); + } addToPolls(obj, null); ArrayList messArr = new ArrayList<>(); messArr.add(obj); @@ -8982,7 +8985,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (message.media.ttl_seconds != 0 && (message.media.photo instanceof TLRPC.TL_photoEmpty || message.media.document instanceof TLRPC.TL_documentEmpty)) { existMessageObject.setType(); - chatAdapter.updateRowWithMessageObject(existMessageObject, false); + if (chatAdapter != null) { + chatAdapter.updateRowWithMessageObject(existMessageObject, false); + } } else { updateVisibleRows(); } @@ -10377,6 +10382,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatLeaveTime = System.currentTimeMillis(); updateInformationForScreenshotDetector(); } + if (undoView != null) { + undoView.hide(true, false); + } } private void applyDraftMaybe(boolean canClear) { @@ -10736,7 +10744,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (msg.messageOwner.action != null) { continue; } - if ((msg.isOut() || canRevokeInbox) || ChatObject.canBlockUsers(currentChat)) { + if ((msg.isOut() || canRevokeInbox) || currentChat != null && ChatObject.canBlockUsers(currentChat)) { if (!hasOutgoing && (currentDate - msg.messageOwner.date) <= revokeTimeLimit) { hasOutgoing = true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index ab2f22cdb..6b11fa25d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -852,7 +852,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image chatId = param; currentChat = MessagesController.getInstance(currentAccount).getChat(param); donePressed = false; - info.hidden_prehistory = true; + if (info != null) { + info.hidden_prehistory = true; + } processDone(); }); return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatSettingsActivity.java deleted file mode 100644 index 181cd7f9c..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatSettingsActivity.java +++ /dev/null @@ -1,519 +0,0 @@ -/* - * 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; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Build; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.DataQuery; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MessagesController; -import org.telegram.messenger.R; -import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; -import org.telegram.ui.ActionBar.ActionBar; -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.ActionBar.ThemeDescription; -import org.telegram.ui.Cells.CheckBoxCell; -import org.telegram.ui.Cells.EmptyCell; -import org.telegram.ui.Cells.HeaderCell; -import org.telegram.ui.Cells.NotificationsCheckCell; -import org.telegram.ui.Cells.ShadowSectionCell; -import org.telegram.ui.Cells.TextCheckCell; -import org.telegram.ui.Cells.TextDetailSettingsCell; -import org.telegram.ui.Cells.TextSettingsCell; -import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.NumberPicker; -import org.telegram.ui.Components.RecyclerListView; - -public class ChatSettingsActivity extends BaseFragment { - - private RecyclerListView listView; - private ListAdapter listAdapter; - - private int rowCount; - private int appearanceRow; - private int nightModeRow; - private int themeRow; - private int backgroundRow; - private int textSizeRow; - private int appearance2Row; - private int settingsRow; - private int customTabsRow; - private int directShareRow; - private int raiseToSpeakRow; - private int sendByEnterRow; - private int autoplayGifsRow; - private int saveToGalleryRow; - private int enableAnimationsRow; - private int settings2Row; - private int stickersRow; - private int stickersSection2Row; - - private int emojiRow; - private int contactsReimportRow; - private int contactsSortRow; - - @Override - public boolean onFragmentCreate() { - super.onFragmentCreate(); - - emojiRow = -1; - contactsReimportRow = -1; - contactsSortRow = -1; - - rowCount = 0; - appearanceRow = rowCount++; - nightModeRow = rowCount++; - themeRow = rowCount++; - backgroundRow = rowCount++; - textSizeRow = rowCount++; - appearance2Row = rowCount++; - settingsRow = rowCount++; - customTabsRow = rowCount++; - directShareRow = rowCount++; - enableAnimationsRow = rowCount++; - raiseToSpeakRow = rowCount++; - sendByEnterRow = rowCount++; - autoplayGifsRow = rowCount++; - saveToGalleryRow = rowCount++; - settings2Row = rowCount++; - stickersRow = rowCount++; - stickersSection2Row = rowCount++; - - return true; - } - - @Override - public View createView(Context context) { - actionBar.setBackButtonImage(R.drawable.ic_ab_back); - actionBar.setTitle(LocaleController.getString("ChatSettings", R.string.ChatSettings)); - - if (AndroidUtilities.isTablet()) { - actionBar.setOccupyStatusBar(false); - } - actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { - @Override - public void onItemClick(int id) { - if (id == -1) { - finishFragment(); - } - } - }); - - listAdapter = new ListAdapter(context); - - fragmentView = new FrameLayout(context); - fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); - FrameLayout frameLayout = (FrameLayout) fragmentView; - - listView = new RecyclerListView(context); - listView.setVerticalScrollBarEnabled(false); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { - @Override - public boolean supportsPredictiveItemAnimations() { - return false; - } - }); - listView.setGlowColor(Theme.getColor(Theme.key_avatar_backgroundActionBarBlue)); - listView.setAdapter(listAdapter); - listView.setItemAnimator(null); - listView.setLayoutAnimation(null); - frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); - listView.setOnItemClickListener((view, position, x, y) -> { - if (position == textSizeRow) { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("TextSize", R.string.TextSize)); - final NumberPicker numberPicker = new NumberPicker(getParentActivity()); - numberPicker.setMinValue(12); - numberPicker.setMaxValue(30); - numberPicker.setValue(SharedConfig.fontSize); - builder.setView(numberPicker); - builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), (dialog, which) -> { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("fons_size", numberPicker.getValue()); - SharedConfig.fontSize = numberPicker.getValue(); - editor.commit(); - if (listAdapter != null) { - listAdapter.notifyItemChanged(position); - } - }); - showDialog(builder.create()); - } else if (position == enableAnimationsRow) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - boolean animations = preferences.getBoolean("view_animations", true); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("view_animations", !animations); - editor.commit(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!animations); - } - } else if (position == backgroundRow) { - presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL)); - } else if (position == sendByEnterRow) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - boolean send = preferences.getBoolean("send_by_enter", false); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("send_by_enter", !send); - editor.commit(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!send); - } - } else if (position == raiseToSpeakRow) { - SharedConfig.toogleRaiseToSpeak(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(SharedConfig.raiseToSpeak); - } - } else if (position == autoplayGifsRow) { - SharedConfig.toggleAutoplayGifs(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(SharedConfig.autoplayGifs); - } - } else if (position == saveToGalleryRow) { - SharedConfig.toggleSaveToGallery(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(SharedConfig.saveToGallery); - } - } else if (position == customTabsRow) { - SharedConfig.toggleCustomTabs(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(SharedConfig.customTabs); - } - } else if(position == directShareRow) { - SharedConfig.toggleDirectShare(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(SharedConfig.directShare); - } - } else if (position == themeRow) { - presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC)); - } else if (position == contactsReimportRow) { - //not implemented - } else if (position == contactsSortRow) { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("SortBy", R.string.SortBy)); - builder.setItems(new CharSequence[]{ - LocaleController.getString("Default", R.string.Default), - LocaleController.getString("SortFirstName", R.string.SortFirstName), - LocaleController.getString("SortLastName", R.string.SortLastName) - }, (dialog, which) -> { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("sortContactsBy", which); - editor.commit(); - if (listAdapter != null) { - listAdapter.notifyItemChanged(position); - } - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); - } else if (position == stickersRow) { - presentFragment(new StickersActivity(DataQuery.TYPE_IMAGE)); - } else if (position == emojiRow) { - if (getParentActivity() == null) { - return; - } - final boolean maskValues[] = new boolean[2]; - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); - - builder.setApplyTopPadding(false); - builder.setApplyBottomPadding(false); - LinearLayout linearLayout = new LinearLayout(getParentActivity()); - linearLayout.setOrientation(LinearLayout.VERTICAL); - for (int a = 0; a < (Build.VERSION.SDK_INT >= 19 ? 2 : 1); a++) { - String name = null; - if (a == 0) { - maskValues[a] = SharedConfig.allowBigEmoji; - name = LocaleController.getString("EmojiBigSize", R.string.EmojiBigSize); - } else if (a == 1) { - maskValues[a] = SharedConfig.useSystemEmoji; - name = LocaleController.getString("EmojiUseDefault", R.string.EmojiUseDefault); - } - CheckBoxCell checkBoxCell = new CheckBoxCell(getParentActivity(), 1, 21); - checkBoxCell.setTag(a); - checkBoxCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - linearLayout.addView(checkBoxCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); - checkBoxCell.setText(name, "", maskValues[a], true); - checkBoxCell.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - checkBoxCell.setOnClickListener(v -> { - CheckBoxCell cell = (CheckBoxCell) v; - int num = (Integer) cell.getTag(); - maskValues[num] = !maskValues[num]; - cell.setChecked(maskValues[num], true); - }); - } - BottomSheet.BottomSheetCell cell = new BottomSheet.BottomSheetCell(getParentActivity(), 1); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - cell.setTextAndIcon(LocaleController.getString("Save", R.string.Save).toUpperCase(), 0); - cell.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); - cell.setOnClickListener(v -> { - try { - if (visibleDialog != null) { - visibleDialog.dismiss(); - } - } catch (Exception e) { - FileLog.e(e); - } - SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); - editor.putBoolean("allowBigEmoji", SharedConfig.allowBigEmoji = maskValues[0]); - editor.putBoolean("useSystemEmoji", SharedConfig.useSystemEmoji = maskValues[1]); - editor.commit(); - if (listAdapter != null) { - listAdapter.notifyItemChanged(position); - } - }); - linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); - builder.setCustomView(linearLayout); - showDialog(builder.create()); - } else if (position == nightModeRow) { - if (LocaleController.isRTL && x <= AndroidUtilities.dp(76) || !LocaleController.isRTL && x >= view.getMeasuredWidth() - AndroidUtilities.dp(76)) { - NotificationsCheckCell checkCell = (NotificationsCheckCell) view; - if (Theme.selectedAutoNightType == Theme.AUTO_NIGHT_TYPE_NONE) { - Theme.selectedAutoNightType = Theme.AUTO_NIGHT_TYPE_AUTOMATIC; - checkCell.setChecked(true); - } else { - Theme.selectedAutoNightType = Theme.AUTO_NIGHT_TYPE_NONE; - checkCell.setChecked(false); - } - Theme.saveAutoNightThemeConfig(); - Theme.checkAutoNightThemeConditions(); - boolean enabled = Theme.selectedAutoNightType != Theme.AUTO_NIGHT_TYPE_NONE; - String value = enabled ? Theme.getCurrentNightThemeName() : LocaleController.getString("NotificationsOff", R.string.NotificationsOff); - checkCell.setTextAndValueAndCheck(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), value, enabled, true); - } else { - presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT)); - } - } - }); - - return fragmentView; - } - - @Override - public void onResume() { - super.onResume(); - if (listAdapter != null) { - listAdapter.notifyDataSetChanged(); - } - } - - private class ListAdapter extends RecyclerListView.SelectionAdapter { - - private Context mContext; - - public ListAdapter(Context context) { - mContext = context; - } - - @Override - public int getItemCount() { - return rowCount; - } - - @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - switch (holder.getItemViewType()) { - case 2: { - TextSettingsCell textCell = (TextSettingsCell) holder.itemView; - if (position == textSizeRow) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - int size = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16); - textCell.setTextAndValue(LocaleController.getString("TextSize", R.string.TextSize), String.format("%d", size), false); - } else if (position == contactsSortRow) { - String value; - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - int sort = preferences.getInt("sortContactsBy", 0); - if (sort == 0) { - value = LocaleController.getString("Default", R.string.Default); - } else if (sort == 1) { - value = LocaleController.getString("FirstName", R.string.SortFirstName); - } else { - value = LocaleController.getString("LastName", R.string.SortLastName); - } - textCell.setTextAndValue(LocaleController.getString("SortBy", R.string.SortBy), value, true); - } else if (position == backgroundRow) { - textCell.setText(LocaleController.getString("ChatBackground", R.string.ChatBackground), true); - } else if (position == contactsReimportRow) { - textCell.setText(LocaleController.getString("ImportContacts", R.string.ImportContacts), true); - } else if (position == stickersRow) { - textCell.setText(LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), false); - } else if (position == emojiRow) { - textCell.setText(LocaleController.getString("Emoji", R.string.Emoji), true); - } - break; - } - case 3: { - TextCheckCell textCell = (TextCheckCell) holder.itemView; - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - if (position == enableAnimationsRow) { - textCell.setTextAndCheck(LocaleController.getString("EnableAnimations", R.string.EnableAnimations), preferences.getBoolean("view_animations", true), true); - } else if (position == sendByEnterRow) { - textCell.setTextAndCheck(LocaleController.getString("SendByEnter", R.string.SendByEnter), preferences.getBoolean("send_by_enter", false), true); - } else if (position == saveToGalleryRow) { - textCell.setTextAndCheck(LocaleController.getString("SaveToGallerySettings", R.string.SaveToGallerySettings), SharedConfig.saveToGallery, false); - } else if (position == autoplayGifsRow) { - textCell.setTextAndCheck(LocaleController.getString("AutoplayGifs", R.string.AutoplayGifs), SharedConfig.autoplayGifs, true); - } else if (position == raiseToSpeakRow) { - textCell.setTextAndCheck(LocaleController.getString("RaiseToSpeak", R.string.RaiseToSpeak), SharedConfig.raiseToSpeak, true); - } else if (position == customTabsRow) { - textCell.setTextAndValueAndCheck(LocaleController.getString("ChromeCustomTabs", R.string.ChromeCustomTabs), LocaleController.getString("ChromeCustomTabsInfo", R.string.ChromeCustomTabsInfo), SharedConfig.customTabs, false, true); - } else if (position == directShareRow) { - textCell.setTextAndValueAndCheck(LocaleController.getString("DirectShare", R.string.DirectShare), LocaleController.getString("DirectShareInfo", R.string.DirectShareInfo), SharedConfig.directShare, false, true); - } - break; - } - case 4: { - HeaderCell headerCell = (HeaderCell) holder.itemView; - if (position == settingsRow) { - headerCell.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS)); - } else if (position == appearanceRow) { - headerCell.setText(LocaleController.getString("Appearance", R.string.Appearance)); - } - break; - } - case 5: { - NotificationsCheckCell checkCell = (NotificationsCheckCell) holder.itemView; - if (position == nightModeRow) { - boolean enabled = Theme.selectedAutoNightType != Theme.AUTO_NIGHT_TYPE_NONE; - String value = enabled ? Theme.getCurrentNightThemeName() : LocaleController.getString("NotificationsOff", R.string.NotificationsOff); - checkCell.setTextAndValueAndCheck(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), value, enabled, true); - } - break; - } - case 6: { - TextDetailSettingsCell textCell = (TextDetailSettingsCell) holder.itemView; - if (position == themeRow) { - textCell.setTextAndValue(LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("ThemeInfo", R.string.ThemeInfo), true); - } - break; - } - } - } - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder) { - int position = holder.getAdapterPosition(); - return position == textSizeRow || position == enableAnimationsRow || position == backgroundRow || - position == sendByEnterRow || position == autoplayGifsRow || position == contactsSortRow || - position == contactsReimportRow || position == saveToGalleryRow || position == stickersRow || - position == raiseToSpeakRow || position == customTabsRow || position == directShareRow || - position == emojiRow || position == themeRow || position == nightModeRow; - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = null; - switch (viewType) { - case 1: - view = new ShadowSectionCell(mContext); - break; - case 2: - view = new TextSettingsCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - break; - case 3: - view = new TextCheckCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - break; - case 4: - view = new HeaderCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - break; - case 5: - view = new NotificationsCheckCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - break; - case 6: - view = new TextDetailSettingsCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - break; - } - view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); - return new RecyclerListView.Holder(view); - } - - @Override - public int getItemViewType(int position) { - if (position == stickersSection2Row || position == settings2Row || position == appearance2Row) { - return 1; - } else if (position == backgroundRow || position == contactsReimportRow || - position == textSizeRow || position == contactsSortRow || position == stickersRow || - position == emojiRow) { - return 2; - } else if (position == enableAnimationsRow || position == sendByEnterRow || position == saveToGalleryRow || - position == autoplayGifsRow || position == raiseToSpeakRow || position == customTabsRow || - position == directShareRow) { - return 3; - } else if (position == appearanceRow || position == settingsRow) { - return 4; - } else if (position == nightModeRow) { - return 5; - } - return 6; - } - } - - @Override - public ThemeDescription[] getThemeDescriptions() { - return new ThemeDescription[]{ - new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{EmptyCell.class, TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, TextDetailSettingsCell.class, NotificationsCheckCell.class}, null, null, null, Theme.key_windowBackgroundWhite), - new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), - - new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), - new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_avatar_actionBarIconBlue), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_avatar_actionBarSelectorBlue), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), - - new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), - - new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider), - - new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), - - new ThemeDescription(listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), - new ThemeDescription(listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteValueText), - - new ThemeDescription(listView, 0, new Class[]{NotificationsCheckCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), - new ThemeDescription(listView, 0, new Class[]{NotificationsCheckCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2), - new ThemeDescription(listView, 0, new Class[]{NotificationsCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrack), - new ThemeDescription(listView, 0, new Class[]{NotificationsCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrackChecked), - - new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), - new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2), - new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrack), - new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrackChecked), - - new ThemeDescription(listView, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader), - - new ThemeDescription(listView, 0, new Class[]{TextDetailSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), - new ThemeDescription(listView, 0, new Class[]{TextDetailSettingsCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2), - }; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index 970c154ac..f96e197da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -654,17 +654,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente removeUser(user_id); } } else { - if (type == TYPE_BANNED) { - createMenuForParticipant(listViewAdapter.getItem(position), false); - return; - } boolean canEdit = false; if (type == TYPE_ADMIN) { canEdit = user_id != UserConfig.getInstance(currentAccount).getClientUserId() && (currentChat.creator || canEditAdmin); } else if (type == TYPE_BANNED || type == TYPE_KICKED) { canEdit = ChatObject.canBlockUsers(currentChat); } - if (type != TYPE_ADMIN && isChannel || type == TYPE_USERS && selectType == 0) { + if (type == TYPE_BANNED || type != TYPE_ADMIN && isChannel || type == TYPE_USERS && selectType == 0) { Bundle args = new Bundle(); args.putInt("user_id", user_id); presentFragment(new ProfileActivity(args)); @@ -963,7 +959,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente return true; } items = new CharSequence[]{ - isChannel ? LocaleController.getString("ChannelAddToChannel", R.string.ChannelAddToChannel) : LocaleController.getString("ChannelAddToGroup", R.string.ChannelAddToGroup), + ChatObject.canAddUsers(currentChat) ? (isChannel ? LocaleController.getString("ChannelAddToChannel", R.string.ChannelAddToChannel) : LocaleController.getString("ChannelAddToGroup", R.string.ChannelAddToGroup)) : null, LocaleController.getString("ChannelDeleteFromList", R.string.ChannelDeleteFromList)}; icons = new int[]{ R.drawable.actions_addmember2, diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java index 15906b95a..f2029cbab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -32,7 +32,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; -import org.telegram.messenger.ContactsController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; @@ -674,9 +673,9 @@ public class AlertsCreator { if (clear) { if (user != null) { if (secret) { - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithSecretUser", R.string.AreYouSureClearHistoryWithSecretUser, ContactsController.formatName(user.first_name, user.last_name)))); + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithSecretUser", R.string.AreYouSureClearHistoryWithSecretUser, UserObject.getUserName(user)))); } else { - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithUser", R.string.AreYouSureClearHistoryWithUser, ContactsController.formatName(user.first_name, user.last_name)))); + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithUser", R.string.AreYouSureClearHistoryWithUser, UserObject.getUserName(user)))); } } else if (chat != null) { if (!ChatObject.isChannel(chat) || chat.megagroup && TextUtils.isEmpty(chat.username)) { @@ -690,9 +689,9 @@ public class AlertsCreator { } else { if (user != null) { if (secret) { - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithSecretUser", R.string.AreYouSureDeleteThisChatWithSecretUser, ContactsController.formatName(user.first_name, user.last_name)))); + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithSecretUser", R.string.AreYouSureDeleteThisChatWithSecretUser, UserObject.getUserName(user)))); } else { - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, ContactsController.formatName(user.first_name, user.last_name)))); + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, UserObject.getUserName(user)))); } } else if (ChatObject.isChannel(chat)) { if (chat.megagroup) { @@ -727,7 +726,9 @@ public class AlertsCreator { AlertDialog alertDialog = builder.create(); fragment.showDialog(alertDialog); TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); - button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } } public interface DatePickerDelegate { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index 496858a03..2d3ac6036 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -48,50 +48,54 @@ public class BackupImageView extends View { } public void setImage(SecureDocument path, String filter) { - setImage(path, null, filter, null, null, null, null, null, 0, null); + setImage(path, filter, null, null, null, null, null, 0, null); } public void setImage(TLObject path, String filter, String ext, Drawable thumb, Object parentObject) { - setImage(path, null, filter, thumb, null, null, null, ext, 0, parentObject); + setImage(path, filter, thumb, null, null, null, ext, 0, parentObject); } public void setImage(TLObject path, String filter, Drawable thumb, Object parentObject) { - setImage(path, null, filter, thumb, null, null, null, null, 0, parentObject); + setImage(path, filter, thumb, null, null, null, null, 0, parentObject); } public void setImage(TLObject path, String filter, Bitmap thumb, Object parentObject) { - setImage(path, null, filter, null, thumb, null, null, null, 0, parentObject); + setImage(path, filter, null, thumb, null, null, null, 0, parentObject); } public void setImage(TLObject path, String filter, Drawable thumb, int size, Object parentObject) { - setImage(path, null, filter, thumb, null, null, null, null, size, parentObject); + setImage(path, filter, thumb, null, null, null, null, size, parentObject); } public void setImage(TLObject path, String filter, Bitmap thumb, int size, Object parentObject) { - setImage(path, null, filter, null, thumb, null, null, null, size, parentObject); + setImage(path, filter, null, thumb, null, null, null, size, parentObject); } public void setImage(TLObject path, String filter, TLObject thumb, int size, Object parentObject) { - setImage(path, null, filter, null, null, thumb, null, null, size, parentObject); + setImage(path, filter, null, null, thumb, null, null, size, parentObject); } public void setImage(String path, String filter, Drawable thumb) { - setImage(null, path, filter, thumb, null, null, null, null, 0, null); + setImage(path, filter, thumb, null, null, null, null, 0, null); + } + + public void setImage(String path, String filter, String thumbPath, String thumbFilter) { + setImage(path, filter, null, null, thumbPath, thumbFilter, null, 0, null); } public void setOrientation(int angle, boolean center) { imageReceiver.setOrientation(angle, center); } - public void setImage(TLObject path, String httpUrl, String filter, Drawable thumb, Bitmap thumbBitmap, TLObject thumbLocation, String thumbFilter, String ext, int size, Object parentObject) { + public void setImage(Object path, String filter, Drawable thumb, Bitmap thumbBitmap, Object thumbLocation, String thumbFilter, String ext, int size, Object parentObject) { if (thumbBitmap != null) { thumb = new BitmapDrawable(null, thumbBitmap); } - imageReceiver.setImage(path, httpUrl, filter, thumb, thumbLocation, thumbFilter, size, ext, parentObject, 0); + imageReceiver.setImage(path, filter, thumb, thumbLocation, thumbFilter, size, ext, parentObject, 0); } public void setImage(TLObject path, String filter, TLObject thumbLocation, String thumbFilter, String ext, int size, int cacheType, Object parentObject) { - imageReceiver.setImage(path, null, filter, null, thumbLocation, thumbFilter, size, ext, parentObject, cacheType); + imageReceiver.setImage(path, filter, null, thumbLocation, thumbFilter, size, ext, parentObject, cacheType); } public void setImageBitmap(Bitmap bitmap) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index deb92c452..3545d14ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -405,6 +405,8 @@ public class EditTextBoldCursor extends EditText { if (supportRtlHint && LocaleController.isRTL) { canvas.translate((hintWidth + lineLeft) - (hintWidth + lineLeft) * scale, 0); + } else if (lineLeft != 0) { + canvas.translate(lineLeft * (1.0f - scale), 0); } canvas.scale(scale, scale); canvas.translate(0, translation); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java index c5c097ae6..71e3a6dbe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java @@ -107,7 +107,7 @@ public class GroupCreateSpan extends View { if (user != null && user.photo != null) { photo = user.photo.photo_small; } - imageReceiver.setImage(photo, null, "50_50", avatarDrawable, null, null, 0, null, user, 1); + imageReceiver.setImage(photo, "50_50", avatarDrawable, null, null, 0, null, user, 1); updateColors(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java index 37b93f20e..069854dd9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java @@ -335,7 +335,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes } else { parent = "avatar_" + delegate.getAvatarsDialogId(); } - receiver.setImage(null, null, null, null, location, "80_80", 0, null, parent, 1); + receiver.setImage(null, null, null, location, "80_80", 0, null, parent, 1); receiver.setParam(a); } else { break; @@ -357,7 +357,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes } else { parent = "avatar_" + delegate.getAvatarsDialogId(); } - receiver.setImage(null, null, null, null, location, "80_80", 0, null, parent, 1); + receiver.setImage(null, null, null, location, "80_80", 0, null, parent, 1); receiver.setParam(a); } else { break; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java index 7fcaa42b4..c2c259cad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java @@ -10,6 +10,7 @@ package org.telegram.ui.Components; import android.graphics.Path; import android.graphics.RectF; +import android.os.Build; import android.text.StaticLayout; import org.telegram.messenger.AndroidUtilities; @@ -24,6 +25,7 @@ public class LinkPath extends Path { private RectF rect; private boolean allowReset = true; private int baselineShift; + private int lineHeight; public LinkPath() { super(); @@ -39,6 +41,12 @@ public class LinkPath extends Path { currentLine = layout.getLineForOffset(start); lastTop = -1; heightOffset = yOffset; + if (Build.VERSION.SDK_INT >= 28) { + int lineCount = layout.getLineCount(); + if (lineCount > 0) { + lineHeight = layout.getLineBottom(lineCount - 1) - layout.getLineTop(lineCount - 1); + } + } } public void setAllowReset(boolean value) { @@ -79,7 +87,15 @@ public class LinkPath extends Path { left = lineLeft; } float y = top; - float y2 = bottom - (bottom != currentLayout.getHeight() ? currentLayout.getSpacingAdd() : 0); + float y2; + if (Build.VERSION.SDK_INT >= 28) { + y2 = bottom; + if (bottom - top > lineHeight) { + y2 -= (bottom != currentLayout.getHeight() ? currentLayout.getSpacingAdd() : 0); + } + } else { + y2 = bottom - (bottom != currentLayout.getHeight() ? currentLayout.getSpacingAdd() : 0); + } if (baselineShift < 0) { y2 += baselineShift; } else if (baselineShift > 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java index b17e5d0fa..eccae9398 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java @@ -60,6 +60,8 @@ public class MediaActionDrawable extends Drawable { private String percentString; private int percentStringWidth; + private float overrideAlpha = 1.0f; + private int currentIcon; private int nextIcon; private float transitionProgress = 1.0f; @@ -104,9 +106,11 @@ public class MediaActionDrawable extends Drawable { @Override public void setAlpha(int alpha) { - paint.setAlpha(alpha); - paint2.setAlpha(alpha); - textPaint.setAlpha(alpha); + + } + + public void setOverrideAlpha(float alpha) { + overrideAlpha = alpha; } @Override @@ -148,7 +152,7 @@ public class MediaActionDrawable extends Drawable { } if (icon == ICON_CANCEL) { transitionAnimationTime = 400.0f; - } else if (icon == ICON_CHECK) { + } else if (currentIcon != ICON_NONE && icon == ICON_CHECK) { transitionAnimationTime = 360.0f; } else { transitionAnimationTime = 220.0f; @@ -180,6 +184,10 @@ public class MediaActionDrawable extends Drawable { return nextIcon; } + public int getPreviousIcon() { + return currentIcon; + } + public void setProgress(float value, boolean animated) { if (!animated) { animatedDownloadProgress = value; @@ -235,6 +243,9 @@ public class MediaActionDrawable extends Drawable { float progress = 1.0f - transitionProgress; canvas.save(); canvas.scale(progress, progress, cx, cy); + } else if ((nextIcon == ICON_CHECK || nextIcon == ICON_EMPTY) && currentIcon == ICON_NONE) { + canvas.save(); + canvas.scale(transitionProgress, transitionProgress, cx, cy); } int width = AndroidUtilities.dp(3); @@ -399,9 +410,9 @@ public class MediaActionDrawable extends Drawable { rect.set(bounds.left + diff, bounds.top + diff, bounds.right - diff, bounds.bottom - diff); canvas.drawArc(rect, downloadRadOffset, rad, false, paint); } - } else if (currentIcon == ICON_EMPTY || currentIcon == ICON_CANCEL_PERCENT) { + } else if (currentIcon == ICON_EMPTY || nextIcon == ICON_EMPTY || currentIcon == ICON_CANCEL_PERCENT) { int alpha; - if (nextIcon == ICON_NONE) { + if (nextIcon == ICON_NONE || nextIcon == ICON_CHECK) { float progress = transitionProgress; float backProgress = 1.0f - progress; alpha = (int) (255 * backProgress); @@ -410,7 +421,7 @@ public class MediaActionDrawable extends Drawable { } if (alpha != 0) { - paint.setAlpha(alpha); + paint.setAlpha((int) (alpha * overrideAlpha)); float rad = Math.max(4, 360 * animatedDownloadProgress); int diff = AndroidUtilities.dp(isMini ? 2 : 4); rect.set(bounds.left + diff, bounds.top + diff, bounds.right - diff, bounds.bottom - diff); @@ -707,7 +718,7 @@ public class MediaActionDrawable extends Drawable { invalidateSelf(); } } - if (nextIcon == ICON_NONE) { + if (nextIcon == ICON_NONE || (nextIcon == ICON_CHECK || nextIcon == ICON_EMPTY) && currentIcon == ICON_NONE) { canvas.restore(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java index e1f7c6ec8..b181abfda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java @@ -217,7 +217,15 @@ public class RadialProgress2 { return; } - float wholeAlpha = mediaActionDrawable.getCurrentIcon() != MediaActionDrawable.ICON_NONE ? 1.0f : 1.0f - mediaActionDrawable.getTransitionProgress(); + int currentIcon = mediaActionDrawable.getCurrentIcon(); + int prevIcon = mediaActionDrawable.getPreviousIcon(); + + float wholeAlpha; + if ((currentIcon == MediaActionDrawable.ICON_CHECK || currentIcon == MediaActionDrawable.ICON_EMPTY) && prevIcon == MediaActionDrawable.ICON_NONE) { + wholeAlpha = mediaActionDrawable.getTransitionProgress(); + } else { + wholeAlpha = currentIcon != MediaActionDrawable.ICON_NONE ? 1.0f : 1.0f - mediaActionDrawable.getTransitionProgress(); + } if (isPressedMini) { if (iconPressedColorKey != null) { @@ -315,7 +323,7 @@ public class RadialProgress2 { if (drawMiniIcon && miniDrawCanvas != null) { miniDrawCanvas.drawCircle(centerX, centerY, circleRadius, circlePaint); } else { - if (mediaActionDrawable.getCurrentIcon() != MediaActionDrawable.ICON_NONE || wholeAlpha != 0) { + if (currentIcon != MediaActionDrawable.ICON_NONE || wholeAlpha != 0) { canvas.drawCircle(centerX, centerY, circleRadius * wholeAlpha, circlePaint); } } @@ -333,13 +341,13 @@ public class RadialProgress2 { } mediaActionDrawable.setBounds(centerX - circleRadius, centerY - circleRadius, centerX + circleRadius, centerY + circleRadius); if (drawMiniIcon) { - mediaActionDrawable.setAlpha((int) (255 * wholeAlpha * overrideAlpha)); if (miniDrawCanvas != null) { mediaActionDrawable.draw(miniDrawCanvas); } else { mediaActionDrawable.draw(canvas); } } else { + mediaActionDrawable.setOverrideAlpha(overrideAlpha); mediaActionDrawable.draw(canvas); } @@ -370,7 +378,6 @@ public class RadialProgress2 { miniDrawCanvas.drawCircle(AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(halfSize + 1) * alpha, Theme.checkboxSquare_eraserPaint); } else { miniProgressBackgroundPaint.setColor(progressColor); - miniProgressBackgroundPaint.setAlpha((int) (255 * alpha * wholeAlpha * overrideAlpha)); canvas.drawCircle(cx, cy, AndroidUtilities.dp(12), miniProgressBackgroundPaint); } @@ -379,7 +386,6 @@ public class RadialProgress2 { } canvas.drawCircle(cx, cy, AndroidUtilities.dp(halfSize) * alpha, circleMiniPaint); - miniMediaActionDrawable.setAlpha((int) (255 * wholeAlpha * overrideAlpha)); miniMediaActionDrawable.setBounds((int) (cx - AndroidUtilities.dp(halfSize) * alpha), (int) (cy - AndroidUtilities.dp(halfSize) * alpha), (int) (cx + AndroidUtilities.dp(halfSize) * alpha), (int) (cy + AndroidUtilities.dp(halfSize) * alpha)); miniMediaActionDrawable.draw(canvas); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index 997da0daa..03973a305 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -55,7 +55,6 @@ import org.telegram.messenger.support.widget.GridLayoutManager; import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; -import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BottomSheet; @@ -65,7 +64,6 @@ import org.telegram.ui.DialogsActivity; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; @@ -134,23 +132,15 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi TLRPC.TL_channels_exportMessageLink req = new TLRPC.TL_channels_exportMessageLink(); req.id = messages.get(0).getId(); req.channel = MessagesController.getInstance(currentAccount).getInputChannel(messages.get(0).messageOwner.to_id.channel_id); - ConnectionsManager.getInstance(currentAccount).sendRequest(req, new RequestDelegate() { - @Override - public void run(final TLObject response, TLRPC.TL_error error) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (response != null) { - exportedMessageLink = (TLRPC.TL_exportedMessageLink) response; - if (copyLinkOnEnd) { - copyLink(context); - } - } - loadingLink = false; - } - }); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response != null) { + exportedMessageLink = (TLRPC.TL_exportedMessageLink) response; + if (copyLinkOnEnd) { + copyLink(context); + } } - }); + loadingLink = false; + })); } containerView = new FrameLayout(context) { @@ -213,49 +203,41 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi frameLayout = new FrameLayout(context); frameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); - frameLayout.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }); + frameLayout.setOnTouchListener((v, event) -> true); doneButton = new LinearLayout(context); doneButton.setOrientation(LinearLayout.HORIZONTAL); doneButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 0)); doneButton.setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); frameLayout.addView(doneButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); - doneButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (selectedDialogs.size() == 0 && (isPublicChannel || linkToCopy != null)) { - if (linkToCopy == null && loadingLink) { - copyLinkOnEnd = true; - Toast.makeText(ShareAlert.this.getContext(), LocaleController.getString("Loading", R.string.Loading), Toast.LENGTH_SHORT).show(); - } else { - copyLink(ShareAlert.this.getContext()); - } - dismiss(); + doneButton.setOnClickListener(v -> { + if (selectedDialogs.size() == 0 && (isPublicChannel || linkToCopy != null)) { + if (linkToCopy == null && loadingLink) { + copyLinkOnEnd = true; + Toast.makeText(ShareAlert.this.getContext(), LocaleController.getString("Loading", R.string.Loading), Toast.LENGTH_SHORT).show(); } else { - if (sendingMessageObjects != null) { - for (int a = 0; a < selectedDialogs.size(); a++) { - long key = selectedDialogs.keyAt(a); - if (frameLayout2.getTag() != null && commentTextView.length() > 0) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null); - } - SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingMessageObjects, key); - } - } else if (sendingText != null) { - for (int a = 0; a < selectedDialogs.size(); a++) { - long key = selectedDialogs.keyAt(a); - if (frameLayout2.getTag() != null && commentTextView.length() > 0) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null); - } - SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingText, key, null, null, true, null, null, null); - } - } - dismiss(); + copyLink(ShareAlert.this.getContext()); } + dismiss(); + } else { + if (sendingMessageObjects != null) { + for (int a = 0; a < selectedDialogs.size(); a++) { + long key = selectedDialogs.keyAt(a); + if (frameLayout2.getTag() != null && commentTextView.length() > 0) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null); + } + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingMessageObjects, key); + } + } else if (sendingText != null) { + for (int a = 0; a < selectedDialogs.size(); a++) { + long key = selectedDialogs.keyAt(a); + if (frameLayout2.getTag() != null && commentTextView.length() > 0) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null); + } + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingText, key, null, null, true, null, null, null); + } + } + dismiss(); } }); @@ -362,31 +344,28 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi containerView.addView(gridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); gridView.setAdapter(listAdapter = new ShareDialogsAdapter(context)); gridView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); - gridView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { - @Override - public void onItemClick(View view, int position) { - if (position < 0) { - return; - } - TLRPC.TL_dialog dialog; - if (gridView.getAdapter() == listAdapter) { - dialog = listAdapter.getItem(position); - } else { - dialog = searchAdapter.getItem(position); - } - if (dialog == null) { - return; - } - ShareDialogCell cell = (ShareDialogCell) view; - if (selectedDialogs.indexOfKey(dialog.id) >= 0) { - selectedDialogs.remove(dialog.id); - cell.setChecked(false, true); - } else { - selectedDialogs.put(dialog.id, dialog); - cell.setChecked(true, true); - } - updateSelectedCount(); + gridView.setOnItemClickListener((view, position) -> { + if (position < 0) { + return; } + TLRPC.TL_dialog dialog; + if (gridView.getAdapter() == listAdapter) { + dialog = listAdapter.getItem(position); + } else { + dialog = searchAdapter.getItem(position); + } + if (dialog == null) { + return; + } + ShareDialogCell cell = (ShareDialogCell) view; + if (selectedDialogs.indexOfKey(dialog.id) >= 0) { + selectedDialogs.remove(dialog.id); + cell.setChecked(false, true); + } else { + selectedDialogs.put(dialog.id, dialog); + cell.setChecked(true, true); + } + updateSelectedCount(); }); gridView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -412,12 +391,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi frameLayout2.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); frameLayout2.setTranslationY(AndroidUtilities.dp(53)); containerView.addView(frameLayout2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); - frameLayout2.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }); + frameLayout2.setOnTouchListener((v, event) -> true); commentTextView = new EditTextBoldCursor(context); commentTextView.setHint(LocaleController.getString("ShareComment", R.string.ShareComment)); @@ -588,9 +562,16 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi public void fetchDialogs() { dialogs.clear(); - for (int a = 0; a < MessagesController.getInstance(currentAccount).dialogsForward.size(); a++) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogsForward.get(a); + int selfUserId = UserConfig.getInstance(currentAccount).clientUserId; + if (!MessagesController.getInstance(currentAccount).dialogsForward.isEmpty()) { + dialogs.add(MessagesController.getInstance(currentAccount).dialogsForward.get(0)); + } + for (int a = 0; a < MessagesController.getInstance(currentAccount).dialogs.size(); a++) { + TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs.get(a); int lower_id = (int) dialog.id; + if (lower_id == selfUserId) { + continue; + } int high_id = (int) (dialog.id >> 32); if (lower_id != 0 && high_id != 1) { if (lower_id > 0) { @@ -665,143 +646,55 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } private void searchDialogsInternal(final String query, final int searchId) { - MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(new Runnable() { - @Override - public void run() { - try { - String search1 = query.trim().toLowerCase(); - if (search1.length() == 0) { - lastSearchId = -1; - updateSearchResults(new ArrayList(), lastSearchId); - return; - } - String search2 = LocaleController.getInstance().getTranslitString(search1); - if (search1.equals(search2) || search2.length() == 0) { - search2 = null; - } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; - search[0] = search1; - if (search2 != null) { - search[1] = search2; - } + MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { + try { + String search1 = query.trim().toLowerCase(); + if (search1.length() == 0) { + lastSearchId = -1; + updateSearchResults(new ArrayList<>(), lastSearchId); + return; + } + String search2 = LocaleController.getInstance().getTranslitString(search1); + if (search1.equals(search2) || search2.length() == 0) { + search2 = null; + } + String search[] = new String[1 + (search2 != null ? 1 : 0)]; + search[0] = search1; + if (search2 != null) { + search[1] = search2; + } - ArrayList usersToLoad = new ArrayList<>(); - ArrayList chatsToLoad = new ArrayList<>(); - int resultCount = 0; + ArrayList usersToLoad = new ArrayList<>(); + ArrayList chatsToLoad = new ArrayList<>(); + int resultCount = 0; - LongSparseArray dialogsResult = new LongSparseArray<>(); - SQLiteCursor cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT did, date FROM dialogs ORDER BY date DESC LIMIT 400"); + LongSparseArray dialogsResult = new LongSparseArray<>(); + SQLiteCursor cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT did, date FROM dialogs ORDER BY date DESC LIMIT 400"); + while (cursor.next()) { + long id = cursor.longValue(0); + DialogSearchResult dialogSearchResult = new DialogSearchResult(); + dialogSearchResult.date = cursor.intValue(1); + dialogsResult.put(id, dialogSearchResult); + + int lower_id = (int) id; + int high_id = (int) (id >> 32); + if (lower_id != 0 && high_id != 1) { + if (lower_id > 0) { + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); + } + } else { + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); + } + } + } + } + cursor.dispose(); + + if (!usersToLoad.isEmpty()) { + cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, status, name FROM users WHERE uid IN(%s)", TextUtils.join(",", usersToLoad))); while (cursor.next()) { - long id = cursor.longValue(0); - DialogSearchResult dialogSearchResult = new DialogSearchResult(); - dialogSearchResult.date = cursor.intValue(1); - dialogsResult.put(id, dialogSearchResult); - - int lower_id = (int) id; - int high_id = (int) (id >> 32); - if (lower_id != 0 && high_id != 1) { - if (lower_id > 0) { - if (!usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); - } - } else { - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); - } - } - } - } - cursor.dispose(); - - if (!usersToLoad.isEmpty()) { - cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, status, name FROM users WHERE uid IN(%s)", TextUtils.join(",", usersToLoad))); - while (cursor.next()) { - String name = cursor.stringValue(2); - String tName = LocaleController.getInstance().getTranslitString(name); - if (name.equals(tName)) { - tName = null; - } - String username = null; - int usernamePos = name.lastIndexOf(";;;"); - if (usernamePos != -1) { - username = name.substring(usernamePos + 3); - } - int found = 0; - for (String q : search) { - if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) { - found = 1; - } else if (username != null && username.startsWith(q)) { - found = 2; - } - if (found != 0) { - NativeByteBuffer data = cursor.byteBufferValue(0); - if (data != null) { - TLRPC.User user = TLRPC.User.TLdeserialize(data, data.readInt32(false), false); - data.reuse(); - DialogSearchResult dialogSearchResult = dialogsResult.get((long) user.id); - if (user.status != null) { - user.status.expires = cursor.intValue(1); - } - if (found == 1) { - dialogSearchResult.name = AndroidUtilities.generateSearchName(user.first_name, user.last_name, q); - } else { - dialogSearchResult.name = AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q); - } - dialogSearchResult.object = user; - dialogSearchResult.dialog.id = user.id; - resultCount++; - } - break; - } - } - } - cursor.dispose(); - } - - if (!chatsToLoad.isEmpty()) { - cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, name FROM chats WHERE uid IN(%s)", TextUtils.join(",", chatsToLoad))); - while (cursor.next()) { - String name = cursor.stringValue(1); - String tName = LocaleController.getInstance().getTranslitString(name); - if (name.equals(tName)) { - tName = null; - } - for (int a = 0; a < search.length; a++) { - String q = search[a]; - if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) { - NativeByteBuffer data = cursor.byteBufferValue(0); - if (data != null) { - TLRPC.Chat chat = TLRPC.Chat.TLdeserialize(data, data.readInt32(false), false); - data.reuse(); - if (!(chat == null || ChatObject.isNotInChat(chat) || ChatObject.isChannel(chat) && !chat.creator && (chat.admin_rights == null || !chat.admin_rights.post_messages) && !chat.megagroup)) { - DialogSearchResult dialogSearchResult = dialogsResult.get(-(long) chat.id); - dialogSearchResult.name = AndroidUtilities.generateSearchName(chat.title, null, q); - dialogSearchResult.object = chat; - dialogSearchResult.dialog.id = -chat.id; - resultCount++; - } - } - break; - } - } - } - cursor.dispose(); - } - - ArrayList searchResults = new ArrayList<>(resultCount); - for (int a = 0; a < dialogsResult.size(); a++) { - DialogSearchResult dialogSearchResult = dialogsResult.valueAt(a); - if (dialogSearchResult.object != null && dialogSearchResult.name != null) { - searchResults.add(dialogSearchResult); - } - } - - cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT u.data, u.status, u.name, u.uid FROM users as u INNER JOIN contacts as c ON u.uid = c.uid"); - while (cursor.next()) { - int uid = cursor.intValue(3); - if (dialogsResult.indexOfKey((long) uid) >= 0) { - continue; - } String name = cursor.stringValue(2); String tName = LocaleController.getInstance().getTranslitString(name); if (name.equals(tName)) { @@ -824,74 +717,153 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi if (data != null) { TLRPC.User user = TLRPC.User.TLdeserialize(data, data.readInt32(false), false); data.reuse(); - DialogSearchResult dialogSearchResult = new DialogSearchResult(); + DialogSearchResult dialogSearchResult = dialogsResult.get((long) user.id); if (user.status != null) { user.status.expires = cursor.intValue(1); } - dialogSearchResult.dialog.id = user.id; - dialogSearchResult.object = user; if (found == 1) { dialogSearchResult.name = AndroidUtilities.generateSearchName(user.first_name, user.last_name, q); } else { dialogSearchResult.name = AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q); } - searchResults.add(dialogSearchResult); + dialogSearchResult.object = user; + dialogSearchResult.dialog.id = user.id; + resultCount++; } break; } } } cursor.dispose(); - - Collections.sort(searchResults, new Comparator() { - @Override - public int compare(DialogSearchResult lhs, DialogSearchResult rhs) { - if (lhs.date < rhs.date) { - return 1; - } else if (lhs.date > rhs.date) { - return -1; - } - return 0; - } - }); - - updateSearchResults(searchResults, searchId); - } catch (Exception e) { - FileLog.e(e); } + + if (!chatsToLoad.isEmpty()) { + cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, name FROM chats WHERE uid IN(%s)", TextUtils.join(",", chatsToLoad))); + while (cursor.next()) { + String name = cursor.stringValue(1); + String tName = LocaleController.getInstance().getTranslitString(name); + if (name.equals(tName)) { + tName = null; + } + for (int a = 0; a < search.length; a++) { + String q = search[a]; + if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) { + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data != null) { + TLRPC.Chat chat = TLRPC.Chat.TLdeserialize(data, data.readInt32(false), false); + data.reuse(); + if (!(chat == null || ChatObject.isNotInChat(chat) || ChatObject.isChannel(chat) && !chat.creator && (chat.admin_rights == null || !chat.admin_rights.post_messages) && !chat.megagroup)) { + DialogSearchResult dialogSearchResult = dialogsResult.get(-(long) chat.id); + dialogSearchResult.name = AndroidUtilities.generateSearchName(chat.title, null, q); + dialogSearchResult.object = chat; + dialogSearchResult.dialog.id = -chat.id; + resultCount++; + } + } + break; + } + } + } + cursor.dispose(); + } + + ArrayList searchResults = new ArrayList<>(resultCount); + for (int a = 0; a < dialogsResult.size(); a++) { + DialogSearchResult dialogSearchResult = dialogsResult.valueAt(a); + if (dialogSearchResult.object != null && dialogSearchResult.name != null) { + searchResults.add(dialogSearchResult); + } + } + + cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT u.data, u.status, u.name, u.uid FROM users as u INNER JOIN contacts as c ON u.uid = c.uid"); + while (cursor.next()) { + int uid = cursor.intValue(3); + if (dialogsResult.indexOfKey((long) uid) >= 0) { + continue; + } + String name = cursor.stringValue(2); + String tName = LocaleController.getInstance().getTranslitString(name); + if (name.equals(tName)) { + tName = null; + } + String username = null; + int usernamePos = name.lastIndexOf(";;;"); + if (usernamePos != -1) { + username = name.substring(usernamePos + 3); + } + int found = 0; + for (String q : search) { + if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) { + found = 1; + } else if (username != null && username.startsWith(q)) { + found = 2; + } + if (found != 0) { + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data != null) { + TLRPC.User user = TLRPC.User.TLdeserialize(data, data.readInt32(false), false); + data.reuse(); + DialogSearchResult dialogSearchResult = new DialogSearchResult(); + if (user.status != null) { + user.status.expires = cursor.intValue(1); + } + dialogSearchResult.dialog.id = user.id; + dialogSearchResult.object = user; + if (found == 1) { + dialogSearchResult.name = AndroidUtilities.generateSearchName(user.first_name, user.last_name, q); + } else { + dialogSearchResult.name = AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q); + } + searchResults.add(dialogSearchResult); + } + break; + } + } + } + cursor.dispose(); + + Collections.sort(searchResults, (lhs, rhs) -> { + if (lhs.date < rhs.date) { + return 1; + } else if (lhs.date > rhs.date) { + return -1; + } + return 0; + }); + + updateSearchResults(searchResults, searchId); + } catch (Exception e) { + FileLog.e(e); } }); } private void updateSearchResults(final ArrayList result, final int searchId) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (searchId != lastSearchId) { - return; - } - for (int a = 0; a < result.size(); a++) { - DialogSearchResult obj = result.get(a); - if (obj.object instanceof TLRPC.User) { - TLRPC.User user = (TLRPC.User) obj.object; - MessagesController.getInstance(currentAccount).putUser(user, true); - } else if (obj.object instanceof TLRPC.Chat) { - TLRPC.Chat chat = (TLRPC.Chat) obj.object; - MessagesController.getInstance(currentAccount).putChat(chat, true); - } - } - boolean becomeEmpty = !searchResult.isEmpty() && result.isEmpty(); - boolean isEmpty = searchResult.isEmpty() && result.isEmpty(); - if (becomeEmpty) { - topBeforeSwitch = getCurrentTop(); - } - searchResult = result; - notifyDataSetChanged(); - if (!isEmpty && !becomeEmpty && topBeforeSwitch > 0) { - layoutManager.scrollToPositionWithOffset(0, -topBeforeSwitch); - topBeforeSwitch = -1000; + AndroidUtilities.runOnUIThread(() -> { + if (searchId != lastSearchId) { + return; + } + for (int a = 0; a < result.size(); a++) { + DialogSearchResult obj = result.get(a); + if (obj.object instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) obj.object; + MessagesController.getInstance(currentAccount).putUser(user, true); + } else if (obj.object instanceof TLRPC.Chat) { + TLRPC.Chat chat = (TLRPC.Chat) obj.object; + MessagesController.getInstance(currentAccount).putChat(chat, true); } } + boolean becomeEmpty = !searchResult.isEmpty() && result.isEmpty(); + boolean isEmpty = searchResult.isEmpty() && result.isEmpty(); + if (becomeEmpty) { + topBeforeSwitch = getCurrentTop(); + } + searchResult = result; + notifyDataSetChanged(); + if (!isEmpty && !becomeEmpty && topBeforeSwitch > 0) { + layoutManager.scrollToPositionWithOffset(0, -topBeforeSwitch); + topBeforeSwitch = -1000; + } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java index 2f0c890d2..916f04879 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -34,6 +34,7 @@ public class SizeNotifierFrameLayout extends FrameLayout { private float translationX; private float translationY; private float parallaxScale = 1.0f; + private boolean paused = true; public interface SizeNotifierFrameLayoutDelegate { void onSizeChanged(int keyboardHeight, boolean isWidthGreater); @@ -58,10 +59,13 @@ public class SizeNotifierFrameLayout extends FrameLayout { parallaxScale = parallaxEffect.getScale(getMeasuredWidth(), getMeasuredHeight()); } } + if (!paused) { + parallaxEffect.setEnabled(true); + } } else if (parallaxEffect != null) { parallaxEffect.setEnabled(false); parallaxEffect = null; - parallaxScale = 0; + parallaxScale = 1.0f; translationX = 0; translationY = 0; } @@ -84,12 +88,14 @@ public class SizeNotifierFrameLayout extends FrameLayout { if (parallaxEffect != null) { parallaxEffect.setEnabled(false); } + paused = true; } public void onResume() { if (parallaxEffect != null) { parallaxEffect.setEnabled(true); } + paused = false; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TermsOfServiceView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TermsOfServiceView.java index 3717d2c67..569a176a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TermsOfServiceView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TermsOfServiceView.java @@ -30,6 +30,8 @@ public class TermsOfServiceView extends FrameLayout { private TextView textView; private TermsOfServiceViewDelegate delegate; private TLRPC.TL_help_termsOfService currentTos; + private TextView titleTextView; + private ScrollView scrollView; private int currentAccount; public interface TermsOfServiceViewDelegate { @@ -52,7 +54,7 @@ public class TermsOfServiceView extends FrameLayout { imageView.setImageResource(R.drawable.logo_middle); addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 30 + top, 0, 0)); - TextView titleTextView = new TextView(context); + titleTextView = new TextView(context); titleTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); titleTextView.setGravity(Gravity.LEFT | Gravity.TOP); @@ -60,7 +62,7 @@ public class TermsOfServiceView extends FrameLayout { titleTextView.setText(LocaleController.getString("PrivacyPolicyAndTerms", R.string.PrivacyPolicyAndTerms)); addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 27, 126 + top, 27, 75)); - ScrollView scrollView = new ScrollView(context); + scrollView = new ScrollView(context); AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault)); addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 27, 160 + top, 27, 75)); @@ -173,6 +175,14 @@ public class TermsOfServiceView extends FrameLayout { currentAccount = account; } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureChildWithMargins(titleTextView, widthMeasureSpec, 0, heightMeasureSpec, 0); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) scrollView.getLayoutParams(); + layoutParams.topMargin = AndroidUtilities.dp(126 + 30) + titleTextView.getMeasuredHeight(); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + public void setDelegate(TermsOfServiceViewDelegate termsOfServiceViewDelegate) { delegate = termsOfServiceViewDelegate; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java index 4ffc3a2b5..77817681f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java @@ -192,7 +192,7 @@ public class ThemeEditorView { linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); - for (int a = 0; a < 4; a++){ + for (int a = 0; a < 4; a++) { colorEditText[a] = new EditTextBoldCursor(context); colorEditText[a].setInputType(InputType.TYPE_CLASS_NUMBER); colorEditText[a].setTextColor(0xff212121); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java index 9ba282d70..c13c6dbde 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java @@ -102,7 +102,7 @@ public class UndoView extends FrameLayout { } public void hide(boolean apply, boolean animated) { - if (getVisibility() != VISIBLE) { + if (getVisibility() != VISIBLE || currentActionRunnable == null) { return; } if (currentActionRunnable != null) { @@ -159,6 +159,9 @@ public class UndoView extends FrameLayout { infoTextView.setText(LocaleController.getString("ChatDeletedUndo", R.string.ChatDeletedUndo)); } } + if (currentActionRunnable != null) { + currentActionRunnable.run(); + } currentActionRunnable = actionRunnable; currentCancelRunnable = cancelRunnable; currentDialogId = did; @@ -166,13 +169,15 @@ public class UndoView extends FrameLayout { timeLeft = 5000; lastUpdateTime = SystemClock.uptimeMillis(); MessagesController.getInstance(currentAccount).addDialogAction(did, clear); - setVisibility(VISIBLE); - setTranslationY(AndroidUtilities.dp(48)); - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, AndroidUtilities.dp(48), 0)); - animatorSet.setInterpolator(new DecelerateInterpolator()); - animatorSet.setDuration(180); - animatorSet.start(); + if (getVisibility() != VISIBLE) { + setVisibility(VISIBLE); + setTranslationY(AndroidUtilities.dp(48)); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, AndroidUtilities.dp(48), 0)); + animatorSet.setInterpolator(new DecelerateInterpolator()); + animatorSet.setDuration(180); + animatorSet.start(); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperParallaxEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperParallaxEffect.java index 3d32a1331..19c0866db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperParallaxEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperParallaxEffect.java @@ -65,8 +65,8 @@ public class WallpaperParallaxEffect implements SensorEventListener { float z = event.values[2] / SensorManager.GRAVITY_EARTH; - float roll = (float) (Math.atan2(y, z) / Math.PI * 2.0); - float pitch = (float) (Math.atan2(-x, Math.sqrt(y * y + z * z)) / Math.PI * 2.0); + float pitch=(float)(Math.atan2(x, Math.sqrt(y*y+z*z))/Math.PI*2.0); + float roll=(float)(Math.atan2(y, Math.sqrt(x*x+z*z))/Math.PI*2.0); switch (rotation) { case Surface.ROTATION_0: diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java index b0d2de53b..8407a6a3a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java @@ -54,7 +54,6 @@ public class WallpaperUpdater { parentActivity = activity; parentFragment = fragment; delegate = wallpaperUpdaterDelegate; - currentWallpaperPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.random.nextInt() + ".jpg"); } public void showAlert(final boolean fromTheme) { @@ -147,6 +146,7 @@ public class WallpaperUpdater { if (!photos.isEmpty()) { SendMessagesHelper.SendingMediaInfo info = photos.get(0); if (info.path != null) { + currentWallpaperPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.random.nextInt() + ".jpg"); Point screenSize = AndroidUtilities.getRealScreenSize(); Bitmap bitmap = ImageLoader.loadBitmap(info.path, null, screenSize.x, screenSize.y, true); FileOutputStream stream = new FileOutputStream(currentWallpaperPath); @@ -160,11 +160,9 @@ public class WallpaperUpdater { } public void cleanup() { - currentWallpaperPath.delete(); - } - - public File getCurrentWallpaperPath() { - return currentWallpaperPath; + /*if (currentWallpaperPath != null) { + currentWallpaperPath.delete(); + }*/ } public String getCurrentPicturePath() { @@ -181,6 +179,7 @@ public class WallpaperUpdater { AndroidUtilities.addMediaToGallery(currentPicturePath); FileOutputStream stream = null; try { + currentWallpaperPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.random.nextInt() + ".jpg"); Point screenSize = AndroidUtilities.getRealScreenSize(); Bitmap bitmap = ImageLoader.loadBitmap(currentPicturePath, null, screenSize.x, screenSize.y, true); stream = new FileOutputStream(currentWallpaperPath); @@ -203,6 +202,7 @@ public class WallpaperUpdater { return; } try { + currentWallpaperPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.random.nextInt() + ".jpg"); Point screenSize = AndroidUtilities.getRealScreenSize(); Bitmap bitmap = ImageLoader.loadBitmap(null, data.getData(), screenSize.x, screenSize.y, true); FileOutputStream stream = new FileOutputStream(currentWallpaperPath); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 6794ac945..62f8f3d95 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -146,7 +146,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateInterfaces); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.encryptedChatCreated); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.closeChats); - MessagesController.getGlobalNotificationsSettings().getBoolean("askAboutContacts", true); checkPermission = UserConfig.getInstance(currentAccount).syncContacts; if (arguments != null) { onlyUsers = getArguments().getBoolean("onlyUsers", false); @@ -375,7 +374,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter if (row < 0 || section < 0) { return; } - if ((!onlyUsers || chat_id != 0) && section == 0) { + if ((!onlyUsers || chat_id != 0 && inviteViaLink) && section == 0) { if (needPhonebook) { if (row == 0) { presentFragment(new InviteContactsActivity()); @@ -671,7 +670,9 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter if (activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { AlertDialog.Builder builder = AlertsCreator.createContactsPermissionDialog(activity, param -> { askAboutContacts = param != 0; - MessagesController.getGlobalNotificationsSettings().edit().putBoolean("askAboutContacts", askAboutContacts).commit(); + if (param == 0) { + return; + } askForPermissons(false); }); showDialog(permissionDialog = builder.create()); @@ -703,7 +704,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter @Override protected void onDialogDismiss(Dialog dialog) { super.onDialogDismiss(dialog); - if (permissionDialog != null && dialog == permissionDialog && getParentActivity() != null) { + if (permissionDialog != null && dialog == permissionDialog && getParentActivity() != null && askAboutContacts) { askForPermissons(false); } } @@ -717,7 +718,9 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter if (alert && askAboutContacts) { AlertDialog.Builder builder = AlertsCreator.createContactsPermissionDialog(activity, param -> { askAboutContacts = param != 0; - MessagesController.getGlobalNotificationsSettings().edit().putBoolean("askAboutContacts", askAboutContacts).commit(); + if (param == 0) { + return; + } askForPermissons(false); }); showDialog(builder.create()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 2da77a764..cbecabb89 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -938,10 +938,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. TLRPC.Chat chat = isChat ? MessagesController.getInstance(currentAccount).getChat(-lower_id) : null; if (lower_id == 0) { TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); - if (encryptedChat == null) { - return false; + if (encryptedChat != null) { + user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); + } else { + user = new TLRPC.TL_userEmpty(); } - user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); } else { user = !isChat && lower_id > 0 && high_id != 1 ? MessagesController.getInstance(currentAccount).getUser(lower_id) : null; } @@ -1476,7 +1477,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (activity != null) { checkPermission = false; if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED || activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - if (UserConfig.getInstance(currentAccount).syncContacts && activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { + if (askAboutContacts && UserConfig.getInstance(currentAccount).syncContacts && activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { AlertDialog.Builder builder = AlertsCreator.createContactsPermissionDialog(activity, param -> { askAboutContacts = param != 0; MessagesController.getGlobalNotificationsSettings().edit().putBoolean("askAboutContacts", askAboutContacts).commit(); @@ -1531,6 +1532,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (commentView != null) { commentView.onResume(); } + if (undoView != null) { + undoView.hide(true, false); + } } @Override @@ -1758,7 +1762,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override protected void onDialogDismiss(Dialog dialog) { super.onDialogDismiss(dialog); - if (permissionDialog != null && dialog == permissionDialog && getParentActivity() != null) { + if (permissionDialog != null && dialog == permissionDialog && getParentActivity() != null && askAboutContacts) { askForPermissons(false); } } @@ -1948,6 +1952,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. return MessagesController.getInstance(currentAccount).dialogsGroupsOnly; } else if (dialogsType == 3) { return MessagesController.getInstance(currentAccount).dialogsForward; + } else if (dialogsType == 4) { + return MessagesController.getInstance(currentAccount).dialogsUsersOnly; + } else if (dialogsType == 5) { + return MessagesController.getInstance(currentAccount).dialogsChannelsOnly; } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 48c3e0c41..215ad87eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -1040,7 +1040,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa String username = null; String group = null; String sticker = null; - String instantView[] = null; HashMap auth = null; String unsupportedUrl = null; String botUser = null; @@ -1051,8 +1050,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa String phoneHash = null; String lang = null; String code = null; - String wallpaper = null; - int wallpaperModes = 0; + TLRPC.TL_wallPaper wallPaper = null; Integer messageId = null; boolean hasUrl = false; String scheme = data.getScheme(); @@ -1064,20 +1062,40 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (path != null && path.length() > 1) { path = path.substring(1); if (path.startsWith("bg/")) { - wallpaper = path.replace("bg/", ""); - String mode = data.getQueryParameter("mode"); - if (mode != null) { - mode = mode.toLowerCase(); - String[] modes = mode.split(" "); - if (modes != null && modes.length > 0) { - for (int a = 0; a < modes.length; a++) { - if ("blur".equals(modes[a])) { - wallpaperModes |= 1; - } else if ("motion".equals(modes[a])) { - wallpaperModes |= 2; + wallPaper = new TLRPC.TL_wallPaper(); + wallPaper.settings = new TLRPC.TL_wallPaperSettings(); + wallPaper.slug = path.replace("bg/", ""); + if (wallPaper.slug != null && wallPaper.slug.length() == 6) { + try { + wallPaper.settings.background_color = Integer.parseInt(wallPaper.slug, 16) | 0xff000000; + } catch (Exception ignore) { + + } + wallPaper.slug = null; + } else { + String mode = data.getQueryParameter("mode"); + if (mode != null) { + mode = mode.toLowerCase(); + String[] modes = mode.split(" "); + if (modes != null && modes.length > 0) { + for (int a = 0; a < modes.length; a++) { + if ("blur".equals(modes[a])) { + wallPaper.settings.blur = true; + } else if ("motion".equals(modes[a])) { + wallPaper.settings.motion = true; + } } } } + wallPaper.settings.intensity = Utilities.parseInt(data.getQueryParameter("intensity")); + try { + String bgColor = data.getQueryParameter("bg_color"); + if (!TextUtils.isEmpty(bgColor)) { + wallPaper.settings.background_color = Integer.parseInt(bgColor, 16) | 0xff000000; + } + } catch (Exception ignore) { + + } } } else if (path.startsWith("login/")) { code = path.replace("login/", ""); @@ -1085,12 +1103,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa group = path.replace("joinchat/", ""); } else if (path.startsWith("addstickers/")) { sticker = path.replace("addstickers/", ""); - } else if (path.startsWith("iv/")) { - instantView[0] = data.getQueryParameter("url"); - instantView[1] = data.getQueryParameter("rhash"); - if (TextUtils.isEmpty(instantView[0]) || TextUtils.isEmpty(instantView[1])) { - instantView = null; - } } else if (path.startsWith("msg/") || path.startsWith("share/")) { message = data.getQueryParameter("url"); if (message == null) { @@ -1162,20 +1174,43 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else if (url.startsWith("tg:bg") || url.startsWith("tg://bg")) { url = url.replace("tg:bg", "tg://telegram.org").replace("tg://bg", "tg://telegram.org"); data = Uri.parse(url); - wallpaper = data.getQueryParameter("slug"); - String mode = data.getQueryParameter("mode"); - if (mode != null) { - mode = mode.toLowerCase(); - String[] modes = mode.split(" "); - if (modes != null && modes.length > 0) { - for (int a = 0; a < modes.length; a++) { - if ("blur".equals(modes[a])) { - wallpaperModes |= 1; - } else if ("motion".equals(modes[a])) { - wallpaperModes |= 2; + wallPaper = new TLRPC.TL_wallPaper(); + wallPaper.settings = new TLRPC.TL_wallPaperSettings(); + wallPaper.slug = data.getQueryParameter("slug"); + if (wallPaper.slug == null) { + wallPaper.slug = data.getQueryParameter("color"); + } + if (wallPaper.slug != null && wallPaper.slug.length() == 6) { + try { + wallPaper.settings.background_color = Integer.parseInt(wallPaper.slug, 16) | 0xff000000; + } catch (Exception ignore) { + + } + wallPaper.slug = null; + } else { + String mode = data.getQueryParameter("mode"); + if (mode != null) { + mode = mode.toLowerCase(); + String[] modes = mode.split(" "); + if (modes != null && modes.length > 0) { + for (int a = 0; a < modes.length; a++) { + if ("blur".equals(modes[a])) { + wallPaper.settings.blur = true; + } else if ("motion".equals(modes[a])) { + wallPaper.settings.motion = true; + } } } } + wallPaper.settings.intensity = Utilities.parseInt(data.getQueryParameter("intensity")); + try { + String bgColor = data.getQueryParameter("bg_color"); + if (!TextUtils.isEmpty(bgColor)) { + wallPaper.settings.background_color = Integer.parseInt(bgColor, 16) | 0xff000000; + } + } catch (Exception ignore) { + + } } } else if (url.startsWith("tg:join") || url.startsWith("tg://join")) { url = url.replace("tg:join", "tg://telegram.org").replace("tg://join", "tg://telegram.org"); @@ -1273,11 +1308,11 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa args.putString("phone", phone); args.putString("hash", phoneHash); AndroidUtilities.runOnUIThread(() -> presentFragment(new CancelAccountDeletionActivity(args))); - } else if (username != null || group != null || sticker != null || message != null || game != null || instantView != null || auth != null || unsupportedUrl != null || lang != null || code != null || wallpaper != null) { + } else if (username != null || group != null || sticker != null || message != null || game != null || auth != null || unsupportedUrl != null || lang != null || code != null || wallPaper != null) { if (message != null && message.startsWith("@")) { message = " " + message; } - runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, message, hasUrl, messageId, game, instantView, auth, lang, unsupportedUrl, code, wallpaper, wallpaperModes, 0); + runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, message, hasUrl, messageId, game, auth, lang, unsupportedUrl, code, wallPaper, 0); } else { try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) { if (cursor != null) { @@ -1518,20 +1553,18 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa final boolean hasUrl, final Integer messageId, final String game, - final String[] instantView, final HashMap auth, final String lang, final String unsupportedUrl, final String code, - final String wallpaper, - final int wallpaperModes, + final TLRPC.TL_wallPaper wallPaper, final int state) { if (state == 0 && UserConfig.getActivatedAccountsCount() >= 2 && auth != null) { AlertsCreator.createAccountSelectDialog(this, account -> { if (account != intentAccount) { switchToAccount(account, true); } - runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, game, instantView, auth, lang, unsupportedUrl, code, wallpaper, wallpaperModes, 1); + runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, game, auth, lang, unsupportedUrl, code, wallPaper, 1); }).show(); return; } else if (code != null) { @@ -1720,7 +1753,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa AlertDialog.Builder builder = new AlertDialog.Builder(LaunchActivity.this); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.formatString("ChannelJoinTo", R.string.ChannelJoinTo, invite.chat != null ? invite.chat.title : invite.title)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> runLinkRequest(intentAccount, username, group, sticker, botUser, botChat, message, hasUrl, messageId, game, instantView, auth, lang, unsupportedUrl, code, wallpaper, wallpaperModes, 1)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> runLinkRequest(intentAccount, username, group, sticker, botUser, botChat, message, hasUrl, messageId, game, auth, lang, unsupportedUrl, code, wallPaper, 1)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showAlertDialog(builder); } @@ -1827,8 +1860,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } }); presentFragment(fragment, false, true); - } else if (instantView != null) { - } else if (auth != null) { final int bot_id = Utilities.parseInt(auth.get("bot_id")); if (bot_id == 0) { @@ -1908,25 +1939,47 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } })); - } else if (wallpaper != null) { - TLRPC.TL_account_getWallPaper req = new TLRPC.TL_account_getWallPaper(); - TLRPC.TL_inputWallPaperSlug inputWallPaperSlug = new TLRPC.TL_inputWallPaperSlug(); - inputWallPaperSlug.slug = wallpaper; - req.wallpaper = inputWallPaperSlug; - requestId[0] = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + } else if (wallPaper != null) { + boolean ok = false; + if (TextUtils.isEmpty(wallPaper.slug)) { try { - progressDialog.dismiss(); + WallpapersListActivity.ColorWallpaper colorWallpaper = new WallpapersListActivity.ColorWallpaper(-100, wallPaper.settings.background_color); + WallpaperActivity wallpaperActivity = new WallpaperActivity(colorWallpaper, null); + AndroidUtilities.runOnUIThread(() -> presentFragment(wallpaperActivity)); + ok = true; } catch (Exception e) { FileLog.e(e); } - if (response instanceof TLRPC.TL_wallPaper) { - WallpaperActivity wallpaperActivity = new WallpaperActivity(response, null); - wallpaperActivity.setInitialModes(wallpaperModes); - presentFragment(wallpaperActivity); - } else { - showAlertDialog(AlertsCreator.createSimpleAlert(LaunchActivity.this, LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text)); - } - })); + } + if (!ok) { + TLRPC.TL_account_getWallPaper req = new TLRPC.TL_account_getWallPaper(); + TLRPC.TL_inputWallPaperSlug inputWallPaperSlug = new TLRPC.TL_inputWallPaperSlug(); + inputWallPaperSlug.slug = wallPaper.slug; + req.wallpaper = inputWallPaperSlug; + requestId[0] = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e(e); + } + if (response instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper res = (TLRPC.TL_wallPaper) response; + Object object; + if (wallPaper.settings.background_color != 0) { + WallpapersListActivity.ColorWallpaper colorWallpaper = new WallpapersListActivity.ColorWallpaper(-1, wallPaper.settings.background_color, res.id, wallPaper.settings.intensity / 100.0f, wallPaper.settings.motion, null); + colorWallpaper.pattern = res; + object = colorWallpaper; + } else { + object = res; + } + WallpaperActivity wallpaperActivity = new WallpaperActivity(object, null); + wallpaperActivity.setInitialModes(wallPaper.settings.blur, wallPaper.settings.motion); + presentFragment(wallpaperActivity); + } else { + showAlertDialog(AlertsCreator.createSimpleAlert(LaunchActivity.this, LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text)); + } + })); + } } if (requestId[0] != 0) { @@ -2587,10 +2640,11 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } else if (id == NotificationCenter.needSetDayNightTheme) { Theme.ThemeInfo theme = (Theme.ThemeInfo) args[0]; - actionBarLayout.animateThemedValues(theme); + boolean nigthTheme = (Boolean) args[1]; + actionBarLayout.animateThemedValues(theme, nigthTheme); if (AndroidUtilities.isTablet()) { - layersActionBarLayout.animateThemedValues(theme); - rightActionBarLayout.animateThemedValues(theme); + layersActionBarLayout.animateThemedValues(theme, nigthTheme); + rightActionBarLayout.animateThemedValues(theme, nigthTheme); } } else if (id == NotificationCenter.notificationsCountUpdated) { if (sideMenu != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index ae64048a7..e297628bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -110,9 +110,6 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; -//SmsManager mgr = SmsManager.getDefault(); -//String token = mgr.createAppSpecificSmsToken(PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, new Intent("SMS_RECEIVED"), PendingIntent.FLAG_UPDATE_CURRENT)); - @SuppressLint("HardwareIds") public class LoginActivity extends BaseFragment { @@ -205,7 +202,9 @@ public class LoginActivity extends BaseFragment { views[currentViewNum].onNextPressed(); } } else if (id == -1) { - onBackPressed(); + if (onBackPressed()) { + finishFragment(); + } } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java index 7f8fea306..e8e6a0c17 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java @@ -20,12 +20,12 @@ import android.net.Uri; import android.os.Vibrator; import android.telephony.TelephonyManager; 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; +import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.AdapterView; @@ -337,9 +337,6 @@ public class NewContactActivity extends BaseFragment implements AdapterView.OnIt codeField.setMaxLines(1); codeField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - InputFilter[] inputFilters = new InputFilter[1]; - inputFilters[0] = new InputFilter.LengthFilter(5); - codeField.setFilters(inputFilters); linearLayout2.addView(codeField, LayoutHelper.createLinear(55, 36, -9, 0, 16, 0)); codeField.addTextChangedListener(new TextWatcher() { @Override @@ -521,6 +518,15 @@ public class NewContactActivity extends BaseFragment implements AdapterView.OnIt } return false; }); + phoneField.setOnKeyListener((v, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_DEL && phoneField.length() == 0) { + codeField.requestFocus(); + codeField.setSelection(codeField.length()); + codeField.dispatchKeyEvent(event); + return true; + } + return false; + }); HashMap languageMap = new HashMap<>(); try { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index 799a0a7d2..04ae03a79 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -20,6 +20,7 @@ import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.provider.Settings; import android.view.View; import android.view.ViewGroup; @@ -46,11 +47,12 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.NotificationsCheckCell; -import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextColorCell; import org.telegram.ui.Cells.TextSettingsCell; +import org.telegram.ui.Cells.UserCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; @@ -83,7 +85,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { private int messagePopupNotificationRow; private int messagePriorityRow; private int groupSection2Row; - private int exceptionsSectionRow; + private int exceptionsAddRow; private int exceptionsStartRow; private int exceptionsEndRow; private int exceptionsSection2Row; @@ -213,14 +215,11 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { } } arrayList.remove(exception); - if (arrayList.isEmpty() && arrayList == exceptions) { - listView.getAdapter().notifyItemRemoved(exceptionsSection2Row); - listView.getAdapter().notifyItemChanged(groupSection2Row); + if (exceptionsAddRow != -1 && arrayList.isEmpty() && arrayList == exceptions) { + listView.getAdapter().notifyItemChanged(exceptionsAddRow); } listView.getAdapter().notifyItemRemoved(position); - if (arrayList.isEmpty() && arrayList == exceptions) { - listView.getAdapter().notifyItemRemoved(exceptionsSectionRow); - } + updateRows(); checkRowsEnabled(); } else { @@ -238,7 +237,30 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { }); return; } - if (position == alertRow) { + if (position == exceptionsAddRow) { + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + if (currentType == NotificationsController.TYPE_GROUP) { + args.putInt("dialogsType", 2); + } else if (currentType == NotificationsController.TYPE_CHANNEL) { + args.putInt("dialogsType", 5); + } else { + args.putInt("dialogsType", 4); + } + DialogsActivity activity = new DialogsActivity(args); + activity.setDelegate((fragment, dids, message, param) -> { + Bundle args2 = new Bundle(); + args2.putLong("dialog_id", dids.get(0)); + args2.putBoolean("exception", true); + ProfileNotificationsActivity profileNotificationsActivity = new ProfileNotificationsActivity(args2); + profileNotificationsActivity.setDelegate(exception -> { + exceptions.add(0, exception); + updateRows(); + }); + presentFragment(profileNotificationsActivity, true); + }); + presentFragment(activity); + } else if (position == alertRow) { enabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(currentType); NotificationsCheckCell checkCell = (NotificationsCheckCell) view; @@ -481,6 +503,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { messagePriorityRow = -1; } groupSection2Row = rowCount++; + exceptionsAddRow = rowCount++; } else { alertRow = -1; alertSection2Row = -1; @@ -492,21 +515,19 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { messageSoundRow = -1; messagePriorityRow = -1; groupSection2Row = -1; + exceptionsAddRow = -1; } if (exceptions != null && !exceptions.isEmpty()) { - if (currentType != -1) { - exceptionsSectionRow = rowCount++; - } else { - exceptionsSectionRow = -1; - } exceptionsStartRow = rowCount; rowCount += exceptions.size(); exceptionsEndRow = rowCount; - exceptionsSection2Row = rowCount++; } else { - exceptionsSectionRow = -1; exceptionsStartRow = -1; exceptionsEndRow = -1; + } + if (currentType != -1 || exceptions != null && !exceptions.isEmpty()) { + exceptionsSection2Row = rowCount++; + } else { exceptionsSection2Row = -1; } } @@ -725,7 +746,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = new ProfileSearchCell(mContext); + View view = new UserCell(mContext, 9, 0, false); view.setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), 0); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); return new RecyclerListView.Holder(view); @@ -733,8 +754,8 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - ProfileSearchCell cell = (ProfileSearchCell) holder.itemView; - cell.setException(searchResult.get(position), searchResultNames.get(position)); + UserCell cell = (UserCell) holder.itemView; + cell.setException(searchResult.get(position), searchResultNames.get(position), position != searchResult.size() - 1); } @Override @@ -775,8 +796,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 2: - view = new ProfileSearchCell(mContext); - view.setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), 0); + view = new UserCell(mContext, 6, 0, false); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 3: @@ -791,10 +811,14 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 6: - default: view = new NotificationsCheckCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 7: + default: + view = new TextCell(mContext); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; } return new RecyclerListView.Holder(view); } @@ -806,8 +830,6 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { HeaderCell headerCell = (HeaderCell) holder.itemView; if (position == messageSectionRow) { headerCell.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS)); - } else if (position == exceptionsSectionRow) { - headerCell.setText(LocaleController.getString("NotificationsExceptions", R.string.NotificationsExceptions)); } break; } @@ -828,9 +850,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { break; } case 2: { - ProfileSearchCell cell = (ProfileSearchCell) holder.itemView; + UserCell cell = (UserCell) holder.itemView; NotificationsSettingsActivity.NotificationException exception = exceptions.get(position - exceptionsStartRow); - cell.setException(exception, null); + cell.setException(exception, null, position != exceptionsEndRow - 1); break; } case 3: { @@ -972,6 +994,14 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { checkCell.setTextAndValueAndCheck(text, builder, enabled, iconType, false); break; } + case 7: { + TextCell textCell = (TextCell) holder.itemView; + textCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); + if (position == exceptionsAddRow) { + textCell.setTextAndIcon(LocaleController.getString("NotificationsAddAnException", R.string.NotificationsAddAnException), R.drawable.actions_addmember2, exceptionsStartRow != -1); + } + break; + } } } @@ -1011,7 +1041,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { @Override public int getItemViewType(int position) { - if (position == messageSectionRow || position == exceptionsSectionRow) { + if (position == messageSectionRow) { return 0; } else if (position == previewRow) { return 1; @@ -1023,6 +1053,8 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { return 4; } else if (position == alertRow) { return 6; + } else if (position == exceptionsAddRow) { + return 7; } else { return 5; } @@ -1036,15 +1068,15 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { int count = listView.getChildCount(); for (int a = 0; a < count; a++) { View child = listView.getChildAt(a); - if (child instanceof ProfileSearchCell) { - ((ProfileSearchCell) child).update(0); + if (child instanceof UserCell) { + ((UserCell) child).update(0); } } } }; return new ThemeDescription[]{ - new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{HeaderCell.class, TextCheckCell.class, TextColorCell.class, TextSettingsCell.class, ProfileSearchCell.class, NotificationsCheckCell.class}, null, null, null, Theme.key_windowBackgroundWhite), + new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{HeaderCell.class, TextCheckCell.class, TextColorCell.class, TextSettingsCell.class, UserCell.class, NotificationsCheckCell.class}, null, null, null, Theme.key_windowBackgroundWhite), new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), @@ -1064,11 +1096,18 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrack), new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrackChecked), - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_namePaint, null, cellDelegate, Theme.key_chats_name), - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_nameEncryptedPaint, null, cellDelegate, Theme.key_chats_secretName), - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, cellDelegate, Theme.key_chats_secretIcon), - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, cellDelegate, Theme.key_chats_nameIcon), - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_offlinePaint, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText3), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink), new ThemeDescription(listView, 0, new Class[]{NotificationsCheckCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{NotificationsCheckCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2), @@ -1081,6 +1120,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { new ThemeDescription(listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteValueText), new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + + new ThemeDescription(listView, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueButton), + new ThemeDescription(listView, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueIcon), }; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index aa5cbc23d..063d0d7c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -114,6 +114,57 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif @Override public boolean onFragmentCreate() { MessagesController.getInstance(currentAccount).loadSignUpNotificationsSettings(); + loadExceptions(); + + notificationsSectionRow = rowCount++; + privateRow = rowCount++; + groupRow = rowCount++; + channelsRow = rowCount++; + notificationsSection2Row = rowCount++; + + callsSectionRow = rowCount++; + callsVibrateRow = rowCount++; + callsRingtoneRow = rowCount++; + eventsSection2Row = rowCount++; + + badgeNumberSection = rowCount++; + badgeNumberShowRow = rowCount++; + badgeNumberMutedRow = rowCount++; + badgeNumberMessagesRow = rowCount++; + badgeNumberSection2Row = rowCount++; + + inappSectionRow = rowCount++; + inappSoundRow = rowCount++; + inappVibrateRow = rowCount++; + inappPreviewRow = rowCount++; + inchatSoundRow = rowCount++; + if (Build.VERSION.SDK_INT >= 21) { + inappPriorityRow = rowCount++; + } else { + inappPriorityRow = -1; + } + callsSection2Row = rowCount++; + + eventsSectionRow = rowCount++; + contactJoinedRow = rowCount++; + pinnedMessageRow = rowCount++; + otherSection2Row = rowCount++; + + otherSectionRow = rowCount++; + notificationsServiceRow = rowCount++; + notificationsServiceConnectionRow = rowCount++; + androidAutoAlertRow = -1; + repeatRow = rowCount++; + resetSection2Row = rowCount++; + resetSectionRow = rowCount++; + resetNotificationsRow = rowCount++; + + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.notificationsSettingsUpdated); + + return super.onFragmentCreate(); + } + + private void loadExceptions() { MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { ArrayList usersResult = new ArrayList<>(); ArrayList chatsResult = new ArrayList<>(); @@ -258,53 +309,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif adapter.notifyItemChanged(channelsRow); }); }); - - notificationsSectionRow = rowCount++; - privateRow = rowCount++; - groupRow = rowCount++; - channelsRow = rowCount++; - notificationsSection2Row = rowCount++; - - callsSectionRow = rowCount++; - callsVibrateRow = rowCount++; - callsRingtoneRow = rowCount++; - eventsSection2Row = rowCount++; - - badgeNumberSection = rowCount++; - badgeNumberShowRow = rowCount++; - badgeNumberMutedRow = rowCount++; - badgeNumberMessagesRow = rowCount++; - badgeNumberSection2Row = rowCount++; - - inappSectionRow = rowCount++; - inappSoundRow = rowCount++; - inappVibrateRow = rowCount++; - inappPreviewRow = rowCount++; - inchatSoundRow = rowCount++; - if (Build.VERSION.SDK_INT >= 21) { - inappPriorityRow = rowCount++; - } else { - inappPriorityRow = -1; - } - callsSection2Row = rowCount++; - - eventsSectionRow = rowCount++; - contactJoinedRow = rowCount++; - pinnedMessageRow = rowCount++; - otherSection2Row = rowCount++; - - otherSectionRow = rowCount++; - notificationsServiceRow = rowCount++; - notificationsServiceConnectionRow = rowCount++; - androidAutoAlertRow = -1; - repeatRow = rowCount++; - resetSection2Row = rowCount++; - resetSectionRow = rowCount++; - resetNotificationsRow = rowCount++; - - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.notificationsSettingsUpdated); - - return super.onFragmentCreate(); } @Override @@ -376,24 +380,22 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif try { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); - tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, position == callsRingtoneRow ? RingtoneManager.TYPE_RINGTONE : RingtoneManager.TYPE_NOTIFICATION); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); - tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(position == callsRingtoneRow ? RingtoneManager.TYPE_RINGTONE : RingtoneManager.TYPE_NOTIFICATION)); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)); Uri currentSound = null; String defaultPath = null; - Uri defaultUri = position == callsRingtoneRow ? Settings.System.DEFAULT_RINGTONE_URI : Settings.System.DEFAULT_NOTIFICATION_URI; + Uri defaultUri = Settings.System.DEFAULT_RINGTONE_URI; if (defaultUri != null) { defaultPath = defaultUri.getPath(); } - if (position == callsRingtoneRow) { - String path = preferences.getString("CallsRingtonfePath", defaultPath); - if (path != null && !path.equals("NoSound")) { - if (path.equals(defaultPath)) { - currentSound = defaultUri; - } else { - currentSound = Uri.parse(path); - } + String path = preferences.getString("CallsRingtonePath", defaultPath); + if (path != null && !path.equals("NoSound")) { + if (path.equals(defaultPath)) { + currentSound = defaultUri; + } else { + currentSound = Uri.parse(path); } } tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, currentSound); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index f6c2dd4c0..7a336222d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -967,8 +967,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen return; } int addedCount = 0; + int oldCount = searchResult.size(); if (response != null) { - boolean added = false; TLRPC.TL_messages_foundGifs res = (TLRPC.TL_messages_foundGifs) response; nextGiphySearchOffset = res.next_offset; for (int a = 0; a < res.results.size(); a++) { @@ -976,7 +976,6 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (searchResultKeys.containsKey(gif.url)) { continue; } - added = true; MediaController.SearchImage bingImage = new MediaController.SearchImage(); bingImage.id = gif.url; if (gif.document != null) { @@ -1009,11 +1008,11 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen addedCount++; searchResultKeys.put(bingImage.id, bingImage); } - giphySearchEndReached = !added; + giphySearchEndReached = oldCount == searchResult.size(); } searching = false; if (addedCount != 0) { - listAdapter.notifyItemRangeInserted(searchResult.size(), addedCount); + listAdapter.notifyItemRangeInserted(oldCount, addedCount); } else if (giphySearchEndReached) { listAdapter.notifyItemRemoved(searchResult.size() - 1); } @@ -1097,10 +1096,10 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen return; } int addedCount = 0; + int oldCount = searchResult.size(); if (response != null) { TLRPC.messages_BotResults res = (TLRPC.messages_BotResults) response; nextImagesSearchOffset = res.next_offset; - boolean added = false; for (int a = 0, count = res.results.size(); a < count; a++) { TLRPC.BotInlineResult result = res.results.get(a); @@ -1111,7 +1110,6 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen continue; } - added = true; MediaController.SearchImage bingImage = new MediaController.SearchImage(); if (result.photo != null) { TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, AndroidUtilities.getPhotoSize()); @@ -1154,13 +1152,12 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen searchResultKeys.put(bingImage.id, bingImage); addedCount++; - added = true; } - bingSearchEndReached = !added || nextImagesSearchOffset == null; + bingSearchEndReached = oldCount == searchResult.size() || nextImagesSearchOffset == null; } searching = false; if (addedCount != 0) { - listAdapter.notifyItemRangeInserted(searchResult.size(), addedCount); + listAdapter.notifyItemRangeInserted(oldCount, addedCount); } else if (bingSearchEndReached) { listAdapter.notifyItemRemoved(searchResult.size() - 1); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 8e9d90951..dd22f7219 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -5952,7 +5952,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } SecureDocument document = secureDocuments.get(index); int imageSize = document.secureFile.size; - imageReceiver.setImage(document, null, "d", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, null, null, imageSize, null, null, 0); + imageReceiver.setImage(document, "d", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, null, null, imageSize, null, null, 0); } } else if (!imagesArrLocals.isEmpty()) { if (index >= 0 && index < imagesArrLocals.size()) { @@ -6036,9 +6036,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (document != null) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - imageReceiver.setImage(document, null, "d", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumb : null, String.format(Locale.US, "%d_%d", size, size), imageSize, null, object, cacheType); + imageReceiver.setImage(document, "d", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumb : null, String.format(Locale.US, "%d_%d", size, size), imageSize, null, object, cacheType); } else if (photo != null) { - imageReceiver.setImage(photo, null, filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, null, String.format(Locale.US, "%d_%d", size, size), imageSize, null, object, cacheType); + imageReceiver.setImage(photo, filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, null, String.format(Locale.US, "%d_%d", size, size), imageSize, null, object, cacheType); } else if (webDocument != null) { imageReceiver.setImage(webDocument, filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : (isVideo && parentActivity != null ? parentActivity.getResources().getDrawable(R.drawable.nophotos) : null), null, object, cacheType); } else { @@ -6065,7 +6065,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeHolder = currentThumb; } TLRPC.PhotoSize thumbLocation = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100); - imageReceiver.setImage(null, null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", 0, null, messageObject, 1); + imageReceiver.setImage(null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", 0, null, messageObject, 1); } else { imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder)); } @@ -6083,7 +6083,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeHolder = currentThumb; } TLRPC.PhotoSize thumbLocation = messageObject != null ? FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100) : null; - imageReceiver.setImage(document, null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", document.size, null, messageObject, 0); + imageReceiver.setImage(document, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", document.size, null, messageObject, 0); } else { OtherDocumentPlaceholderDrawable drawable = new OtherDocumentPlaceholderDrawable(parentActivity, containerView, messageObject); imageReceiver.setImageBitmap(drawable); @@ -6108,7 +6108,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat thumbLocation = null; } boolean cacheOnly = messageObject != null && messageObject.isWebpage() || avatarsDialogId != 0 || isEvent; - imageReceiver.setImage(fileLocation, null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", size[0], null, messageObject, cacheOnly ? 1 : 0); + imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", size[0], null, messageObject, cacheOnly ? 1 : 0); } else { imageReceiver.setNeedsQualityThumb(true); if (size[0] == 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 099189ea0..0a60d747f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -1045,6 +1045,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. nameTextView[a].setPivotX(0); nameTextView[a].setPivotY(0); nameTextView[a].setAlpha(a == 0 ? 0.0f : 1.0f); + if (a == 1) { + nameTextView[a].setScrollNonFitText(true); + nameTextView[a].setBackgroundColor(AvatarDrawable.getProfileBackColorForId(user_id != 0 || ChatObject.isChannel(chat_id, currentAccount) && !currentChat.megagroup ? 5 : chat_id)); + } frameLayout.addView(nameTextView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, a == 0 ? 48 : 0, 0)); onlineTextView[a] = new SimpleTextView(context); @@ -2791,7 +2795,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (chat_id > 0) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chat_id); if (ChatObject.isChannel(chat)) { - if (ChatObject.hasAdminRights(chat)) { + if (ChatObject.hasAdminRights(chat) || ChatObject.canChangeChatInfo(chat)) { editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); } if (!chat.megagroup && chatInfo != null && chatInfo.can_view_stats) { @@ -3253,6 +3257,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. new ThemeDescription(topView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_avatar_actionBarSelectorBlue), new ThemeDescription(nameTextView[1], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_profile_title), + new ThemeDescription(nameTextView[1], ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), new ThemeDescription(onlineTextView[1], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_avatar_subtitleInProfileBlue), new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 139856898..2736b08fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -15,6 +15,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.graphics.drawable.Drawable; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; @@ -35,23 +36,28 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.RadioCell; +import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCheckBoxCell; +import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextColorCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; +import org.telegram.ui.Cells2.UserCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; @@ -66,12 +72,19 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi private long dialog_id; + private boolean addingException; + private boolean customEnabled; private boolean notificationsEnabled; + private ProfileNotificationsActivityDelegate delegate; + private int customRow; private int customInfoRow; private int generalRow; + private int avatarRow; + private int avatarSectionRow; + private int enableRow; private int soundRow; private int vibrateRow; private int smartRow; @@ -90,17 +103,38 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi private int ledInfoRow; private int rowCount; + private final static int done_button = 1; + + public interface ProfileNotificationsActivityDelegate { + void didCreateNewException(NotificationsSettingsActivity.NotificationException exception); + } + public ProfileNotificationsActivity(Bundle args) { super(args); dialog_id = args.getLong("dialog_id"); + addingException = args.getBoolean("exception", false); } @Override public boolean onFragmentCreate() { rowCount = 0; - customRow = rowCount++; - customInfoRow = rowCount++; + if (addingException) { + avatarRow = rowCount++; + avatarSectionRow = rowCount++; + customRow = -1; + customInfoRow = -1; + } else { + avatarRow = -1; + avatarSectionRow = -1; + customRow = rowCount++; + customInfoRow = rowCount++; + } generalRow = rowCount++; + if (addingException) { + enableRow = rowCount++; + } else { + enableRow = -1; + } soundRow = rowCount++; vibrateRow = rowCount++; if ((int) dialog_id < 0) { @@ -151,7 +185,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi ledInfoRow = rowCount++; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - customEnabled = preferences.getBoolean("custom_" + dialog_id, false); + customEnabled = preferences.getBoolean("custom_" + dialog_id, false) || addingException; boolean hasOverride = preferences.contains("notify2_" + dialog_id); int value = preferences.getInt("notify2_" + dialog_id, 0); @@ -183,19 +217,59 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi public View createView(final Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); - actionBar.setTitle(LocaleController.getString("CustomNotifications", R.string.CustomNotifications)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(int id) { if (id == -1) { - if (notificationsEnabled && customEnabled) { + if (!addingException && notificationsEnabled && customEnabled) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().putInt("notify2_" + dialog_id, 0).commit(); } - finishFragment(); + } else if (id == done_button) { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("custom_" + dialog_id, true); + + + TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); + if (notificationsEnabled) { + editor.putInt("notify2_" + dialog_id, 0); + MessagesStorage.getInstance(currentAccount).setDialogFlags(dialog_id, 0); + if (dialog != null) { + dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); + } + } else { + editor.putInt("notify2_" + dialog_id, 2); + NotificationsController.getInstance(currentAccount).removeNotificationsForDialog(dialog_id); + MessagesStorage.getInstance(currentAccount).setDialogFlags(dialog_id, 1); + if (dialog != null) { + dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); + dialog.notify_settings.mute_until = Integer.MAX_VALUE; + } + } + + editor.commit(); + NotificationsController.getInstance(currentAccount).updateServerNotificationsSettings(dialog_id); + if (delegate != null) { + NotificationsSettingsActivity.NotificationException exception = new NotificationsSettingsActivity.NotificationException(); + exception.did = dialog_id; + exception.hasCustom = true; + exception.notify = preferences.getInt("notify2_" + dialog_id, 0); + if (exception.notify != 0) { + exception.muteUntil = preferences.getInt("notifyuntil_" + dialog_id, 0); + } + delegate.didCreateNewException(exception); + } } + finishFragment(); } }); + if (addingException) { + actionBar.setTitle(LocaleController.getString("NotificationsNewException", R.string.NotificationsNewException)); + actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + } else { + actionBar.setTitle(LocaleController.getString("CustomNotifications", R.string.CustomNotifications)); + } fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; @@ -335,6 +409,10 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi adapter.notifyItemChanged(vibrateRow); } })); + } else if (position == enableRow) { + TextCheckCell checkCell = (TextCheckCell) view; + notificationsEnabled = !checkCell.isChecked(); + checkCell.setChecked(notificationsEnabled); } else if (position == callsVibrateRow) { showDialog(AlertsCreator.createVibrationSelectDialog(getParentActivity(), dialog_id, "calls_vibrate_", () -> { if (adapter != null) { @@ -525,6 +603,10 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } } + public void setDelegate(ProfileNotificationsActivityDelegate profileNotificationsActivityDelegate) { + delegate = profileNotificationsActivityDelegate; + } + private class ListAdapter extends RecyclerView.Adapter { private Context context; @@ -562,10 +644,21 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 5: - default: view = new TextCheckBoxCell(context); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 6: + view = new UserCell(context, 4, 0); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; + case 7: + view = new ShadowSectionCell(context); + break; + case 8: + default: + view = new TextCheckCell(context); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); return new RecyclerListView.Holder(view); @@ -722,6 +815,26 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi cell.setTextAndCheck(LocaleController.getString("NotificationsEnableCustom", R.string.NotificationsEnableCustom), customEnabled && notificationsEnabled, false); break; } + case 6: { + UserCell userCell = (UserCell) holder.itemView; + int lower_id = (int) dialog_id; + TLObject object; + if (lower_id > 0) { + object = MessagesController.getInstance(currentAccount).getUser(lower_id); + } else { + object = MessagesController.getInstance(currentAccount).getChat(-lower_id); + } + userCell.setData(object, null, null, 0); + break; + } + case 8: { + TextCheckCell checkCell = (TextCheckCell) holder.itemView; + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + if (position == enableRow) { + checkCell.setTextAndCheck(LocaleController.getString("Notifications", R.string.Notifications), notificationsEnabled, true); + } + break; + } } } @@ -767,6 +880,12 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi return 4; } else if (position == customRow) { return 5; + } else if (position == avatarRow) { + return 6; + } else if (position == avatarSectionRow) { + return 7; + } else if (position == enableRow) { + return 8; } return 0; } @@ -774,8 +893,20 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi @Override public ThemeDescription[] getThemeDescriptions() { + ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> { + if (listView != null) { + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = listView.getChildAt(a); + if (child instanceof UserCell) { + ((UserCell) child).update(0); + } + } + } + }; + return new ThemeDescription[]{ - new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{HeaderCell.class, TextSettingsCell.class, TextColorCell.class, RadioCell.class, TextCheckBoxCell.class}, null, null, null, Theme.key_windowBackgroundWhite), + new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{HeaderCell.class, TextSettingsCell.class, TextColorCell.class, RadioCell.class, UserCell.class, TextCheckCell.class, TextCheckBoxCell.class}, null, null, null, Theme.key_windowBackgroundWhite), new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), @@ -803,6 +934,25 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi new ThemeDescription(listView, ThemeDescription.FLAG_CHECKBOX, new Class[]{RadioCell.class}, new String[]{"radioButton"}, null, null, null, Theme.key_radioBackground), new ThemeDescription(listView, ThemeDescription.FLAG_CHECKBOXCHECK, new Class[]{RadioCell.class}, new String[]{"radioButton"}, null, null, null, Theme.key_radioBackgroundChecked), + new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + + new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2), + new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrack), + new ThemeDescription(listView, 0, new Class[]{TextCheckCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_switchTrackChecked), + + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue), + new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink), + new ThemeDescription(listView, 0, new Class[]{TextCheckBoxCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{TextCheckBoxCell.class}, null, null, null, Theme.key_checkboxSquareUnchecked), new ThemeDescription(listView, 0, new Class[]{TextCheckBoxCell.class}, null, null, null, Theme.key_checkboxSquareDisabled), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index 142cb27c1..6001e2081 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -356,7 +356,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } else if (position == dataRow) { presentFragment(new DataSettingsActivity()); } else if (position == chatRow) { - presentFragment(new ChatSettingsActivity()); + presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC)); } else if (position == helpRow) { BottomSheet.Builder builder = new BottomSheet.Builder(context); builder.setApplyTopPadding(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java index d3a34b72c..48f9a8ac7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java @@ -15,6 +15,12 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.location.Address; import android.location.Geocoder; import android.location.Location; @@ -26,8 +32,10 @@ import android.os.Bundle; import android.os.Vibrator; import android.support.v4.content.FileProvider; import android.text.InputType; +import android.text.TextPaint; import android.util.TypedValue; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; @@ -39,24 +47,33 @@ import android.widget.Toast; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildConfig; +import org.telegram.messenger.DataQuery; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.support.widget.DefaultItemAnimator; import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.time.SunDate; +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.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.BrightnessControlCell; +import org.telegram.ui.Cells.ChatMessageCell; +import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCheckCell; @@ -67,6 +84,7 @@ import org.telegram.ui.Cells.ThemeTypeCell; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SeekBarView; import org.telegram.ui.Components.ThemeEditorView; import java.io.File; @@ -84,6 +102,25 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private ListAdapter listAdapter; private RecyclerListView listView; + private int backgroundRow; + private int textSizeHeaderRow; + private int textSizeRow; + private int settingsRow; + private int customTabsRow; + private int directShareRow; + private int raiseToSpeakRow; + private int sendByEnterRow; + private int autoplayGifsRow; + private int saveToGalleryRow; + private int enableAnimationsRow; + private int settings2Row; + private int stickersRow; + private int stickersSection2Row; + + private int emojiRow; + private int contactsReimportRow; + private int contactsSortRow; + private int nightThemeRow; private int nightDisabledRow; private int nightScheduledRow; @@ -100,8 +137,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int automaticBrightnessRow; private int automaticBrightnessInfoRow; private int preferedHeaderRow; - private int newThemeRow; private int newThemeInfoRow; + private int themeHeaderRow; private int themeStartRow; private int themeEndRow; private int themeInfoRow; @@ -115,6 +152,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private GpsLocationListener gpsLocationListener = new GpsLocationListener(); private GpsLocationListener networkLocationListener = new GpsLocationListener(); + private final static int create_theme = 1; + private class GpsLocationListener implements LocationListener { @Override @@ -142,6 +181,207 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } } + public interface SizeChooseViewDelegate { + void onSizeChanged(); + } + + private class TextSizeCell extends FrameLayout { + + private LinearLayout messagesContainer; + private ChatMessageCell[] cells = new ChatMessageCell[2]; + private SeekBarView sizeBar; + private Drawable shadowDrawable; + private int startFontSize = 12; + private int endFontSize = 30; + private int lastWidth; + + private TextPaint textPaint; + + public TextSizeCell(Context context) { + super(context); + + setWillNotDraw(false); + + textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + textPaint.setTextSize(AndroidUtilities.dp(16)); + + shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow); + + sizeBar = new SeekBarView(context); + sizeBar.setReportChanges(true); + sizeBar.setDelegate(progress -> { + int fontSize = Math.round(startFontSize + (endFontSize - startFontSize) * progress); + if (fontSize != SharedConfig.fontSize) { + SharedConfig.fontSize = fontSize; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt("fons_size", SharedConfig.fontSize); + editor.commit(); + Theme.chat_msgTextPaint.setTextSize(AndroidUtilities.dp(SharedConfig.fontSize)); + for (int a = 0; a < cells.length; a++) { + cells[a].getMessageObject().resetLayout(); + cells[a].requestLayout(); + } + } + }); + addView(sizeBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.LEFT | Gravity.TOP, 9, 5, 43, 0)); + + messagesContainer = new LinearLayout(context) { + + private Drawable backgroundDrawable; + + @Override + protected void onDraw(Canvas canvas) { + Drawable newDrawable = Theme.getCachedWallpaperNonBlocking(); + if (newDrawable != null) { + backgroundDrawable = newDrawable; + } + if (backgroundDrawable instanceof ColorDrawable) { + backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + backgroundDrawable.draw(canvas); + } else if (backgroundDrawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable; + if (bitmapDrawable.getTileModeX() == Shader.TileMode.REPEAT) { + canvas.save(); + float scale = 2.0f / AndroidUtilities.density; + canvas.scale(scale, scale); + backgroundDrawable.setBounds(0, 0, (int) Math.ceil(getMeasuredWidth() / scale), (int) Math.ceil(getMeasuredHeight() / scale)); + backgroundDrawable.draw(canvas); + canvas.restore(); + } else { + int viewHeight = getMeasuredHeight(); + float scaleX = (float) getMeasuredWidth() / (float) backgroundDrawable.getIntrinsicWidth(); + float scaleY = (float) (viewHeight) / (float) backgroundDrawable.getIntrinsicHeight(); + float scale = scaleX < scaleY ? scaleY : scaleX; + int width = (int) Math.ceil(backgroundDrawable.getIntrinsicWidth() * scale); + int height = (int) Math.ceil(backgroundDrawable.getIntrinsicHeight() * scale); + int x = (getMeasuredWidth() - width) / 2; + int y = (viewHeight - height) / 2; + canvas.save(); + canvas.clipRect(0, 0, width, getMeasuredHeight()); + backgroundDrawable.setBounds(x, y, x + width, y + height); + backgroundDrawable.draw(canvas); + canvas.restore(); + } + } else { + super.onDraw(canvas); + } + + shadowDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + shadowDrawable.draw(canvas); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return false; + } + + @Override + protected void dispatchSetPressed(boolean pressed) { + + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return false; + } + }; + messagesContainer.setOrientation(LinearLayout.VERTICAL); + messagesContainer.setWillNotDraw(false); + messagesContainer.setPadding(0, AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11)); + addView(messagesContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 53, 0, 0)); + + int date = (int) (System.currentTimeMillis() / 1000) - 60 * 60; + TLRPC.Message message = new TLRPC.TL_message(); + message.message = LocaleController.getString("FontSizePreviewReply", R.string.FontSizePreviewReply); + message.date = date + 60; + message.dialog_id = 1; + message.flags = 259; + message.from_id = UserConfig.getInstance(currentAccount).getClientUserId(); + message.id = 1; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = true; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = 0; + MessageObject replyMessageObject = new MessageObject(currentAccount, message, true); + + message = new TLRPC.TL_message(); + message.message = LocaleController.getString("FontSizePreviewLine2", R.string.FontSizePreviewLine2); + message.date = date + 960; + message.dialog_id = 1; + message.flags = 259; + message.from_id = UserConfig.getInstance(currentAccount).getClientUserId(); + message.id = 1; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = true; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = 0; + MessageObject message1 = new MessageObject(currentAccount, message, true); + message1.resetLayout(); + message1.eventId = 1; + + message = new TLRPC.TL_message(); + message.message = LocaleController.getString("FontSizePreviewLine1", R.string.FontSizePreviewLine1); + message.date = date + 60; + message.dialog_id = 1; + message.flags = 257 + 8; + message.from_id = 0; + message.id = 1; + message.reply_to_msg_id = 5; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = false; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); + MessageObject message2 = new MessageObject(currentAccount, message, true); + message2.customReplyName = "Lucio"; + message2.eventId = 1; + message2.resetLayout(); + message2.replyMessageObject = replyMessageObject; + + for (int a = 0; a < cells.length; a++) { + cells[a] = new ChatMessageCell(context); + cells[a].setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + + }); + cells[a].isChat = false; + cells[a].setFullyDraw(true); + cells[a].setMessageObject(a == 0 ? message2 : message1, null, false, false); + messagesContainer.addView(cells[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + } + + @Override + protected void onDraw(Canvas canvas) { + textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + canvas.drawText("" + SharedConfig.fontSize, getMeasuredWidth() - AndroidUtilities.dp(39), AndroidUtilities.dp(28), textPaint); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int w = MeasureSpec.getSize(widthMeasureSpec); + if (lastWidth != w) { + sizeBar.setProgress((SharedConfig.fontSize - startFontSize) / (float) (endFontSize - startFontSize)); + lastWidth = w; + } + } + + @Override + public void invalidate() { + super.invalidate(); + messagesContainer.invalidate(); + sizeBar.invalidate(); + for (int a = 0; a < cells.length; a++) { + cells[a].invalidate(); + } + } + } + private int currentType; public ThemeActivity(int type) { @@ -154,6 +394,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No int oldRowCount = rowCount; rowCount = 0; + emojiRow = -1; + contactsReimportRow = -1; + contactsSortRow = -1; scheduleLocationRow = -1; scheduleUpdateLocationRow = -1; scheduleLocationInfoRow = -1; @@ -163,7 +406,6 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No nightTypeInfoRow = -1; scheduleHeaderRow = -1; nightThemeRow = -1; - newThemeRow = -1; newThemeInfoRow = -1; scheduleFromRow = -1; scheduleToRow = -1; @@ -175,15 +417,46 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No automaticHeaderRow = -1; automaticBrightnessRow = -1; automaticBrightnessInfoRow = -1; + textSizeHeaderRow = -1; + themeHeaderRow = -1; + + textSizeRow = -1; + backgroundRow = -1; + settingsRow = -1; + customTabsRow = -1; + directShareRow = -1; + enableAnimationsRow = -1; + raiseToSpeakRow = -1; + sendByEnterRow = -1; + autoplayGifsRow = -1; + saveToGalleryRow = -1; + settings2Row = -1; + stickersRow = -1; + stickersSection2Row = -1; if (currentType == THEME_TYPE_BASIC) { + textSizeHeaderRow = rowCount++; + textSizeRow = rowCount++; + backgroundRow = rowCount++; nightThemeRow = rowCount++; - newThemeRow = rowCount++; newThemeInfoRow = rowCount++; + themeHeaderRow = rowCount++; themeStartRow = rowCount; rowCount += Theme.themes.size(); themeEndRow = rowCount; themeInfoRow = rowCount++; + + settingsRow = rowCount++; + customTabsRow = rowCount++; + directShareRow = rowCount++; + enableAnimationsRow = rowCount++; + raiseToSpeakRow = rowCount++; + sendByEnterRow = rowCount++; + autoplayGifsRow = rowCount++; + saveToGalleryRow = rowCount++; + settings2Row = rowCount++; + stickersRow = rowCount++; + stickersSection2Row = rowCount++; } else { nightDisabledRow = rowCount++; nightScheduledRow = rowCount++; @@ -262,6 +535,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override public boolean onFragmentCreate() { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.locationPermissionGranted); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper); return super.onFragmentCreate(); } @@ -270,6 +544,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No super.onFragmentDestroy(); stopLocationUpdate(); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.locationPermissionGranted); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper); Theme.saveAutoNightThemeConfig(); } @@ -277,6 +552,10 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.locationPermissionGranted) { updateSunTime(null, true); + } else if (id == NotificationCenter.didSetNewWallpapper) { + if (listView != null) { + listView.invalidateViews(); + } } } @@ -284,8 +563,14 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(false); + if (AndroidUtilities.isTablet()) { + actionBar.setOccupyStatusBar(false); + } if (currentType == THEME_TYPE_BASIC) { - actionBar.setTitle(LocaleController.getString("Theme", R.string.Theme)); + actionBar.setTitle(LocaleController.getString("ChatSettings", R.string.ChatSettings)); + ActionBarMenu menu = actionBar.createMenu(); + ActionBarMenuItem item = menu.addItem(0, R.drawable.ic_ab_other); + item.addSubItem(create_theme, LocaleController.getString("CreateNewThemeMenu", R.string.CreateNewThemeMenu)); } else { actionBar.setTitle(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme)); } @@ -295,6 +580,16 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No public void onItemClick(int id) { if (id == -1) { finishFragment(); + } else if (id == create_theme) { + if (getParentActivity() == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("NewTheme", R.string.NewTheme)); + builder.setMessage(LocaleController.getString("CreateNewThemeAlert", R.string.CreateNewThemeAlert)); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setPositiveButton(LocaleController.getString("CreateTheme", R.string.CreateTheme), (dialog, which) -> openThemeCreate()); + showDialog(builder.create()); } } }); @@ -312,99 +607,149 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setOnItemClickListener((view, position) -> { - if (position == newThemeRow) { + if (position == enableAnimationsRow) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + boolean animations = preferences.getBoolean("view_animations", true); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("view_animations", !animations); + editor.commit(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(!animations); + } + } else if (position == backgroundRow) { + presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL)); + } else if (position == sendByEnterRow) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + boolean send = preferences.getBoolean("send_by_enter", false); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("send_by_enter", !send); + editor.commit(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(!send); + } + } else if (position == raiseToSpeakRow) { + SharedConfig.toogleRaiseToSpeak(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(SharedConfig.raiseToSpeak); + } + } else if (position == autoplayGifsRow) { + SharedConfig.toggleAutoplayGifs(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(SharedConfig.autoplayGifs); + } + } else if (position == saveToGalleryRow) { + SharedConfig.toggleSaveToGallery(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(SharedConfig.saveToGallery); + } + } else if (position == customTabsRow) { + SharedConfig.toggleCustomTabs(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(SharedConfig.customTabs); + } + } else if (position == directShareRow) { + SharedConfig.toggleDirectShare(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(SharedConfig.directShare); + } + } else if (position == contactsReimportRow) { + //not implemented + } else if (position == contactsSortRow) { if (getParentActivity() == null) { return; } - final EditTextBoldCursor editText = new EditTextBoldCursor(getParentActivity()); - editText.setBackgroundDrawable(Theme.createEditTextDrawable(getParentActivity(), true)); - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("NewTheme", R.string.NewTheme)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { - + builder.setTitle(LocaleController.getString("SortBy", R.string.SortBy)); + builder.setItems(new CharSequence[]{ + LocaleController.getString("Default", R.string.Default), + LocaleController.getString("SortFirstName", R.string.SortFirstName), + LocaleController.getString("SortLastName", R.string.SortLastName) + }, (dialog, which) -> { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt("sortContactsBy", which); + editor.commit(); + if (listAdapter != null) { + listAdapter.notifyItemChanged(position); + } }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + } else if (position == stickersRow) { + presentFragment(new StickersActivity(DataQuery.TYPE_IMAGE)); + } else if (position == emojiRow) { + if (getParentActivity() == null) { + return; + } + final boolean maskValues[] = new boolean[2]; + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); + builder.setApplyTopPadding(false); + builder.setApplyBottomPadding(false); LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(LinearLayout.VERTICAL); - builder.setView(linearLayout); - - final TextView message = new TextView(getParentActivity()); - message.setText(LocaleController.formatString("EnterThemeName", R.string.EnterThemeName)); - message.setTextSize(16); - message.setPadding(AndroidUtilities.dp(23), AndroidUtilities.dp(12), AndroidUtilities.dp(23), AndroidUtilities.dp(6)); - message.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - linearLayout.addView(message, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - editText.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - editText.setMaxLines(1); - editText.setLines(1); - editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); - editText.setGravity(Gravity.LEFT | Gravity.TOP); - editText.setSingleLine(true); - editText.setImeOptions(EditorInfo.IME_ACTION_DONE); - editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - editText.setCursorSize(AndroidUtilities.dp(20)); - editText.setCursorWidth(1.5f); - editText.setPadding(0, AndroidUtilities.dp(4), 0, 0); - linearLayout.addView(editText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, Gravity.TOP | Gravity.LEFT, 24, 6, 24, 0)); - editText.setOnEditorActionListener((textView, i, keyEvent) -> { - AndroidUtilities.hideKeyboard(textView); - return false; - }); - final AlertDialog alertDialog = builder.create(); - alertDialog.setOnShowListener(dialog -> AndroidUtilities.runOnUIThread(() -> { - editText.requestFocus(); - AndroidUtilities.showKeyboard(editText); - })); - showDialog(alertDialog); - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> { - if (editText.length() == 0) { - Vibrator vibrator = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE); - if (vibrator != null) { - vibrator.vibrate(200); - } - AndroidUtilities.shakeView(editText, 2, 0); - return; + for (int a = 0; a < (Build.VERSION.SDK_INT >= 19 ? 2 : 1); a++) { + String name = null; + if (a == 0) { + maskValues[a] = SharedConfig.allowBigEmoji; + name = LocaleController.getString("EmojiBigSize", R.string.EmojiBigSize); + } else if (a == 1) { + maskValues[a] = SharedConfig.useSystemEmoji; + name = LocaleController.getString("EmojiUseDefault", R.string.EmojiUseDefault); } - ThemeEditorView themeEditorView = new ThemeEditorView(); - String name = editText.getText().toString() + ".attheme"; - themeEditorView.show(getParentActivity(), name); - Theme.saveCurrentTheme(name, true); - updateRows(); - alertDialog.dismiss(); - - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - if (preferences.getBoolean("themehint", false)) { - return; - } - preferences.edit().putBoolean("themehint", true).commit(); + CheckBoxCell checkBoxCell = new CheckBoxCell(getParentActivity(), 1, 21); + checkBoxCell.setTag(a); + checkBoxCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + linearLayout.addView(checkBoxCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); + checkBoxCell.setText(name, "", maskValues[a], true); + checkBoxCell.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + checkBoxCell.setOnClickListener(v -> { + CheckBoxCell cell = (CheckBoxCell) v; + int num = (Integer) cell.getTag(); + maskValues[num] = !maskValues[num]; + cell.setChecked(maskValues[num], true); + }); + } + BottomSheet.BottomSheetCell cell = new BottomSheet.BottomSheetCell(getParentActivity(), 1); + cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + cell.setTextAndIcon(LocaleController.getString("Save", R.string.Save).toUpperCase(), 0); + cell.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + cell.setOnClickListener(v -> { try { - Toast.makeText(getParentActivity(), LocaleController.getString("CreateNewThemeHelp", R.string.CreateNewThemeHelp), Toast.LENGTH_LONG).show(); + if (visibleDialog != null) { + visibleDialog.dismiss(); + } } catch (Exception e) { FileLog.e(e); } + SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); + editor.putBoolean("allowBigEmoji", SharedConfig.allowBigEmoji = maskValues[0]); + editor.putBoolean("useSystemEmoji", SharedConfig.useSystemEmoji = maskValues[1]); + editor.commit(); + if (listAdapter != null) { + listAdapter.notifyItemChanged(position); + } }); + linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); + builder.setCustomView(linearLayout); + showDialog(builder.create()); } else if (position >= themeStartRow && position < themeEndRow) { int p = position - themeStartRow; if (p >= 0 && p < Theme.themes.size()) { Theme.ThemeInfo themeInfo = Theme.themes.get(p); if (currentType == THEME_TYPE_BASIC) { - Theme.applyTheme(themeInfo); - if (parentLayout != null) { - parentLayout.rebuildAllFragmentViews(false, false); + if (themeInfo == Theme.getCurrentTheme()) { + return; } - finishFragment(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false); } else { Theme.setCurrentNightTheme(themeInfo); - int count = listView.getChildCount(); - for (int a = 0; a < count; a++) { - View child = listView.getChildAt(a); - if (child instanceof ThemeCell) { - ((ThemeCell) child).updateCurrentThemeCheck(); - } + } + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = listView.getChildAt(a); + if (child instanceof ThemeCell) { + ((ThemeCell) child).updateCurrentThemeCheck(); } } } @@ -475,6 +820,80 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } } + private void openThemeCreate() { + final EditTextBoldCursor editText = new EditTextBoldCursor(getParentActivity()); + editText.setBackgroundDrawable(Theme.createEditTextDrawable(getParentActivity(), true)); + + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("NewTheme", R.string.NewTheme)); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { + + }); + + LinearLayout linearLayout = new LinearLayout(getParentActivity()); + linearLayout.setOrientation(LinearLayout.VERTICAL); + builder.setView(linearLayout); + + final TextView message = new TextView(getParentActivity()); + message.setText(LocaleController.formatString("EnterThemeName", R.string.EnterThemeName)); + message.setTextSize(16); + message.setPadding(AndroidUtilities.dp(23), AndroidUtilities.dp(12), AndroidUtilities.dp(23), AndroidUtilities.dp(6)); + message.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + linearLayout.addView(message, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + editText.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + editText.setMaxLines(1); + editText.setLines(1); + editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); + editText.setGravity(Gravity.LEFT | Gravity.TOP); + editText.setSingleLine(true); + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + editText.setCursorSize(AndroidUtilities.dp(20)); + editText.setCursorWidth(1.5f); + editText.setPadding(0, AndroidUtilities.dp(4), 0, 0); + linearLayout.addView(editText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, Gravity.TOP | Gravity.LEFT, 24, 6, 24, 0)); + editText.setOnEditorActionListener((textView, i, keyEvent) -> { + AndroidUtilities.hideKeyboard(textView); + return false; + }); + final AlertDialog alertDialog = builder.create(); + alertDialog.setOnShowListener(dialog -> AndroidUtilities.runOnUIThread(() -> { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + })); + showDialog(alertDialog); + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> { + if (editText.length() == 0) { + Vibrator vibrator = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE); + if (vibrator != null) { + vibrator.vibrate(200); + } + AndroidUtilities.shakeView(editText, 2, 0); + return; + } + ThemeEditorView themeEditorView = new ThemeEditorView(); + String name = editText.getText().toString() + ".attheme"; + themeEditorView.show(getParentActivity(), name); + Theme.saveCurrentTheme(name, true); + updateRows(); + alertDialog.dismiss(); + + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + if (preferences.getBoolean("themehint", false)) { + return; + } + preferences.edit().putBoolean("themehint", true).commit(); + try { + Toast.makeText(getParentActivity(), LocaleController.getString("CreateNewThemeHelp", R.string.CreateNewThemeHelp), Toast.LENGTH_LONG).show(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + private void updateSunTime(Location lastKnownLocation, boolean forceUpdate) { LocationManager locationManager = (LocationManager) ApplicationLoader.applicationContext.getSystemService(Context.LOCATION_SERVICE); if (Build.VERSION.SDK_INT >= 23) { @@ -800,10 +1219,14 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 7: - default: view = new TextCheckCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 8: + default: + view = new TextSizeCell(mContext); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; } return new RecyclerListView.Holder(view); @@ -820,13 +1243,11 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } case 1: { TextSettingsCell cell = (TextSettingsCell) holder.itemView; - if (position == newThemeRow) { - cell.setText(LocaleController.getString("CreateNewTheme", R.string.CreateNewTheme), false); - } else if (position == nightThemeRow) { + if (position == nightThemeRow) { if (Theme.selectedAutoNightType == Theme.AUTO_NIGHT_TYPE_NONE || Theme.getCurrentNightTheme() == null) { - cell.setText(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), true); + cell.setTextAndValue(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), LocaleController.getString("AutoNightThemeOff", R.string.AutoNightThemeOff), false); } else { - cell.setTextAndValue(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), Theme.getCurrentNightThemeName(), true); + cell.setTextAndValue(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), Theme.getCurrentNightThemeName(), false); } } else if (position == scheduleFromRow) { int currentHour = Theme.autoNightDayStartTime / 60; @@ -838,14 +1259,32 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No cell.setTextAndValue(LocaleController.getString("AutoNightTo", R.string.AutoNightTo), String.format("%02d:%02d", currentHour, currentMinute), false); } else if (position == scheduleUpdateLocationRow) { cell.setTextAndValue(LocaleController.getString("AutoNightUpdateLocation", R.string.AutoNightUpdateLocation), Theme.autoNightCityName, false); + } else if (position == contactsSortRow) { + String value; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + int sort = preferences.getInt("sortContactsBy", 0); + if (sort == 0) { + value = LocaleController.getString("Default", R.string.Default); + } else if (sort == 1) { + value = LocaleController.getString("FirstName", R.string.SortFirstName); + } else { + value = LocaleController.getString("LastName", R.string.SortLastName); + } + cell.setTextAndValue(LocaleController.getString("SortBy", R.string.SortBy), value, true); + } else if (position == backgroundRow) { + cell.setText(LocaleController.getString("ChatBackground", R.string.ChatBackground), true); + } else if (position == contactsReimportRow) { + cell.setText(LocaleController.getString("ImportContacts", R.string.ImportContacts), true); + } else if (position == stickersRow) { + cell.setText(LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), false); + } else if (position == emojiRow) { + cell.setText(LocaleController.getString("Emoji", R.string.Emoji), true); } break; } case 2: { TextInfoPrivacyCell cell = (TextInfoPrivacyCell) holder.itemView; - if (position == newThemeInfoRow) { - cell.setText(LocaleController.getString("CreateNewThemeInfo", R.string.CreateNewThemeInfo)); - } else if (position == automaticBrightnessInfoRow) { + if (position == automaticBrightnessInfoRow) { cell.setText(LocaleController.formatString("AutoNightBrightnessInfo", R.string.AutoNightBrightnessInfo, (int) (100 * Theme.autoNightBrighnessThreshold))); } else if (position == scheduleLocationInfoRow) { cell.setText(getLocationSunString()); @@ -871,6 +1310,12 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No headerCell.setText(LocaleController.getString("AutoNightBrightness", R.string.AutoNightBrightness)); } else if (position == preferedHeaderRow) { headerCell.setText(LocaleController.getString("AutoNightPreferred", R.string.AutoNightPreferred)); + } else if (position == settingsRow) { + headerCell.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS)); + } else if (position == themeHeaderRow) { + headerCell.setText(LocaleController.getString("ColorTheme", R.string.ColorTheme)); + } else if (position == textSizeHeaderRow) { + headerCell.setText(LocaleController.getString("TextSizeHeader", R.string.TextSizeHeader)); } break; } @@ -883,6 +1328,22 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No TextCheckCell textCheckCell = (TextCheckCell) holder.itemView; if (position == scheduleLocationRow) { textCheckCell.setTextAndCheck(LocaleController.getString("AutoNightLocation", R.string.AutoNightLocation), Theme.autoNightScheduleByLocation, true); + } else if (position == enableAnimationsRow) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + textCheckCell.setTextAndCheck(LocaleController.getString("EnableAnimations", R.string.EnableAnimations), preferences.getBoolean("view_animations", true), true); + } else if (position == sendByEnterRow) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + textCheckCell.setTextAndCheck(LocaleController.getString("SendByEnter", R.string.SendByEnter), preferences.getBoolean("send_by_enter", false), true); + } else if (position == saveToGalleryRow) { + textCheckCell.setTextAndCheck(LocaleController.getString("SaveToGallerySettings", R.string.SaveToGallerySettings), SharedConfig.saveToGallery, false); + } else if (position == autoplayGifsRow) { + textCheckCell.setTextAndCheck(LocaleController.getString("AutoplayGifs", R.string.AutoplayGifs), SharedConfig.autoplayGifs, true); + } else if (position == raiseToSpeakRow) { + textCheckCell.setTextAndCheck(LocaleController.getString("RaiseToSpeak", R.string.RaiseToSpeak), SharedConfig.raiseToSpeak, true); + } else if (position == customTabsRow) { + textCheckCell.setTextAndValueAndCheck(LocaleController.getString("ChromeCustomTabs", R.string.ChromeCustomTabs), LocaleController.getString("ChromeCustomTabsInfo", R.string.ChromeCustomTabsInfo), SharedConfig.customTabs, false, true); + } else if (position == directShareRow) { + textCheckCell.setTextAndValueAndCheck(LocaleController.getString("DirectShare", R.string.DirectShare), LocaleController.getString("DirectShareInfo", R.string.DirectShareInfo), SharedConfig.directShare, false, true); } break; } @@ -903,21 +1364,29 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } @Override - public int getItemViewType(int i) { - if (i == newThemeRow || i == nightThemeRow || i == scheduleFromRow || i == scheduleToRow || i == scheduleUpdateLocationRow) { + public int getItemViewType(int position) { + if (position == nightThemeRow || position == scheduleFromRow || position == emojiRow || + position == scheduleToRow || position == scheduleUpdateLocationRow || position == backgroundRow || + position == contactsReimportRow || position == contactsSortRow || position == stickersRow) { return 1; - } else if (i == newThemeInfoRow || i == automaticBrightnessInfoRow || i == scheduleLocationInfoRow) { + } else if (position == automaticBrightnessInfoRow || position == scheduleLocationInfoRow) { return 2; - } else if (i == themeInfoRow || i == nightTypeInfoRow || i == scheduleFromToInfoRow) { + } else if (position == themeInfoRow || position == nightTypeInfoRow || position == scheduleFromToInfoRow || + position == stickersSection2Row || position == settings2Row || position == newThemeInfoRow) { return 3; - } else if (i == nightDisabledRow || i == nightScheduledRow || i == nightAutomaticRow) { + } else if (position == nightDisabledRow || position == nightScheduledRow || position == nightAutomaticRow) { return 4; - } else if (i == scheduleHeaderRow || i == automaticHeaderRow || i == preferedHeaderRow) { + } else if (position == scheduleHeaderRow || position == automaticHeaderRow || position == preferedHeaderRow || + position == settingsRow || position == themeHeaderRow || position == textSizeHeaderRow) { return 5; - } else if (i == automaticBrightnessRow) { + } else if (position == automaticBrightnessRow) { return 6; - } else if (i == scheduleLocationRow) { + } else if (position == scheduleLocationRow || position == enableAnimationsRow || position == sendByEnterRow || + position == saveToGalleryRow || position == autoplayGifsRow || position == raiseToSpeakRow || + position == customTabsRow || position == directShareRow) { return 7; + } else if (position == textSizeRow) { + return 8; } return 0; } @@ -926,7 +1395,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override public ThemeDescription[] getThemeDescriptions() { return new ThemeDescription[]{ - new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, ThemeCell.class}, null, null, null, Theme.key_windowBackgroundWhite), + new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, ThemeCell.class, TextSizeCell.class}, null, null, null, Theme.key_windowBackgroundWhite), new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), @@ -949,6 +1418,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No new ThemeDescription(listView, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4), new ThemeDescription(listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteValueText), new ThemeDescription(listView, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader), @@ -963,6 +1433,33 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No new ThemeDescription(listView, 0, new Class[]{ThemeTypeCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{ThemeTypeCell.class}, new String[]{"checkImage"}, null, null, null, Theme.key_featuredStickers_addedIcon), + + new ThemeDescription(listView, ThemeDescription.FLAG_PROGRESSBAR, new Class[]{TextSizeCell.class}, new String[]{"sizeBar"}, null, null, null, Theme.key_player_progress), + new ThemeDescription(listView, 0, new Class[]{TextSizeCell.class}, new String[]{"sizeBar"}, null, null, null, Theme.key_player_progressBackground), + + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInDrawable, Theme.chat_msgInMediaDrawable}, null, Theme.key_chat_inBubble), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInSelectedDrawable, Theme.chat_msgInMediaSelectedDrawable}, null, Theme.key_chat_inBubbleSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInShadowDrawable, Theme.chat_msgInMediaShadowDrawable}, null, Theme.key_chat_inBubbleShadow), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutDrawable, Theme.chat_msgOutMediaDrawable}, null, Theme.key_chat_outBubble), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutSelectedDrawable, Theme.chat_msgOutMediaSelectedDrawable}, null, Theme.key_chat_outBubbleSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutShadowDrawable, Theme.chat_msgOutMediaShadowDrawable}, null, Theme.key_chat_outBubbleShadow), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_messageTextIn), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_messageTextOut), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheck), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyLine), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyLine), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyNameText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyNameText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyMessageText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyMessageText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyMediaMessageSelectedText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyMediaMessageSelectedText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inTimeText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outTimeText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inTimeSelectedText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outTimeSelectedText), }; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java index 07b1444e5..6e498ce42 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java @@ -12,24 +12,37 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ComposeShader; +import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; +import android.graphics.RadialGradient; +import android.graphics.Rect; import android.graphics.RectF; -import android.graphics.drawable.ColorDrawable; +import android.graphics.Shader; +import android.graphics.SweepGradient; import android.graphics.drawable.Drawable; +import android.text.Editable; +import android.text.InputFilter; +import android.text.InputType; import android.text.TextPaint; import android.text.TextUtils; -import android.text.style.CharacterStyle; +import android.text.TextWatcher; import android.util.Property; import android.util.TypedValue; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; @@ -39,14 +52,16 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.support.widget.RecyclerView; -import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.FileLoader; import org.telegram.messenger.R; @@ -58,13 +73,16 @@ import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SeekBarView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.WallpaperParallaxEffect; @@ -72,16 +90,42 @@ import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; -public class WallpaperActivity extends BaseFragment implements DownloadController.FileDownloadProgressListener { +public class WallpaperActivity extends BaseFragment implements DownloadController.FileDownloadProgressListener, NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; private BackupImageView backgroundImage; - private LinearLayout buttonsContainer; - private File wallpaperFile; + private FrameLayout buttonsContainer; private Drawable themedWallpaper; private AnimatorSet motionAnimation; private RadialProgress2 radialProgress; private FrameLayout bottomOverlayChat; + private CheckBoxView[] checkBoxView; + + private FrameLayout[] patternLayout = new FrameLayout[3]; + private TextView[] patternsCancelButton = new TextView[2]; + private TextView[] patternsSaveButton = new TextView[2]; + private FrameLayout[] patternsButtonsContainer = new FrameLayout[2]; + + private RecyclerListView patternsListView; + private PatternsAdapter patternsAdapter; + private LinearLayoutManager patternsLayoutManager; + private HeaderCell intensityCell; + private SeekBarView intensitySeekBar; + + private ColorPicker colorPicker; + + private ArrayList patterns; + private TLRPC.TL_wallPaper selectedPattern; + private TLRPC.TL_wallPaper previousSelectedPattern; + private int backgroundColor; + private int patternColor; + private int previousBackgroundColor; + private float currentIntensity = 0.4f; + private float previousIntensity; + + private boolean viewCreated; + + private PorterDuff.Mode blendMode = PorterDuff.Mode.SRC_IN; private int TAG; @@ -109,12 +153,432 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle private boolean progressVisible; + private String imageFilter = "640_360"; + private int maxWallpaperSize = 1920; + private WallpaperActivityDelegate delegate; public interface WallpaperActivityDelegate { void didSetNewBackground(); } + private class ColorPicker extends FrameLayout { + + private LinearLayout linearLayout; + + private final int paramValueSliderWidth = AndroidUtilities.dp(20); + + private Paint colorWheelPaint; + private Paint valueSliderPaint; + private Paint circlePaint; + private Drawable circleDrawable; + + private int centerX; + private int centerY; + private int lx; + private int ly; + + boolean ignoreTextChange; + + private Bitmap colorWheelBitmap; + + private EditTextBoldCursor colorEditText[] = new EditTextBoldCursor[2]; + + private int colorWheelRadius; + + private float[] colorHSV = new float[] { 0.0f, 0.0f, 1.0f }; + + private float[] hsvTemp = new float[3]; + private LinearGradient colorGradient; + + private boolean circlePressed; + private boolean colorPressed; + + public ColorPicker(Context context) { + super(context); + + setWillNotDraw(false); + + circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + circleDrawable = context.getResources().getDrawable(R.drawable.knob_shadow).mutate(); + + colorWheelPaint = new Paint(); + colorWheelPaint.setAntiAlias(true); + colorWheelPaint.setDither(true); + + valueSliderPaint = new Paint(); + valueSliderPaint.setAntiAlias(true); + valueSliderPaint.setDither(true); + + linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 64, Gravity.LEFT | Gravity.TOP, 12, 14, 21, 0)); + for (int a = 0; a < 2; a++) { + final int num = a; + + colorEditText[a] = new EditTextBoldCursor(context); + colorEditText[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + colorEditText[a].setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); + colorEditText[a].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + colorEditText[a].setBackgroundDrawable(null); + colorEditText[a].setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + colorEditText[a].setCursorSize(AndroidUtilities.dp(20)); + colorEditText[a].setCursorWidth(1.5f); + colorEditText[a].setSingleLine(true); + colorEditText[a].setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + colorEditText[a].setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); + colorEditText[a].setTransformHintToHeader(true); + colorEditText[a].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)); + colorEditText[a].setPadding(0, 0, 0, 0); + if (a == 0) { + colorEditText[a].setInputType(InputType.TYPE_CLASS_TEXT); + colorEditText[a].setHintText(LocaleController.getString("BackgroundHexColorCode", R.string.BackgroundHexColorCode)); + } else { + colorEditText[a].setInputType(InputType.TYPE_CLASS_NUMBER); + colorEditText[a].setHintText(LocaleController.getString("BackgroundBrightness", R.string.BackgroundBrightness)); + } + colorEditText[a].setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + InputFilter[] inputFilters = new InputFilter[1]; + inputFilters[0] = new InputFilter.LengthFilter(a == 0 ? 7 : 3); + colorEditText[a].setFilters(inputFilters); + linearLayout.addView(colorEditText[a], LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, a == 0 ? 0.67f : 0.31f, 0, 0, a != 1 ? 23 : 0, 0)); + colorEditText[a].addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if (ignoreTextChange) { + return; + } + ignoreTextChange = true; + if (num == 0) { + for (int a = 0; a < editable.length(); a++) { + char ch = editable.charAt(a); + if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F' || ch == '#' && a == 0)) { + editable.replace(a, a + 1, ""); + a--; + } + } + if (editable.length() == 0) { + editable.append("#"); + } else if (editable.charAt(0) != '#') { + editable.insert(0, "#"); + } + try { + setColor(Integer.parseInt(editable.toString().substring(1), 16) | 0xff000000); + } catch (Exception e) { + setColor(0xffffffff); + } + WallpaperActivity.this.setBackgroundColor(getColor()); + colorEditText[1].setText("" + (int) (255 * colorHSV[2])); + } else { + int value = Utilities.parseInt(editable.toString()); + if (value > 255 || value < 0) { + if (value > 255) { + value = 255; + } else { + value = 0; + } + editable.replace(0, editable.length(), "" + value); + } + colorHSV[2] = value / 255.0f; + WallpaperActivity.this.setBackgroundColor(getColor()); + int red = Color.red(backgroundColor); + int green = Color.green(backgroundColor); + int blue = Color.blue(backgroundColor); + colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue)); + } + ColorPicker.this.invalidate(); + ignoreTextChange = false; + } + }); + colorEditText[a].setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == EditorInfo.IME_ACTION_DONE) { + AndroidUtilities.hideKeyboard(textView); + return true; + } + return false; + }); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + int size = Math.min(widthSize, heightSize); + measureChild(linearLayout, MeasureSpec.makeMeasureSpec(widthSize - AndroidUtilities.dp(42), MeasureSpec.EXACTLY), heightMeasureSpec); + setMeasuredDimension(size, size); + } + + @Override + protected void onDraw(Canvas canvas) { + centerX = getWidth() / 2 - paramValueSliderWidth * 2 + AndroidUtilities.dp(11); + centerY = getHeight() / 2 + AndroidUtilities.dp(34); + + canvas.drawBitmap(colorWheelBitmap, centerX - colorWheelRadius, centerY - colorWheelRadius, null); + + float hueAngle = (float) Math.toRadians(colorHSV[0]); + int colorPointX = (int) (-Math.cos(hueAngle) * colorHSV[1] * colorWheelRadius) + centerX; + int colorPointY = (int) (-Math.sin(hueAngle) * colorHSV[1] * colorWheelRadius) + centerY; + + float pointerRadius = 0.075f * colorWheelRadius; + + hsvTemp[0] = colorHSV[0]; + hsvTemp[1] = colorHSV[1]; + hsvTemp[2] = 1.0f; + + drawPointerArrow(canvas, colorPointX, colorPointY, Color.HSVToColor(hsvTemp)); + + lx = centerX + colorWheelRadius + paramValueSliderWidth * 2; + ly = centerY - colorWheelRadius; + int width = AndroidUtilities.dp(9); + int height = colorWheelRadius * 2; + if (colorGradient == null) { + colorGradient = new LinearGradient(lx, ly, lx + width, ly + height, new int[]{Color.BLACK, Color.HSVToColor(hsvTemp)}, null, Shader.TileMode.CLAMP); + } + valueSliderPaint.setShader(colorGradient); + canvas.drawRect(lx, ly, lx + width, ly + height, valueSliderPaint); + drawPointerArrow(canvas, lx + width / 2, (int) (ly + colorHSV[2] * height), Color.HSVToColor(colorHSV)); + } + + private void drawPointerArrow(Canvas canvas, int x, int y, int color) { + int side = AndroidUtilities.dp(13); + circleDrawable.setBounds(x - side, y - side, x + side, y + side); + circleDrawable.draw(canvas); + + circlePaint.setColor(0xffffffff); + canvas.drawCircle(x, y, AndroidUtilities.dp(11), circlePaint); + circlePaint.setColor(color); + canvas.drawCircle(x, y, AndroidUtilities.dp(9), circlePaint); + } + + @Override + protected void onSizeChanged(int width, int height, int oldw, int oldh) { + if (colorWheelRadius != AndroidUtilities.dp(120)) { + colorWheelRadius = AndroidUtilities.dp(120);//Math.max(1, width / 2 - paramValueSliderWidth - AndroidUtilities.dp(20)); + colorWheelBitmap = createColorWheelBitmap(colorWheelRadius * 2, colorWheelRadius * 2); + colorGradient = null; + } + } + + private Bitmap createColorWheelBitmap(int width, int height) { + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + + int colorCount = 12; + int colorAngleStep = 360 / 12; + int colors[] = new int[colorCount + 1]; + float hsv[] = new float[] { 0.0f, 1.0f, 1.0f }; + for (int i = 0; i < colors.length; i++) { + hsv[0] = (i * colorAngleStep + 180) % 360; + colors[i] = Color.HSVToColor(hsv); + } + colors[colorCount] = colors[0]; + + SweepGradient sweepGradient = new SweepGradient(width / 2, height / 2, colors, null); + RadialGradient radialGradient = new RadialGradient(width / 2, height / 2, colorWheelRadius, 0xffffffff, 0x00ffffff, Shader.TileMode.CLAMP); + ComposeShader composeShader = new ComposeShader(sweepGradient, radialGradient, PorterDuff.Mode.SRC_OVER); + + colorWheelPaint.setShader(composeShader); + + Canvas canvas = new Canvas(bitmap); + canvas.drawCircle(width / 2, height / 2, colorWheelRadius, colorWheelPaint); + + return bitmap; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + + int x = (int) event.getX(); + int y = (int) event.getY(); + int cx = x - centerX; + int cy = y - centerY; + double d = Math.sqrt(cx * cx + cy * cy); + + if (circlePressed || !colorPressed && d <= colorWheelRadius) { + if (d > colorWheelRadius) { + d = colorWheelRadius; + } + if (!circlePressed) { + getParent().requestDisallowInterceptTouchEvent(true); + } + circlePressed = true; + colorHSV[0] = (float) (Math.toDegrees(Math.atan2(cy, cx)) + 180.0f); + colorHSV[1] = Math.max(0.0f, Math.min(1.0f, (float) (d / colorWheelRadius))); + colorGradient = null; + } + if (colorPressed || !circlePressed && x >= lx && x <= lx + paramValueSliderWidth && y >= ly && y <= ly + colorWheelRadius * 2) { + float value = (y - ly) / (colorWheelRadius * 2.0f); + if (value < 0.0f) { + value = 0.0f; + } else if (value > 1.0f) { + value = 1.0f; + } + colorHSV[2] = value; + if (!colorPressed) { + getParent().requestDisallowInterceptTouchEvent(true); + } + colorPressed = true; + } + if (colorPressed || circlePressed) { + WallpaperActivity.this.setBackgroundColor(getColor()); + if (!ignoreTextChange) { + int red = Color.red(backgroundColor); + int green = Color.green(backgroundColor); + int blue = Color.blue(backgroundColor); + ignoreTextChange = true; + colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue)); + colorEditText[1].setText("" + (int) (255 * colorHSV[2])); + for (int b = 0; b < 2; b++) { + colorEditText[b].setSelection(colorEditText[b].length()); + } + ignoreTextChange = false; + } + invalidate(); + } + + return true; + case MotionEvent.ACTION_UP: + colorPressed = false; + circlePressed = false; + break; + } + return super.onTouchEvent(event); + } + + public void setColor(int color) { + if (!ignoreTextChange) { + ignoreTextChange = true; + int red = Color.red(color); + int green = Color.green(color); + int blue = Color.blue(color); + Color.colorToHSV(color, colorHSV); + colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue)); + colorEditText[1].setText("" + (int) (255 * colorHSV[2])); + for (int b = 0; b < 2; b++) { + colorEditText[b].setSelection(colorEditText[b].length()); + } + ignoreTextChange = false; + } else { + Color.colorToHSV(color, colorHSV); + } + colorGradient = null; + invalidate(); + } + + public int getColor() { + return (Color.HSVToColor(colorHSV) & 0x00ffffff) | 0xff000000; + } + } + + private class PatternCell extends BackupImageView implements DownloadController.FileDownloadProgressListener { + + private RectF rect = new RectF(); + private RadialProgress2 radialProgress; + private boolean wasSelected; + private TLRPC.TL_wallPaper currentPattern; + + private int TAG; + + public PatternCell(Context context) { + super(context); + setRoundRadius(AndroidUtilities.dp(6)); + + radialProgress = new RadialProgress2(this); + radialProgress.setProgressRect(AndroidUtilities.dp(30), AndroidUtilities.dp(30), AndroidUtilities.dp(70), AndroidUtilities.dp(70)); + + TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); + } + + private void setPattern(TLRPC.TL_wallPaper wallPaper) { + currentPattern = wallPaper; + if (wallPaper != null) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 100); + setImage(thumb, "100_100", null, null, "jpg", 0, 1, wallPaper); + } else { + setImageDrawable(null); + } + updateSelected(false); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + updateSelected(false); + } + + public void updateSelected(boolean animated) { + boolean isSelected = currentPattern == null && selectedPattern == null || selectedPattern != null && currentPattern != null && currentPattern.id == selectedPattern.id; + if (isSelected) { + updateButtonState(radialProgress, selectedPattern, this, false, animated); + } else { + radialProgress.setIcon(MediaActionDrawable.ICON_NONE, false, animated); + } + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + getImageReceiver().setAlpha(0.8f); + + backgroundPaint.setColor(backgroundColor); + rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), backgroundPaint); + + super.onDraw(canvas); + + radialProgress.setColors(patternColor, patternColor, 0xffffffff, 0xffffffff); + radialProgress.draw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(AndroidUtilities.dp(100), AndroidUtilities.dp(100)); + } + + @Override + public void onFailedDownload(String fileName, boolean canceled) { + updateButtonState(radialProgress, currentPattern, this, true, canceled); + } + + @Override + public void onSuccessDownload(String fileName) { + radialProgress.setProgress(1, progressVisible); + updateButtonState(radialProgress, currentPattern, this, false,true); + } + + @Override + public void onProgressDownload(String fileName, float progress) { + radialProgress.setProgress(progress, progressVisible); + if (radialProgress.getIcon() != MediaActionDrawable.ICON_EMPTY) { + updateButtonState(radialProgress, currentPattern, this, false, true); + } + } + + @Override + public void onProgressUpload(String fileName, float progress, boolean isEncrypted) { + + } + + @Override + public int getObserverTag() { + return TAG; + } + } + private class CheckBoxView extends View { private String currentText; @@ -123,8 +587,8 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle private RectF rect; private boolean isChecked; - private Bitmap drawBitmap; private Canvas drawCanvas; + private Bitmap drawBitmap; private float progress; private ObjectAnimator checkAnimator; @@ -143,12 +607,14 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle } }; - public CheckBoxView(Context context) { + public CheckBoxView(Context context, boolean check) { super(context); rect = new RectF(); - drawBitmap = Bitmap.createBitmap(AndroidUtilities.dp(18), AndroidUtilities.dp(18), Bitmap.Config.ARGB_4444); - drawCanvas = new Canvas(drawBitmap); + if (check) { + drawBitmap = Bitmap.createBitmap(AndroidUtilities.dp(18), AndroidUtilities.dp(18), Bitmap.Config.ARGB_4444); + drawCanvas = new Canvas(drawBitmap); + } } public void setText(String text, int current, int max) { @@ -172,36 +638,43 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle canvas.save(); canvas.translate(x, AndroidUtilities.dp(7)); - float checkProgress; - float bounceProgress; - if (progress <= 0.5f) { - bounceProgress = checkProgress = progress / 0.5f; + if (drawBitmap != null) { + float checkProgress; + float bounceProgress; + if (progress <= 0.5f) { + bounceProgress = checkProgress = progress / 0.5f; + } else { + bounceProgress = 2.0f - progress / 0.5f; + checkProgress = 1.0f; + } + + float bounce = AndroidUtilities.dp(1) * bounceProgress; + rect.set(bounce, bounce, AndroidUtilities.dp(18) - bounce, AndroidUtilities.dp(18) - bounce); + + drawBitmap.eraseColor(0); + backgroundPaint.setColor(0xffffffff); + drawCanvas.drawRoundRect(rect, rect.width() / 2, rect.height() / 2, backgroundPaint); + + if (checkProgress != 1) { + float rad = Math.min(AndroidUtilities.dp(7), AndroidUtilities.dp(7) * checkProgress + bounce); + rect.set(AndroidUtilities.dp(2) + rad, AndroidUtilities.dp(2) + rad, AndroidUtilities.dp(16) - rad, AndroidUtilities.dp(16) - rad); + drawCanvas.drawRoundRect(rect, rect.width() / 2, rect.height() / 2, eraserPaint); + } + + if (progress > 0.5f) { + int endX = (int) (AndroidUtilities.dp(7.3f) - AndroidUtilities.dp(2.5f) * (1.0f - bounceProgress)); + int endY = (int) (AndroidUtilities.dp(13) - AndroidUtilities.dp(2.5f) * (1.0f - bounceProgress)); + drawCanvas.drawLine(AndroidUtilities.dp(7.3f), AndroidUtilities.dp(13), endX, endY, checkPaint); + endX = (int) (AndroidUtilities.dp(7.3f) + AndroidUtilities.dp(6) * (1.0f - bounceProgress)); + endY = (int) (AndroidUtilities.dp(13) - AndroidUtilities.dp(6) * (1.0f - bounceProgress)); + drawCanvas.drawLine(AndroidUtilities.dp(7.3f), AndroidUtilities.dp(13), endX, endY, checkPaint); + } + canvas.drawBitmap(drawBitmap, 0, 0, null); } else { - bounceProgress = 2.0f - progress / 0.5f; - checkProgress = 1.0f; + backgroundPaint.setColor(backgroundColor); + rect.set(0, 0, AndroidUtilities.dp(18), AndroidUtilities.dp(18)); + canvas.drawRoundRect(rect, rect.width() / 2, rect.height() / 2, backgroundPaint); } - - float bounce = AndroidUtilities.dp(1) * bounceProgress; - rect.set(bounce, bounce, AndroidUtilities.dp(18) - bounce, AndroidUtilities.dp(18) - bounce); - - drawBitmap.eraseColor(0); - drawCanvas.drawRoundRect(rect, rect.width() / 2, rect.height() / 2, backgroundPaint); - - if (checkProgress != 1) { - float rad = Math.min(AndroidUtilities.dp(7), AndroidUtilities.dp(7) * checkProgress + bounce); - rect.set(AndroidUtilities.dp(2) + rad, AndroidUtilities.dp(2) + rad, AndroidUtilities.dp(16) - rad, AndroidUtilities.dp(16) - rad); - drawCanvas.drawRoundRect(rect, rect.width() / 2, rect.height() / 2, eraserPaint); - } - - if (progress > 0.5f) { - int endX = (int) (AndroidUtilities.dp(7.3f) - AndroidUtilities.dp(2.5f) * (1.0f - bounceProgress)); - int endY = (int) (AndroidUtilities.dp(13) - AndroidUtilities.dp(2.5f) * (1.0f - bounceProgress)); - drawCanvas.drawLine(AndroidUtilities.dp(7.3f), AndroidUtilities.dp(13), endX, endY, checkPaint); - endX = (int) (AndroidUtilities.dp(7.3f) + AndroidUtilities.dp(6) * (1.0f - bounceProgress)); - endY = (int) (AndroidUtilities.dp(13) - AndroidUtilities.dp(6) * (1.0f - bounceProgress)); - drawCanvas.drawLine(AndroidUtilities.dp(7.3f), AndroidUtilities.dp(13), endX, endY, checkPaint); - } - canvas.drawBitmap(drawBitmap, 0, 0, null); canvas.restore(); } @@ -253,17 +726,35 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle super(); currentWallpaper = wallPaper; currentWallpaperBitmap = bitmap; + if (currentWallpaper instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper object = (TLRPC.TL_wallPaper) currentWallpaper; + /*if (object.settings != null) { + isBlurred = object.settings.blur; + isMotion = object.settings.motion; + }*/ + } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + WallpapersListActivity.ColorWallpaper object = (WallpapersListActivity.ColorWallpaper) currentWallpaper; + isMotion = object.motion; + selectedPattern = object.pattern; + if (selectedPattern != null) { + currentIntensity = object.intensity; + } + } } - public void setInitialModes(int modes) { - isBlurred = (modes & 1) != 0; - isMotion = (modes & 2) != 0; + public void setInitialModes(boolean blur, boolean motion) { + isBlurred = blur; + isMotion = motion; } @Override public boolean onFragmentCreate() { super.onFragmentCreate(); + imageFilter = (int) (1080 / AndroidUtilities.density) + "_" + (int) (1920 / AndroidUtilities.density) + "_f"; + maxWallpaperSize = Math.min(1920, Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y)); + + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.wallpapersNeedReload); TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); @@ -283,7 +774,6 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - backgroundPaint.setColor(0xffffffff); return true; } @@ -296,6 +786,7 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle blurredBitmap = null; } Theme.applyChatServiceMessageColor(); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.wallpapersNeedReload); } @Override @@ -313,25 +804,33 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle return; } String link; + StringBuilder modes = new StringBuilder(); + if (isBlurred) { + modes.append("blur"); + } + if (isMotion) { + if (modes.length() > 0) { + modes.append("+"); + } + modes.append("motion"); + } if (currentWallpaper instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/bg/" + wallPaper.slug; - StringBuilder modes = new StringBuilder(); - if (isBlurred) { - modes.append("blur"); - } - if (isMotion) { - if (modes.length() > 0) { - modes.append("+"); - } - modes.append("motion"); - } if (modes.length() > 0) { link += "?mode=" + modes.toString(); } } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { WallpapersListActivity.ColorWallpaper colorWallpaper = (WallpapersListActivity.ColorWallpaper) currentWallpaper; - link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/bg/" + String.format("%02X%02X%02X", (byte) colorWallpaper.color, (byte) colorWallpaper.color >> 8, (byte) colorWallpaper.color >> 16); + String color = String.format("%02x%02x%02x", (byte) (backgroundColor >> 16) & 0xff, (byte) (backgroundColor >> 8) & 0xff, (byte) (backgroundColor & 0xff)).toLowerCase(); + if (selectedPattern != null) { + link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/bg/" + selectedPattern.slug + "?intensity=" + (int) (currentIntensity * 100) + "&bg_color=" + color; + if (modes.length() > 0) { + link += "&mode=" + modes.toString(); + } + } else { + link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/bg/" + color; + } } else { return; } @@ -340,14 +839,14 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle } }); - if (currentWallpaper != null && !WallpapersListActivity.disableFeatures) { + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper || currentWallpaper instanceof TLRPC.TL_wallPaper) { ActionBarMenu menu = actionBar.createMenu(); menu.addItem(share_item, R.drawable.ic_share_video); } FrameLayout frameLayout = new FrameLayout(context); fragmentView = frameLayout; - + hasOwnBackground = true; backgroundImage = new BackupImageView(context) { @Override @@ -375,23 +874,42 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle radialProgress.draw(canvas); } } + + @Override + public void setAlpha(float alpha) { + radialProgress.setOverrideAlpha(alpha); + } }; - backgroundImage.getImageReceiver().setCrossfadeWithOldImage(true); - backgroundImage.getImageReceiver().setForceCrossfade(true); + int textsCount; + int startIndex; + boolean buttonsAvailable; + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + textsCount = 3; + startIndex = patterns != null ? 0 : 2; + buttonsAvailable = patterns != null || selectedPattern != null; + } else { + textsCount = 2; + startIndex = 0; + buttonsAvailable = true; + } frameLayout.addView(backgroundImage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); backgroundImage.getImageReceiver().setDelegate((imageReceiver, set, thumb) -> { - Drawable drawable = imageReceiver.getDrawable(); - if (set && drawable != null) { - Theme.applyChatServiceMessageColor(AndroidUtilities.calcDrawableColor(drawable)); - listView.invalidateViews(); - for (int a = 0, N = buttonsContainer.getChildCount(); a < N; a++) { - buttonsContainer.getChildAt(a).invalidate(); - } - if (radialProgress != null) { - radialProgress.setColors(Theme.key_chat_serviceBackground, Theme.key_chat_serviceBackground, Theme.key_chat_serviceText, Theme.key_chat_serviceText); - } - if (!thumb && isBlurred && blurredBitmap == null) { - updateBlurred(); + if (!(currentWallpaper instanceof WallpapersListActivity.ColorWallpaper)) { + Drawable drawable = imageReceiver.getDrawable(); + if (set && drawable != null) { + Theme.applyChatServiceMessageColor(AndroidUtilities.calcDrawableColor(drawable)); + listView.invalidateViews(); + for (int a = 0, N = buttonsContainer.getChildCount(); a < N; a++) { + buttonsContainer.getChildAt(a).invalidate(); + } + if (radialProgress != null) { + radialProgress.setColors(Theme.key_chat_serviceBackground, Theme.key_chat_serviceBackground, Theme.key_chat_serviceText, Theme.key_chat_serviceText); + } + if (!thumb && isBlurred && blurredBitmap == null) { + backgroundImage.getImageReceiver().setCrossfadeWithOldImage(false); + updateBlurred(); + backgroundImage.getImageReceiver().setCrossfadeWithOldImage(true); + } } } }); @@ -403,11 +921,7 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, true)); listView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); listView.setAdapter(new ListAdapter(context)); - if (WallpapersListActivity.disableFeatures || currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { - listView.setPadding(0, 0, 0, AndroidUtilities.dp(4)); - } else { - listView.setPadding(0, 0, 0, AndroidUtilities.dp(4 + 60)); - } + listView.setPadding(0, 0, 0, AndroidUtilities.dp(buttonsAvailable ? 64 : 4)); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); bottomOverlayChat = new FrameLayout(context) { @@ -424,19 +938,20 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle frameLayout.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); bottomOverlayChat.setOnClickListener(view -> { boolean done; - File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"); - if (isBlurred) { + boolean sameFile = false; + File toFile = new File(ApplicationLoader.getFilesDirFixed(), isBlurred ? "wallpaper_original.jpg" : "wallpaper.jpg"); + if (currentWallpaper instanceof TLRPC.TL_wallPaper) { try { + Bitmap bitmap = backgroundImage.getImageReceiver().getBitmap(); FileOutputStream stream = new FileOutputStream(toFile); - blurredBitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); + bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); stream.close(); done = true; - } catch (Throwable e) { - FileLog.e(e); + } catch (Exception e) { done = false; + FileLog.e(e); } - } else { - if (currentWallpaper instanceof TLRPC.TL_wallPaper) { + if (!done) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; File f = FileLoader.getPathToAttach(wallPaper.document, true); try { @@ -445,54 +960,125 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle done = false; FileLog.e(e); } - } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { - done = true; - } else if (currentWallpaper instanceof WallpapersListActivity.FileWallpaper) { - WallpapersListActivity.FileWallpaper wallpaper = (WallpapersListActivity.FileWallpaper) currentWallpaper; - if (wallpaper.resId != 0 || wallpaper.resId == Theme.THEME_BACKGROUND_ID) { + } + } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + if (selectedPattern != null) { + try { + WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) currentWallpaper; + Bitmap bitmap = backgroundImage.getImageReceiver().getBitmap(); + @SuppressLint("DrawAllocation") + Bitmap dst = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(dst); + canvas.drawColor(backgroundColor); + Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); + paint.setColorFilter(new PorterDuffColorFilter(patternColor, blendMode)); + paint.setAlpha((int) (255 * currentIntensity)); + canvas.drawBitmap(bitmap, 0, 0, paint); + + FileOutputStream stream = new FileOutputStream(toFile); + dst.compress(Bitmap.CompressFormat.JPEG, 87, stream); + stream.close(); done = true; - } else { - try { - done = AndroidUtilities.copyFile(wallpaper.path, toFile); - } catch (Exception e) { - done = false; - FileLog.e(e); - } + } catch (Throwable e) { + FileLog.e(e); + done = false; } } else { + done = true; + } + } else if (currentWallpaper instanceof WallpapersListActivity.FileWallpaper) { + WallpapersListActivity.FileWallpaper wallpaper = (WallpapersListActivity.FileWallpaper) currentWallpaper; + if (wallpaper.resId != 0 || wallpaper.resId == Theme.THEME_BACKGROUND_ID) { + done = true; + } else { + try { + File fromFile = wallpaper.originalPath != null ? wallpaper.originalPath : wallpaper.path; + if (sameFile = fromFile.equals(toFile)) { + done = true; + } else { + done = AndroidUtilities.copyFile(fromFile, toFile); + } + } catch (Exception e) { + done = false; + FileLog.e(e); + } + } + } else if (currentWallpaper instanceof MediaController.SearchImage) { + MediaController.SearchImage wallpaper = (MediaController.SearchImage) currentWallpaper; + File f; + if (wallpaper.photo != null) { + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallpaper.photo.sizes, maxWallpaperSize, true); + f = FileLoader.getPathToAttach(image, true); + } else { + f = ImageLoader.getHttpFilePath(wallpaper.imageUrl, "jpg"); + } + try { + done = AndroidUtilities.copyFile(f, toFile); + } catch (Exception e) { + done = false; + FileLog.e(e); + } + } else { + done = false; + } + if (isBlurred) { + try { + File blurredFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"); + FileOutputStream stream = new FileOutputStream(blurredFile); + blurredBitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); + stream.close(); + done = true; + } catch (Throwable e) { + FileLog.e(e); done = false; } } long id; - int color; + long saveId = 0; + long access_hash = 0; + int color = 0; + long pattern = 0; + File path = null; + if (currentWallpaper instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; - id = wallPaper.id; - color = 0; - - if (!WallpapersListActivity.disableFeatures) { - TLRPC.TL_account_saveWallPaper req = new TLRPC.TL_account_saveWallPaper(); - TLRPC.TL_inputWallPaper inputWallPaper = new TLRPC.TL_inputWallPaper(); - inputWallPaper.id = wallPaper.id; - inputWallPaper.access_hash = wallPaper.access_hash; - req.wallpaper = inputWallPaper; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - - }); - } + saveId = id = wallPaper.id; + access_hash = wallPaper.access_hash; } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) currentWallpaper; - id = wallPaper.id; - color = wallPaper.color; + if (selectedPattern != null) { + saveId = selectedPattern.id; + access_hash = selectedPattern.access_hash; + if (wallPaper.id == wallPaper.patternId && backgroundColor == wallPaper.color && (wallPaper.intensity - currentIntensity) <= 0.001f) { + id = selectedPattern.id; + } else { + id = -1; + } + pattern = selectedPattern.id; + } else { + id = -1; + } + color = backgroundColor; } else if (currentWallpaper instanceof WallpapersListActivity.FileWallpaper) { WallpapersListActivity.FileWallpaper wallPaper = (WallpapersListActivity.FileWallpaper) currentWallpaper; id = wallPaper.id; - color = 0; + path = wallPaper.path; + } else if (currentWallpaper instanceof MediaController.SearchImage) { + MediaController.SearchImage wallPaper = (MediaController.SearchImage) currentWallpaper; + if (wallPaper.photo != null) { + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, maxWallpaperSize, true); + path = FileLoader.getPathToAttach(image, true); + } else { + path = ImageLoader.getHttpFilePath(wallPaper.imageUrl, "jpg"); + } + id = -1; } else { id = 0; color = 0; } + MessagesController.getInstance(currentAccount).saveWallpaperToServer(path, saveId, access_hash, isBlurred, isMotion, color, currentIntensity, access_hash != 0, 0); + if (done) { Theme.serviceMessageColorBackup = Theme.getColor(Theme.key_chat_serviceBackground); SharedPreferences preferences = MessagesController.getGlobalMainSettings(); @@ -501,9 +1087,14 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle editor.putBoolean("selectedBackgroundBlurred", isBlurred); editor.putBoolean("selectedBackgroundMotion", isMotion); editor.putInt("selectedColor", color); + editor.putFloat("selectedIntensity", currentIntensity); + editor.putLong("selectedPattern", pattern); editor.putBoolean("overrideThemeWallpaper", id != Theme.THEME_BACKGROUND_ID); editor.commit(); Theme.reloadWallpaper(); + if (!sameFile) { + ImageLoader.getInstance().removeImage(ImageLoader.getHttpFileName(toFile.getAbsolutePath()) + "@100_100"); + } } if (delegate != null) { delegate.didSetNewBackground(); @@ -518,35 +1109,88 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle bottomOverlayChatText.setText(LocaleController.getString("SetBackground", R.string.SetBackground)); bottomOverlayChat.addView(bottomOverlayChatText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); - buttonsContainer = new LinearLayout(context); - buttonsContainer.setOrientation(LinearLayout.HORIZONTAL); + buttonsContainer = new FrameLayout(context); frameLayout.addView(buttonsContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 50 + 16)); - String text1 = LocaleController.getString("BackgroundBlurred", R.string.BackgroundBlurred); - String text2 = LocaleController.getString("BackgroundMotion", R.string.BackgroundMotion); - int textSize1 = (int) Math.ceil(textPaint.measureText(text1)); - int textSize2 = (int) Math.ceil(textPaint.measureText(text2)); + String[] texts = new String[textsCount]; + int[] textSizes = new int[textsCount]; + checkBoxView = new CheckBoxView[textsCount]; + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + texts[0] = LocaleController.getString("BackgroundColor", R.string.BackgroundColor); + texts[1] = LocaleController.getString("BackgroundPattern", R.string.BackgroundPattern); + texts[2] = LocaleController.getString("BackgroundMotion", R.string.BackgroundMotion); + } else { + texts[0] = LocaleController.getString("BackgroundBlurred", R.string.BackgroundBlurred); + texts[1] = LocaleController.getString("BackgroundMotion", R.string.BackgroundMotion); + } + int maxTextSize = 0; + for (int a = 0; a < texts.length; a++) { + textSizes[a] = (int) Math.ceil(textPaint.measureText(texts[a])); + maxTextSize = Math.max(maxTextSize, textSizes[a]); + } - for (int a = 0; a < 2; a++) { + for (int a = startIndex; a < textsCount; a++) { final int num = a; - CheckBoxView view = new CheckBoxView(context); - view.setText(a == 0 ? text1 : text2, a == 0 ? textSize1 : textSize2, Math.max(textSize1, textSize2)); - view.setChecked(a == 0 ? isBlurred : isMotion, false); - buttonsContainer.addView(view, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, a == 1 ? 9 : 0, 0, 0, 0)); - view.setOnClickListener(v -> { - if (!bottomOverlayChat.isEnabled()) { + checkBoxView[a] = new CheckBoxView(context, !(currentWallpaper instanceof WallpapersListActivity.ColorWallpaper && a == 0)); + checkBoxView[a].setText(texts[a], textSizes[a], maxTextSize); + + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + if (a == 1) { + checkBoxView[a].setChecked(selectedPattern != null, false); + } else if (a == 2) { + checkBoxView[a].setChecked(isMotion, false); + } + } else { + checkBoxView[a].setChecked(a == 0 ? isBlurred : isMotion, false); + } + int width = maxTextSize + AndroidUtilities.dp(14 * 2 + 28); + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, width); + layoutParams.gravity = Gravity.LEFT | Gravity.TOP; + layoutParams.leftMargin = a == 1 ? width + AndroidUtilities.dp(9) : 0; + buttonsContainer.addView(checkBoxView[a], layoutParams); + CheckBoxView view = checkBoxView[a]; + checkBoxView[a].setOnClickListener(v -> { + if (buttonsContainer.getAlpha() != 1.0f) { return; } - view.setChecked(!view.isChecked(), true); - if (num == 0) { - isBlurred = view.isChecked(); - updateBlurred(); + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + if (num == 2) { + view.setChecked(!view.isChecked(), true); + isMotion = view.isChecked(); + parallaxEffect.setEnabled(isMotion); + animateMotionChange(); + } else { + if (num == 1 && patternLayout[num].getVisibility() == View.VISIBLE) { + backgroundImage.setImageDrawable(null); + selectedPattern = null; + isMotion = false; + updateButtonState(radialProgress, null, WallpaperActivity.this, false, true); + updateSelectedPattern(true); + checkBoxView[1].setChecked(false, true); + patternsListView.invalidateViews(); + } + showPatternsView(num, patternLayout[num].getVisibility() != View.VISIBLE); + } } else { - isMotion = view.isChecked(); - parallaxEffect.setEnabled(isMotion); - animateMotionChange(); + view.setChecked(!view.isChecked(), true); + if (num == 0) { + isBlurred = view.isChecked(); + updateBlurred(); + } else { + isMotion = view.isChecked(); + parallaxEffect.setEnabled(isMotion); + animateMotionChange(); + } } }); + if (startIndex == 0 && a == 2) { + checkBoxView[a].setAlpha(0.0f); + checkBoxView[a].setVisibility(View.INVISIBLE); + } + } + + if (!buttonsAvailable) { + buttonsContainer.setVisibility(View.GONE); } parallaxEffect = new WallpaperParallaxEffect(context); @@ -564,18 +1208,181 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle backgroundImage.setTranslationY(offsetY * progress); }); - if (WallpapersListActivity.disableFeatures || currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { - buttonsContainer.setVisibility(View.GONE); + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { isBlurred = false; - isMotion = false; + + for (int a = 0; a < 2; a++) { + final int num = a; + + patternLayout[a] = new FrameLayout(context) { + @Override + public void onDraw(Canvas canvas) { + int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom); + Theme.chat_composeShadowDrawable.draw(canvas); + canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), Theme.chat_composeBackgroundPaint); + } + }; + patternLayout[a].setVisibility(View.INVISIBLE); + patternLayout[a].setWillNotDraw(false); + frameLayout.addView(patternLayout[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, a == 0 ? 390 : 242, Gravity.LEFT | Gravity.BOTTOM)); + + patternsButtonsContainer[a] = new FrameLayout(context) { + @Override + public void onDraw(Canvas canvas) { + int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom); + Theme.chat_composeShadowDrawable.draw(canvas); + canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), Theme.chat_composeBackgroundPaint); + } + }; + patternsButtonsContainer[a].setWillNotDraw(false); + patternsButtonsContainer[a].setPadding(0, AndroidUtilities.dp(3), 0, 0); + patternLayout[a].addView(patternsButtonsContainer[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); + + patternsCancelButton[a] = new TextView(context); + patternsCancelButton[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + patternsCancelButton[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + patternsCancelButton[a].setTextColor(Theme.getColor(Theme.key_chat_fieldOverlayText)); + patternsCancelButton[a].setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); + patternsCancelButton[a].setGravity(Gravity.CENTER); + patternsCancelButton[a].setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); + patternsCancelButton[a].setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 0)); + patternsButtonsContainer[a].addView(patternsCancelButton[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); + patternsCancelButton[a].setOnClickListener(v -> { + if (num == 0) { + setBackgroundColor(previousBackgroundColor); + } else { + selectedPattern = previousSelectedPattern; + if (selectedPattern == null) { + backgroundImage.setImageDrawable(null); + } else { + backgroundImage.setImage(selectedPattern.document, imageFilter, null, null, "jpg", selectedPattern.document.size, 1, selectedPattern); + } + checkBoxView[1].setChecked(selectedPattern != null, false); + + currentIntensity = previousIntensity; + intensitySeekBar.setProgress(currentIntensity); + backgroundImage.getImageReceiver().setAlpha(currentIntensity); + updateButtonState(radialProgress, null, WallpaperActivity.this, false, true); + updateSelectedPattern(true); + } + showPatternsView(num, false); + }); + + patternsSaveButton[a] = new TextView(context); + patternsSaveButton[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + patternsSaveButton[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + patternsSaveButton[a].setTextColor(Theme.getColor(Theme.key_chat_fieldOverlayText)); + patternsSaveButton[a].setText(LocaleController.getString("Save", R.string.Save).toUpperCase()); + patternsSaveButton[a].setGravity(Gravity.CENTER); + patternsSaveButton[a].setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); + patternsSaveButton[a].setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 0)); + patternsButtonsContainer[a].addView(patternsSaveButton[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP)); + patternsSaveButton[a].setOnClickListener(v -> showPatternsView(num, false)); + + if (a == 1) { + patternsListView = new RecyclerListView(context) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onTouchEvent(event); + } + }; + patternsListView.setLayoutManager(patternsLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); + patternsListView.setAdapter(patternsAdapter = new PatternsAdapter(context)); + patternsListView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + int position = parent.getChildAdapterPosition(view); + outRect.left = AndroidUtilities.dp(12); + outRect.bottom = outRect.top = 0; + if (position == state.getItemCount() - 1) { + outRect.right = AndroidUtilities.dp(12); + } + } + }); + patternLayout[a].addView(patternsListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 100, Gravity.LEFT | Gravity.TOP, 0, 14, 0, 0)); + patternsListView.setOnItemClickListener((view, position) -> { + boolean previousMotion = selectedPattern != null; + if (position == 0) { + backgroundImage.setImageDrawable(null); + selectedPattern = null; + isMotion = false; + updateButtonState(radialProgress, null, WallpaperActivity.this, false, true); + } else { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) patterns.get(position - 1); + backgroundImage.setImage(wallPaper.document, imageFilter, null, null, "jpg", wallPaper.document.size, 1, wallPaper); + selectedPattern = wallPaper; + isMotion = checkBoxView[2].isChecked(); + updateButtonState(radialProgress, null, WallpaperActivity.this, false, true); + } + if (previousMotion == (selectedPattern == null)) { + animateMotionChange(); + updateMotionButton(); + } + updateSelectedPattern(true); + checkBoxView[1].setChecked(selectedPattern != null, true); + patternsListView.invalidateViews(); + }); + + intensityCell = new HeaderCell(context); + intensityCell.setText(LocaleController.getString("BackgroundIntensity", R.string.BackgroundIntensity)); + patternLayout[a].addView(intensityCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 113, 0, 0)); + + intensitySeekBar = new SeekBarView(context) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onTouchEvent(event); + } + }; + intensitySeekBar.setProgress(currentIntensity); + intensitySeekBar.setReportChanges(true); + intensitySeekBar.setDelegate(progress -> { + currentIntensity = progress; + backgroundImage.getImageReceiver().setAlpha(currentIntensity); + backgroundImage.invalidate(); + patternsListView.invalidateViews(); + }); + patternLayout[a].addView(intensitySeekBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.TOP | Gravity.LEFT, 9, 153, 9, 0)); + } else { + colorPicker = new ColorPicker(context); + patternLayout[a].addView(colorPicker, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 48)); + } + } } setCurrentImage(true); - updateButtonState(false, false); + updateButtonState(radialProgress, null, this, false, false); + if (!backgroundImage.getImageReceiver().hasBitmapImage()) { + fragmentView.setBackgroundColor(0xff000000); + } + + if (!(currentWallpaper instanceof WallpapersListActivity.ColorWallpaper)) { + backgroundImage.getImageReceiver().setCrossfadeWithOldImage(true); + backgroundImage.getImageReceiver().setForceCrossfade(true); + } return fragmentView; } + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.wallpapersNeedReload) { + if (currentWallpaper instanceof WallpapersListActivity.FileWallpaper) { + WallpapersListActivity.FileWallpaper fileWallpaper = (WallpapersListActivity.FileWallpaper) currentWallpaper; + if (fileWallpaper.id == -1) { + fileWallpaper.id = (Long) args[0]; + } + } + } + } + @Override public void onResume() { super.onResume(); @@ -594,20 +1401,20 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle @Override public void onFailedDownload(String fileName, boolean canceled) { - updateButtonState(true, canceled); + updateButtonState(radialProgress, null, this, true, canceled); } @Override public void onSuccessDownload(String fileName) { radialProgress.setProgress(1, progressVisible); - updateButtonState(false,true); + updateButtonState(radialProgress, null, this, false,true); } @Override public void onProgressDownload(String fileName, float progress) { radialProgress.setProgress(progress, progressVisible); - if (radialProgress.getIcon() != MediaActionDrawable.ICON_CANCEL_PERCENT) { - updateButtonState(false, true); + if (radialProgress.getIcon() != MediaActionDrawable.ICON_EMPTY) { + updateButtonState(radialProgress, null, this, false, true); } } @@ -626,8 +1433,9 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle if (currentWallpaperBitmap != null) { blurredBitmap = Utilities.blurWallpaper(currentWallpaperBitmap); } else { - if (backgroundImage.getImageReceiver().hasNotThumb()) { - blurredBitmap = Utilities.blurWallpaper(backgroundImage.getImageReceiver().getBitmap()); + ImageReceiver imageReceiver = backgroundImage.getImageReceiver(); + if (imageReceiver.hasNotThumb() || imageReceiver.hasStaticThumb()) { + blurredBitmap = Utilities.blurWallpaper(imageReceiver.getBitmap()); } } } @@ -640,43 +1448,87 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle } } - private void updateButtonState(boolean ifSame, boolean animated) { - if (currentWallpaper instanceof TLRPC.TL_wallPaper) { - if (animated && !progressVisible) { - animated = false; + private void updateButtonState(RadialProgress2 radial, Object image, DownloadController.FileDownloadProgressListener listener, boolean ifSame, boolean animated) { + Object object; + if (listener == this) { + if (selectedPattern != null) { + object = selectedPattern; + } else { + object = currentWallpaper; } - TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; - String fileName = FileLoader.getAttachFileName(wallPaper.document); - if (TextUtils.isEmpty(fileName)) { - return; + } else { + object = image; + } + if (object instanceof TLRPC.TL_wallPaper || object instanceof MediaController.SearchImage) { + if (image == null) { + if (animated && !progressVisible) { + animated = false; + } } boolean fileExists; - File path = FileLoader.getPathToAttach(wallPaper.document, true); - if (fileExists = path.exists()) { - DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); - actionBar.setSubtitle(AndroidUtilities.formatFileSize(wallPaper.document.size)); - radialProgress.setProgress(1, animated); - radialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, animated); - backgroundImage.invalidate(); + File path; + int size; + String fileName; + if (object instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; + fileName = FileLoader.getAttachFileName(wallPaper.document); + if (TextUtils.isEmpty(fileName)) { + return; + } + path = FileLoader.getPathToAttach(wallPaper.document, true); + size = wallPaper.document.size; } else { - DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, null, this); + MediaController.SearchImage wallPaper = (MediaController.SearchImage) object; + if (wallPaper.photo != null) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, maxWallpaperSize, true); + path = FileLoader.getPathToAttach(photoSize, true); + fileName = FileLoader.getAttachFileName(photoSize); + size = photoSize.size; + } else { + path = ImageLoader.getHttpFilePath(wallPaper.imageUrl, "jpg"); + fileName = path.getName(); + size = wallPaper.size; + } + if (TextUtils.isEmpty(fileName)) { + return; + } + } + if (fileExists = path.exists()) { + DownloadController.getInstance(currentAccount).removeLoadingFileObserver(listener); + radial.setProgress(1, animated); + radial.setIcon(image == null ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_CHECK, ifSame, animated); + if (image == null) { + backgroundImage.invalidate(); + if (size != 0) { + actionBar.setSubtitle(AndroidUtilities.formatFileSize(size)); + } else { + actionBar.setSubtitle(null); + } + } + } else { + DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, null, listener); boolean isLoading = FileLoader.getInstance(currentAccount).isLoadingFile(fileName); Float progress = ImageLoader.getInstance().getFileProgress(fileName); if (progress != null) { - radialProgress.setProgress(progress, animated); + radial.setProgress(progress, animated); } else { - radialProgress.setProgress(0, animated); + radial.setProgress(0, animated); + } + radial.setIcon(MediaActionDrawable.ICON_EMPTY, ifSame, animated); + if (image == null) { + actionBar.setSubtitle(LocaleController.getString("LoadingFullImage", R.string.LoadingFullImage)); + backgroundImage.invalidate(); } - radialProgress.setIcon(MediaActionDrawable.ICON_CANCEL_PERCENT, ifSame, animated); - actionBar.setSubtitle(LocaleController.getString("LoadingFullImage", R.string.LoadingFullImage)); - - backgroundImage.invalidate(); } - buttonsContainer.setAlpha(fileExists ? 1.0f : 0.5f); - bottomOverlayChat.setEnabled(fileExists); - bottomOverlayChatText.setAlpha(fileExists ? 1.0f : 0.5f); + if (image == null) { + if (selectedPattern == null) { + buttonsContainer.setAlpha(fileExists ? 1.0f : 0.5f); + } + bottomOverlayChat.setEnabled(fileExists); + bottomOverlayChatText.setAlpha(fileExists ? 1.0f : 0.5f); + } } else { - radialProgress.setIcon(MediaActionDrawable.ICON_NONE, false, false); + radial.setIcon(listener == this ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_CHECK, ifSame, animated); } } @@ -684,6 +1536,115 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle delegate = wallpaperActivityDelegate; } + public void setPatterns(ArrayList arrayList) { + patterns = arrayList; + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) currentWallpaper; + if (wallPaper.patternId != 0) { + for (int a = 0, N = patterns.size(); a < N; a++) { + TLRPC.TL_wallPaper pattern = (TLRPC.TL_wallPaper) patterns.get(a); + if (pattern.id == wallPaper.patternId) { + selectedPattern = pattern; + break; + } + } + currentIntensity = wallPaper.intensity; + } + } + } + + private void updateSelectedPattern(boolean animated) { + int count = patternsListView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = patternsListView.getChildAt(a); + if (child instanceof PatternCell) { + ((PatternCell) child).updateSelected(animated); + } + } + } + + private void updateMotionButton() { + checkBoxView[selectedPattern != null ? 2 : 0].setVisibility(View.VISIBLE); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether( + ObjectAnimator.ofFloat(checkBoxView[2], View.ALPHA, selectedPattern != null ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(checkBoxView[0], View.ALPHA, selectedPattern != null ? 0.0f : 1.0f)); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + checkBoxView[selectedPattern != null ? 0 : 2].setVisibility(View.INVISIBLE); + } + }); + animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT); + animatorSet.setDuration(200); + animatorSet.start(); + } + + private void showPatternsView(int num, boolean show) { + boolean showMotion = show && num == 1 && selectedPattern != null; + if (show) { + if (num == 0) { + previousBackgroundColor = backgroundColor; + colorPicker.setColor(backgroundColor); + } else { + previousSelectedPattern = selectedPattern; + previousIntensity = currentIntensity; + patternsAdapter.notifyDataSetChanged(); + if (patterns != null) { + int index; + if (selectedPattern == null) { + index = 0; + } else { + index = patterns.indexOf(selectedPattern) + 1; + } + patternsLayoutManager.scrollToPositionWithOffset(index, (patternsListView.getMeasuredWidth() - AndroidUtilities.dp(100) - AndroidUtilities.dp(12)) / 2); + } + } + } + checkBoxView[showMotion ? 2 : 0].setVisibility(View.VISIBLE); + AnimatorSet animatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + int otherNum = num == 0 ? 1 : 0; + if (show) { + patternLayout[num].setVisibility(View.VISIBLE); + animators.add(ObjectAnimator.ofFloat(listView, View.TRANSLATION_Y, -patternLayout[num].getMeasuredHeight() + AndroidUtilities.dp(48))); + animators.add(ObjectAnimator.ofFloat(buttonsContainer, View.TRANSLATION_Y, -patternLayout[num].getMeasuredHeight() + AndroidUtilities.dp(48))); + animators.add(ObjectAnimator.ofFloat(checkBoxView[2], View.ALPHA, showMotion ? 1.0f : 0.0f)); + animators.add(ObjectAnimator.ofFloat(checkBoxView[0], View.ALPHA, showMotion ? 0.0f : 1.0f)); + animators.add(ObjectAnimator.ofFloat(backgroundImage, View.ALPHA, 0.0f)); + if (patternLayout[otherNum].getVisibility() == View.VISIBLE) { + animators.add(ObjectAnimator.ofFloat(patternLayout[otherNum], View.ALPHA, 0.0f)); + animators.add(ObjectAnimator.ofFloat(patternLayout[num], View.ALPHA, 0.0f, 1.0f)); + patternLayout[num].setTranslationY(0); + } else { + animators.add(ObjectAnimator.ofFloat(patternLayout[num], View.TRANSLATION_Y, patternLayout[num].getMeasuredHeight(), 0)); + } + } else { + animators.add(ObjectAnimator.ofFloat(listView, View.TRANSLATION_Y, 0)); + animators.add(ObjectAnimator.ofFloat(buttonsContainer, View.TRANSLATION_Y, 0)); + animators.add(ObjectAnimator.ofFloat(patternLayout[num], View.TRANSLATION_Y, patternLayout[num].getMeasuredHeight())); + animators.add(ObjectAnimator.ofFloat(checkBoxView[0], View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(checkBoxView[2], View.ALPHA, 0.0f)); + animators.add(ObjectAnimator.ofFloat(backgroundImage, View.ALPHA, 1.0f)); + } + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (show && patternLayout[otherNum].getVisibility() == View.VISIBLE) { + patternLayout[otherNum].setAlpha(1.0f); + patternLayout[otherNum].setVisibility(View.INVISIBLE); + } else if (!show) { + patternLayout[num].setVisibility(View.INVISIBLE); + } + checkBoxView[showMotion ? 0 : 2].setVisibility(View.INVISIBLE); + } + }); + animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT); + animatorSet.setDuration(200); + animatorSet.start(); + } + private void animateMotionChange() { if (motionAnimation != null) { motionAnimation.cancel(); @@ -710,27 +1671,114 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle motionAnimation.start(); } + private void setBackgroundColor(int color) { + backgroundColor = color; + backgroundImage.setBackgroundColor(backgroundColor); + if (checkBoxView[0] != null) { + checkBoxView[0].invalidate(); + } + patternColor = AndroidUtilities.getPatternColor(backgroundColor); + Theme.applyChatServiceMessageColor(new int[]{patternColor, patternColor, patternColor, patternColor}); + + if (backgroundImage != null) { + backgroundImage.getImageReceiver().setColorFilter(new PorterDuffColorFilter(patternColor, blendMode)); + backgroundImage.getImageReceiver().setAlpha(currentIntensity); + backgroundImage.invalidate(); + } + if (listView != null) { + listView.invalidateViews(); + } + if (buttonsContainer != null) { + for (int a = 0, N = buttonsContainer.getChildCount(); a < N; a++) { + buttonsContainer.getChildAt(a).invalidate(); + } + } + if (radialProgress != null) { + radialProgress.setColors(Theme.key_chat_serviceBackground, Theme.key_chat_serviceBackground, Theme.key_chat_serviceText, Theme.key_chat_serviceText); + } + } + private void setCurrentImage(boolean setThumb) { if (currentWallpaper instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; TLRPC.PhotoSize thumb = setThumb ? FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 100) : null; - backgroundImage.setImage(wallPaper.document, "1920_1080", thumb, "100_100_b", "jpg", wallPaper.document.size, 1, currentWallpaper); + backgroundImage.setImage(wallPaper.document, imageFilter, thumb, "100_100_b", "jpg", wallPaper.document.size, 1, wallPaper); } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) currentWallpaper; - backgroundImage.setImageDrawable(new ColorDrawable(wallPaper.color)); + setBackgroundColor(wallPaper.color); + if (selectedPattern != null) { + backgroundImage.setImage(selectedPattern.document, imageFilter, null, null, "jpg", selectedPattern.document.size, 1, selectedPattern); + } } else if (currentWallpaper instanceof WallpapersListActivity.FileWallpaper) { if (currentWallpaperBitmap != null) { backgroundImage.setImageBitmap(currentWallpaperBitmap); } else { WallpapersListActivity.FileWallpaper wallPaper = (WallpapersListActivity.FileWallpaper) currentWallpaper; - if (wallPaper.path != null) { - backgroundImage.setImage(wallPaper.path.getAbsolutePath(), "1920_1080", null); + if (wallPaper.originalPath != null) { + backgroundImage.setImage(wallPaper.originalPath.getAbsolutePath(), imageFilter, null); + } else if (wallPaper.path != null) { + backgroundImage.setImage(wallPaper.path.getAbsolutePath(), imageFilter, null); } else if (wallPaper.resId == Theme.THEME_BACKGROUND_ID) { backgroundImage.setImageDrawable(Theme.getThemedWallpaper(false)); } else if (wallPaper.resId != 0) { backgroundImage.setImageResource(wallPaper.resId); } } + } else if (currentWallpaper instanceof MediaController.SearchImage) { + MediaController.SearchImage wallPaper = (MediaController.SearchImage) currentWallpaper; + if (wallPaper.photo != null) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, 100); + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, maxWallpaperSize, true); + if (image == thumb) { + image = null; + } + int size = image != null ? image.size : 0; + backgroundImage.setImage(image, imageFilter, thumb, "100_100_b", "jpg", size, 1, wallPaper); + } else { + backgroundImage.setImage(wallPaper.imageUrl, imageFilter, wallPaper.thumbUrl, "100_100_b"); + } + } + } + + private class PatternsAdapter extends RecyclerListView.SelectionAdapter { + + private Context mContext; + + public PatternsAdapter(Context context) { + mContext = context; + } + + @Override + public int getItemViewType(int position) { + return super.getItemViewType(position); + } + + @Override + public int getItemCount() { + return (patterns != null ? patterns.size() : 0) + 1; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + PatternCell view = new PatternCell(mContext); + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + PatternCell view = (PatternCell) holder.itemView; + if (position == 0) { + view.setPattern(null); + } else { + position--; + view.setPattern((TLRPC.TL_wallPaper) patterns.get(position)); + } + view.getImageReceiver().setColorFilter(new PorterDuffColorFilter(patternColor, blendMode)); } } @@ -749,7 +1797,12 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle TLRPC.Message message; message = new TLRPC.TL_message(); - message.message = "I can't even take you seriously right now.";//LocaleController.getString("BackgroundPreviewLine2", R.string.BackgroundPreviewLine2); + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + message.message = LocaleController.getString("BackgroundColorSinglePreviewLine2", R.string.BackgroundColorSinglePreviewLine2); + //message.message = LocaleController.getString("BackgroundColorPreviewLine2", R.string.BackgroundColorPreviewLine2); + } else { + message.message = LocaleController.getString("BackgroundPreviewLine2", R.string.BackgroundPreviewLine2); + } message.date = date + 60; message.dialog_id = 1; message.flags = 259; @@ -759,10 +1812,18 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle message.out = true; message.to_id = new TLRPC.TL_peerUser(); message.to_id.user_id = 0; - messages.add(new MessageObject(currentAccount, message, true)); + MessageObject messageObject = new MessageObject(currentAccount, message, true); + messageObject.eventId = 1; + messageObject.resetLayout(); + messages.add(messageObject); message = new TLRPC.TL_message(); - message.message = "Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff!";//LocaleController.getString("BackgroundPreviewLine1", R.string.BackgroundPreviewLine1); + if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { + message.message = LocaleController.getString("BackgroundColorSinglePreviewLine1", R.string.BackgroundColorSinglePreviewLine1); + //message.message = LocaleController.getString("BackgroundColorPreviewLine1", R.string.BackgroundColorPreviewLine1); + } else { + message.message = LocaleController.getString("BackgroundPreviewLine1", R.string.BackgroundPreviewLine1); + } message.date = date + 60; message.dialog_id = 1; message.flags = 257 + 8; @@ -773,13 +1834,16 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle message.out = false; message.to_id = new TLRPC.TL_peerUser(); message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); - messages.add(new MessageObject(currentAccount, message, true)); + messageObject = new MessageObject(currentAccount, message, true); + messageObject.eventId = 1; + messageObject.resetLayout(); + messages.add(messageObject); message = new TLRPC.TL_message(); message.message = LocaleController.formatDateChat(date); message.id = 0; message.date = date; - MessageObject messageObject = new MessageObject(currentAccount, message, false); + messageObject = new MessageObject(currentAccount, message, false); messageObject.type = 10; messageObject.contentType = 1; messageObject.isDateObject = true; @@ -803,118 +1867,12 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle view = new ChatMessageCell(mContext); ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { - @Override - public void didPressShare(ChatMessageCell cell) { - } - - @Override - public boolean needPlayMessage(MessageObject messageObject) { - return false; - } - - @Override - public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId) { - - } - - @Override - public void didPressOther(ChatMessageCell cell) { - - } - - @Override - public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user) { - - } - - @Override - public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { - - } - - @Override - public void didPressVoteButton(ChatMessageCell cell, TLRPC.TL_pollAnswer button) { - - } - - @Override - public void didPressCancelSendButton(ChatMessageCell cell) { - - } - - @Override - public void didLongPress(ChatMessageCell cell) { - - } - - @Override - public boolean canPerformActions() { - return false; - } - - @Override - public void didPressUrl(MessageObject messageObject, final CharacterStyle url, boolean longPress) { - - } - - @Override - public void needOpenWebView(String url, String title, String description, String originalUrl, int w, int h) { - - } - - @Override - public void didPressReplyMessage(ChatMessageCell cell, int id) { - - } - - @Override - public void didPressViaBot(ChatMessageCell cell, String username) { - - } - - @Override - public void didPressImage(ChatMessageCell cell) { - - } - - @Override - public void didPressInstantButton(ChatMessageCell cell, int type) { - - } - - @Override - public boolean isChatAdminCell(int uid) { - return false; - } }); } else if (viewType == 1) { view = new ChatActionCell(mContext); ((ChatActionCell) view).setDelegate(new ChatActionCell.ChatActionCellDelegate() { - @Override - public void didClickedImage(ChatActionCell cell) { - } - - @Override - public void didLongPressed(ChatActionCell cell) { - - } - - @Override - public void needOpenUserProfile(int uid) { - - } - - @Override - public void didPressedReplyMessage(ChatActionCell cell, int id) { - - } - - @Override - public void didPressedBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { - - } }); } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); @@ -965,16 +1923,80 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle @Override public ThemeDescription[] getThemeDescriptions() { - return new ThemeDescription[]{ - new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite), + ArrayList arrayList = new ArrayList<>(); - new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), - new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); - new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), - }; + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); + + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); + + for (int a = 0; a < patternLayout.length; a++) { + arrayList.add(new ThemeDescription(patternLayout[a], 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); + arrayList.add(new ThemeDescription(patternLayout[a], 0, null, Theme.chat_composeBackgroundPaint, null, null, Theme.key_chat_messagePanelBackground)); + } + + for (int a = 0; a < patternsButtonsContainer.length; a++) { + arrayList.add(new ThemeDescription(patternsButtonsContainer[a], 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); + arrayList.add(new ThemeDescription(patternsButtonsContainer[a], 0, null, Theme.chat_composeBackgroundPaint, null, null, Theme.key_chat_messagePanelBackground)); + } + + + arrayList.add(new ThemeDescription(bottomOverlayChat, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); + arrayList.add(new ThemeDescription(bottomOverlayChat, 0, null, Theme.chat_composeBackgroundPaint, null, null, Theme.key_chat_messagePanelBackground)); + arrayList.add(new ThemeDescription(bottomOverlayChatText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); + + for (int a = 0; a < patternsSaveButton.length; a++) { + arrayList.add(new ThemeDescription(patternsSaveButton[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); + } + for (int a = 0; a < patternsSaveButton.length; a++) { + arrayList.add(new ThemeDescription(patternsSaveButton[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); + } + + if (colorPicker != null) { + for (int a = 0; a < colorPicker.colorEditText.length; a++) { + arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText)); + arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader)); + arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputField)); + arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); + arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteRedText3)); + } + } + + arrayList.add(new ThemeDescription(intensitySeekBar, 0, new Class[]{SeekBarView.class}, new String[]{"innerPaint1"}, null, null, null, Theme.key_player_progressBackground)); + arrayList.add(new ThemeDescription(intensitySeekBar, 0, new Class[]{SeekBarView.class}, new String[]{"outerPaint1"}, null, null, null, Theme.key_player_progress)); + + arrayList.add(new ThemeDescription(intensityCell, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader)); + + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInDrawable, Theme.chat_msgInMediaDrawable}, null, Theme.key_chat_inBubble)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInSelectedDrawable, Theme.chat_msgInMediaSelectedDrawable}, null, Theme.key_chat_inBubbleSelected)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInShadowDrawable, Theme.chat_msgInMediaShadowDrawable}, null, Theme.key_chat_inBubbleShadow)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutDrawable, Theme.chat_msgOutMediaDrawable}, null, Theme.key_chat_outBubble)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutSelectedDrawable, Theme.chat_msgOutMediaSelectedDrawable}, null, Theme.key_chat_outBubbleSelected)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutShadowDrawable, Theme.chat_msgOutMediaShadowDrawable}, null, Theme.key_chat_outBubbleShadow)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageTextIn)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageTextOut)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheck)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyLine)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyLine)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyNameText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyNameText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyMessageText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyMessageText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyMediaMessageSelectedText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyMediaMessageSelectedText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inTimeText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outTimeText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inTimeSelectedText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outTimeSelectedText)); + + return arrayList.toArray(new ThemeDescription[arrayList.size()]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java index d128fadc5..7d1672c23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java @@ -8,6 +8,9 @@ package org.telegram.ui; +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -18,7 +21,14 @@ import android.graphics.Paint; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.util.LongSparseArray; import android.view.Gravity; +import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewGroup; @@ -36,6 +46,8 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SendMessagesHelper; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; @@ -44,19 +56,25 @@ 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.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCell; +import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.WallpaperCell; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.WallpaperUpdater; import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; public class WallpapersListActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -67,23 +85,14 @@ public class WallpapersListActivity extends BaseFragment implements Notification private int sectionRow; private int wallPaperStartRow; private int totalWallpaperRows; + private int resetSectionRow; + private int resetRow; + private int resetInfoRow; private int currentType; - private ArrayList searchResult = new ArrayList<>(); - private HashMap searchResultKeys = new HashMap<>(); - private HashMap searchResultUrls = new HashMap<>(); - - public static boolean disableFeatures = true; - - private boolean searching; - private boolean bingSearchEndReached = true; - private String lastSearchString; - private String nextImagesSearchOffset; - private int imageReqId; - private int lastSearchToken; - private boolean searchingUser; - private String lastSearchImageString; + private Paint colorPaint; + private Paint colorFramePaint; private ColorWallpaper addedColorWallpaper; private FileWallpaper addedFileWallpaper; @@ -92,7 +101,13 @@ public class WallpapersListActivity extends BaseFragment implements Notification private RecyclerListView listView; private ListAdapter listAdapter; + private SearchAdapter searchAdapter; private LinearLayoutManager layoutManager; + private ActionBarMenuItem searchItem; + private NumberTextView selectedMessagesCountTextView; + private EmptyTextProgressView searchEmptyView; + private ArrayList actionModeViews = new ArrayList<>(); + private AlertDialog progressDialog; private WallpaperUpdater updater; @@ -100,9 +115,22 @@ public class WallpapersListActivity extends BaseFragment implements Notification private long selectedBackground; private int selectedColor; + private float selectedIntensity; + private boolean selectedBackgroundMotion; + private boolean selectedBackgroundBlurred; + private long selectedPattern; + private ArrayList allWallPapers = new ArrayList<>(); + private LongSparseArray allWallPapersDict = new LongSparseArray<>(); private ArrayList wallPapers = new ArrayList<>(); + private ArrayList patterns = new ArrayList<>(); private boolean loadingWallpapers; + private LongSparseArray selectedWallPapers = new LongSparseArray<>(); + private boolean scrolling; + + private final static int forward = 3; + private final static int delete = 4; + private static final int[] defaultColors = new int[]{ 0xffffffff, 0xffd4dfea, @@ -139,6 +167,51 @@ public class WallpapersListActivity extends BaseFragment implements Notification 0xff000000 }; + private static final int[] searchColors = new int[]{ + 0xff0076ff, + 0xffff0000, + 0xffff8a00, + 0xffffca00, + 0xff00e432, + 0xff1fa9ab, + 0xff7300aa, + 0xfff9bec5, + 0xff734021, + 0xff000000, + 0xff5c585f, + 0xffffffff + }; + + private static final String[] searchColorsNames = new String[]{ + "Blue", + "Red", + "Orange", + "Yellow", + "Green", + "Teal", + "Purple", + "Pink", + "Brown", + "Black", + "Gray", + "White" + }; + + private static final int[] searchColorsNamesR = new int[]{ + R.string.Blue, + R.string.Red, + R.string.Orange, + R.string.Yellow, + R.string.Green, + R.string.Teal, + R.string.Purple, + R.string.Pink, + R.string.Brown, + R.string.Black, + R.string.Gray, + R.string.White + }; + public final static int TYPE_ALL = 0; public final static int TYPE_COLOR = 1; @@ -146,10 +219,25 @@ public class WallpapersListActivity extends BaseFragment implements Notification public long id; public int color; + public long patternId; + public TLRPC.TL_wallPaper pattern; + public float intensity; + public File path; + public boolean motion; public ColorWallpaper(long i, int c) { id = i; - color = c; + color = c | 0xff000000; + intensity = 1.0f; + } + + public ColorWallpaper(long i, int c, long p, float in, boolean m, File ph) { + id = i; + color = c | 0xff000000; + patternId = p; + intensity = in; + path = ph; + motion = m; } } @@ -159,10 +247,12 @@ public class WallpapersListActivity extends BaseFragment implements Notification public int resId; public int thumbResId; public File path; + public File originalPath; - public FileWallpaper(long i, File f) { + public FileWallpaper(long i, File f, File of) { id = i; path = f; + originalPath = of; } public FileWallpaper(long i, String f) { @@ -187,6 +277,7 @@ public class WallpapersListActivity extends BaseFragment implements Notification if (currentType == TYPE_ALL) { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.wallpapersDidLoad); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.wallpapersNeedReload); MessagesStorage.getInstance(currentAccount).getWallpapers(); } else { for (int a = 0; a < defaultColors.length; a++) { @@ -199,12 +290,10 @@ public class WallpapersListActivity extends BaseFragment implements Notification @Override public void onFragmentDestroy() { if (currentType == TYPE_ALL) { - if (imageReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); - imageReqId = 0; - } + searchAdapter.onDestroy(); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.wallpapersDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.wallpapersNeedReload); } updater.cleanup(); super.onFragmentDestroy(); @@ -213,10 +302,16 @@ public class WallpapersListActivity extends BaseFragment implements Notification @SuppressWarnings("unchecked") @Override public View createView(Context context) { + colorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + colorFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + colorFramePaint.setStrokeWidth(AndroidUtilities.dp(1)); + colorFramePaint.setStyle(Paint.Style.STROKE); + colorFramePaint.setColor(0x33000000); + updater = new WallpaperUpdater(getParentActivity(), this, new WallpaperUpdater.WallpaperUpdaterDelegate() { @Override public void didSelectWallpaper(File file, Bitmap bitmap, boolean gallery) { - presentFragment(new WallpaperActivity(new FileWallpaper(-1, file), bitmap), gallery); + presentFragment(new WallpaperActivity(new FileWallpaper(-1, file, file), bitmap), gallery); } @Override @@ -237,47 +332,178 @@ public class WallpapersListActivity extends BaseFragment implements Notification @Override public void onItemClick(int id) { if (id == -1) { - finishFragment(); + if (actionBar.isActionModeShowed()) { + selectedWallPapers.clear(); + actionBar.hideActionMode(); + updateRowsSelection(); + } else { + finishFragment(); + } + } else if (id == delete) { + if (getParentActivity() == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setMessage(LocaleController.formatString("DeleteChatBackgroundsAlert", R.string.DeleteChatBackgroundsAlert)); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { + progressDialog = new AlertDialog(getParentActivity(), 3); + progressDialog.setCanCacnel(false); + progressDialog.show(); + + ArrayList ids = new ArrayList<>(); + int deleteCount[] = new int[]{selectedWallPapers.size()}; + for (int b = 0; b < selectedWallPapers.size(); b++) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) selectedWallPapers.valueAt(b); + + TLRPC.TL_account_saveWallPaper req = new TLRPC.TL_account_saveWallPaper(); + req.settings = new TLRPC.TL_wallPaperSettings(); + req.unsave = true; + + TLRPC.TL_inputWallPaper inputWallPaper = new TLRPC.TL_inputWallPaper(); + inputWallPaper.id = wallPaper.id; + inputWallPaper.access_hash = wallPaper.access_hash; + req.wallpaper = inputWallPaper; + + if (wallPaper.id == selectedBackground) { + selectedBackground = Theme.DEFAULT_BACKGROUND_ID; + + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putLong("selectedBackground2", selectedBackground); + editor.putBoolean("selectedBackgroundBlurred", false); + editor.putBoolean("selectedBackgroundMotion", false); + editor.putInt("selectedColor", 0); + editor.putFloat("selectedIntensity", 1.0f); + editor.putLong("selectedPattern", 0); + editor.putBoolean("overrideThemeWallpaper", true); + editor.commit(); + Theme.reloadWallpaper(); + } + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + deleteCount[0]--; + if (deleteCount[0] == 0) { + loadWallpapers(); + } + })); + } + selectedWallPapers.clear(); + actionBar.hideActionMode(); + actionBar.closeSearchField(); + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + } else if (id == forward) { + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + args.putInt("dialogsType", 3); + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate((fragment1, dids, message, param) -> { + StringBuilder fmessage = new StringBuilder(); + for (int b = 0; b < selectedWallPapers.size(); b++) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) selectedWallPapers.valueAt(b); + String link = AndroidUtilities.getWallPaperUrl(wallPaper, currentAccount); + if (!TextUtils.isEmpty(link)) { + if (fmessage.length() > 0) { + fmessage.append('\n'); + } + fmessage.append(link); + } + } + selectedWallPapers.clear(); + actionBar.hideActionMode(); + actionBar.closeSearchField(); + + if (dids.size() > 1 || dids.get(0) == UserConfig.getInstance(currentAccount).getClientUserId() || message != null) { + updateRowsSelection(); + for (int a = 0; a < dids.size(); a++) { + long did = dids.get(a); + if (message != null) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null); + } + SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessage.toString(), did, null, null, true, null, null, null); + } + fragment1.finishFragment(); + } else { + long did = dids.get(0); + int lower_part = (int) did; + int high_part = (int) (did >> 32); + Bundle args1 = new Bundle(); + args1.putBoolean("scrollToTopOnResume", true); + if (lower_part != 0) { + if (lower_part > 0) { + args1.putInt("user_id", lower_part); + } else if (lower_part < 0) { + args1.putInt("chat_id", -lower_part); + } + } else { + args1.putInt("enc_id", high_part); + } + if (lower_part != 0) { + if (!MessagesController.getInstance(currentAccount).checkCanOpenChat(args1, fragment1)) { + return; + } + } + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); + + ChatActivity chatActivity = new ChatActivity(args1); + presentFragment(chatActivity, true); + SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessage.toString(), did, null, null, true, null, null, null); + } + }); + presentFragment(fragment); } } }); if (currentType == TYPE_ALL) { ActionBarMenu menu = actionBar.createMenu(); - ActionBarMenuItem searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { + searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override public void onSearchExpand() { + listView.setAdapter(searchAdapter); + listView.invalidate(); + } + @Override + public void onSearchCollapse() { + listView.setAdapter(listAdapter); + listView.invalidate(); + searchAdapter.processSearch(null, true); + searchItem.setSearchFieldCaption(null); + onCaptionCleared(); } @Override public void onTextChanged(EditText editText) { - if (editText.getText().length() == 0) { - searchResult.clear(); - searchResultKeys.clear(); - lastSearchString = null; - bingSearchEndReached = true; - searching = false; - if (imageReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); - imageReqId = 0; - } - /*if (type == 0) { - emptyView.setText(LocaleController.getString("NoRecentPhotos", R.string.NoRecentPhotos)); - } else if (type == 1) { - emptyView.setText(LocaleController.getString("NoRecentGIFs", R.string.NoRecentGIFs)); - }*/ - updateSearchInterface(); - } + searchAdapter.processSearch(editText.getText().toString(), false); } @Override - public void onSearchPressed(EditText editText) { - processSearch(editText); + public void onCaptionCleared() { + searchAdapter.clearColor(); + searchItem.setSearchFieldHint(LocaleController.getString("SearchBackgrounds", R.string.SearchBackgrounds)); } }); - searchItem.setSearchFieldHint(LocaleController.getString("SearchImagesTitle", R.string.SearchImagesTitle)); - searchItem.setVisibility(View.GONE); + searchItem.setSearchFieldHint(LocaleController.getString("SearchBackgrounds", R.string.SearchBackgrounds)); + + final ActionBarMenu actionMode = actionBar.createActionMode(false); + actionMode.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefault)); + actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon), true); + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSelector), true); + + selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); + selectedMessagesCountTextView.setTextSize(18); + selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + selectedMessagesCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultIcon)); + selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); + actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); + + actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.ic_ab_forward, AndroidUtilities.dp(54))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.ic_ab_delete, AndroidUtilities.dp(54))); + + selectedWallPapers.clear(); } fragmentView = new FrameLayout(context); @@ -296,8 +522,8 @@ public class WallpapersListActivity extends BaseFragment implements Notification @Override public void onDraw(Canvas c) { ViewHolder holder; - if (wallPaperStartRow == -1) { - holder = findViewHolderForAdapterPosition(sectionRow); + if (getAdapter() == listAdapter && resetInfoRow != -1) { + holder = findViewHolderForAdapterPosition(resetInfoRow); } else { holder = null; } @@ -333,44 +559,72 @@ public class WallpapersListActivity extends BaseFragment implements Notification }); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); listView.setAdapter(listAdapter = new ListAdapter(context)); + searchAdapter = new SearchAdapter(context); listView.setGlowColor(Theme.getColor(Theme.key_avatar_backgroundActionBarBlue)); listView.setOnItemClickListener((view, position) -> { + if (getParentActivity() == null || listView.getAdapter() == searchAdapter) { + return; + } if (position == uploadImageRow) { - updater.showAlert(false); + updater.openGallery(); } else if (position == setColorRow) { - presentFragment(new WallpapersListActivity(TYPE_COLOR)); + WallpapersListActivity activity = new WallpapersListActivity(TYPE_COLOR); + activity.patterns = patterns; + presentFragment(activity); + } else if (position == resetRow) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setMessage(LocaleController.getString("ResetChatBackgroundsAlert", R.string.ResetChatBackgroundsAlert)); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setPositiveButton(LocaleController.getString("Reset", R.string.Reset), (dialogInterface, i) -> { + if (actionBar.isActionModeShowed()) { + selectedWallPapers.clear(); + actionBar.hideActionMode(); + updateRowsSelection(); + } + progressDialog = new AlertDialog(getParentActivity(), 3); + progressDialog.setCanCacnel(false); + progressDialog.show(); + TLRPC.TL_account_resetWallPapers req = new TLRPC.TL_account_resetWallPapers(); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(this::loadWallpapers)); + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); } }); - //listView.setOnItemLongClickListener((view, position) -> { - // return false; - //}); - listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } + scrolling = newState != RecyclerView.SCROLL_STATE_IDLE; } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); - int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; - if (visibleItemCount > 0) { - int totalItemCount = layoutManager.getItemCount(); - if (visibleItemCount != 0 && firstVisibleItem + visibleItemCount > totalItemCount - 2 && !searching) { - if (!bingSearchEndReached) { - searchImages(lastSearchString, nextImagesSearchOffset, true); + if (listView.getAdapter() == searchAdapter) { + int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); + int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; + if (visibleItemCount > 0) { + int totalItemCount = layoutManager.getItemCount(); + if (visibleItemCount != 0 && firstVisibleItem + visibleItemCount > totalItemCount - 2) { + searchAdapter.loadMoreResults(); } } } } }); + searchEmptyView = new EmptyTextProgressView(context); + searchEmptyView.setVisibility(View.GONE); + searchEmptyView.setShowAtCenter(true); + searchEmptyView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + searchEmptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + listView.setEmptyView(searchEmptyView); + frameLayout.addView(searchEmptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + updateRows(); - updateSearchInterface(); return fragmentView; } @@ -380,7 +634,11 @@ public class WallpapersListActivity extends BaseFragment implements Notification super.onResume(); SharedPreferences preferences = MessagesController.getGlobalMainSettings(); selectedBackground = Theme.getSelectedBackgroundId(); + selectedPattern = preferences.getLong("selectedPattern", 0); selectedColor = preferences.getInt("selectedColor", 0); + selectedIntensity = preferences.getFloat("selectedIntensity", 1.0f); + selectedBackgroundMotion = preferences.getBoolean("selectedBackgroundMotion", false); + selectedBackgroundBlurred = preferences.getBoolean("selectedBackgroundBlurred", false); fillWallpapersWithCustom(); fixLayout(); } @@ -409,26 +667,132 @@ public class WallpapersListActivity extends BaseFragment implements Notification updater.setCurrentPicturePath(args.getString("path")); } + private boolean onItemLongClick(WallpaperCell view, Object object, int index) { + if (actionBar.isActionModeShowed() || getParentActivity() == null || !(object instanceof TLRPC.TL_wallPaper)) { + return false; + } + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; + AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); + selectedWallPapers.put(wallPaper.id, wallPaper); + selectedMessagesCountTextView.setNumber(1, false); + AnimatorSet animatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + for (int i = 0; i < actionModeViews.size(); i++) { + View view2 = actionModeViews.get(i); + AndroidUtilities.clearDrawableAnimation(view2); + animators.add(ObjectAnimator.ofFloat(view2, View.SCALE_Y, 0.1f, 1.0f)); + } + animatorSet.playTogether(animators); + animatorSet.setDuration(250); + animatorSet.start(); + scrolling = false; + actionBar.showActionMode(); + view.setChecked(index, true, true); + return true; + } + + private void onItemClick(WallpaperCell view, Object object, int index) { + if (actionBar.isActionModeShowed()) { + if (!(object instanceof TLRPC.TL_wallPaper)) { + return; + } + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; + if (selectedWallPapers.indexOfKey(wallPaper.id) >= 0) { + selectedWallPapers.remove(wallPaper.id); + } else { + selectedWallPapers.put(wallPaper.id, wallPaper); + } + if (selectedWallPapers.size() == 0) { + actionBar.hideActionMode(); + } else { + selectedMessagesCountTextView.setNumber(selectedWallPapers.size(), true); + } + scrolling = false; + view.setChecked(index, selectedWallPapers.indexOfKey(wallPaper.id) >= 0, true); + } else { + long id = getWallPaperId(object); + if (object instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; + if (wallPaper.pattern) { + object = new ColorWallpaper(wallPaper.id, wallPaper.settings.background_color, wallPaper.id, wallPaper.settings.intensity / 100.0f, wallPaper.settings.motion, null); + } + } + WallpaperActivity wallpaperActivity = new WallpaperActivity(object, null); + if (currentType == TYPE_COLOR) { + wallpaperActivity.setDelegate(WallpapersListActivity.this::removeSelfFromStack); + } + if (selectedBackground == id) { + wallpaperActivity.setInitialModes(selectedBackgroundBlurred, selectedBackgroundMotion); + } + wallpaperActivity.setPatterns(patterns); + presentFragment(wallpaperActivity); + } + } + + private long getWallPaperId(Object object) { + if (object instanceof TLRPC.TL_wallPaper) { + return ((TLRPC.TL_wallPaper) object).id; + } else if (object instanceof ColorWallpaper) { + return ((ColorWallpaper) object).id; + } else if (object instanceof FileWallpaper) { + return ((FileWallpaper) object).id; + } else { + return 0; + } + } + + private void updateRowsSelection() { + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = listView.getChildAt(a); + if (child instanceof WallpaperCell) { + WallpaperCell cell = (WallpaperCell) child; + for (int b = 0; b < 5; b++) { + cell.setChecked(b, false, true); + } + } + } + } + @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.wallpapersDidLoad) { ArrayList arrayList = (ArrayList) args[0]; wallPapers.clear(); - wallPapers.addAll(arrayList); + patterns.clear(); + allWallPapers.clear(); + allWallPapersDict.clear(); + allWallPapers.addAll(arrayList); + for (int a = 0, N = arrayList.size(); a < N; a++) { + TLRPC.TL_wallPaper wallPaper = arrayList.get(a); + allWallPapersDict.put(wallPaper.id, wallPaper); + if (wallPaper.pattern) { + patterns.add(wallPaper); + } + if (!wallPaper.pattern || wallPaper.settings != null) { + wallPapers.add(wallPaper); + } + } + selectedBackground = Theme.getSelectedBackgroundId(); fillWallpapersWithCustom(); loadWallpapers(); } else if (id == NotificationCenter.didSetNewWallpapper) { if (listView != null) { listView.invalidateViews(); } + if (actionBar != null) { + actionBar.closeSearchField(); + } + } else if (id == NotificationCenter.wallpapersNeedReload) { + MessagesStorage.getInstance(currentAccount).getWallpapers(); } } private void loadWallpapers() { long acc = 0; - for (int a = 0, N = wallPapers.size(); a < N; a++) { - Object object = wallPapers.get(a); + for (int a = 0, N = allWallPapers.size(); a < N; a++) { + Object object = allWallPapers.get(a); if (!(object instanceof TLRPC.TL_wallPaper)) { continue; } @@ -440,18 +804,32 @@ public class WallpapersListActivity extends BaseFragment implements Notification } TLRPC.TL_account_getWallPapers req = new TLRPC.TL_account_getWallPapers(); req.hash = (int) acc; - int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (!(response instanceof TLRPC.TL_account_wallPapers)) { - return; - } - AndroidUtilities.runOnUIThread(() -> { + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_account_wallPapers) { TLRPC.TL_account_wallPapers res = (TLRPC.TL_account_wallPapers) response; wallPapers.clear(); - wallPapers.addAll(res.wallpapers); + patterns.clear(); + allWallPapersDict.clear(); + allWallPapers.clear(); + allWallPapers.addAll(res.wallpapers); + for (int a = 0, N = res.wallpapers.size(); a < N; a++) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) res.wallpapers.get(a); + allWallPapersDict.put(wallPaper.id, wallPaper); + if (wallPaper.pattern) { + patterns.add(wallPaper); + } + if (!wallPaper.pattern || wallPaper.settings != null) { + wallPapers.add(wallPaper); + } + } fillWallpapersWithCustom(); - MessagesStorage.getInstance(currentAccount).putWallpapers(res.wallpapers, true); - }); - }); + MessagesStorage.getInstance(currentAccount).putWallpapers(res.wallpapers, 1); + } + if (progressDialog != null) { + progressDialog.dismiss(); + listView.smoothScrollToPosition(0); + } + })); ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); } @@ -473,10 +851,45 @@ public class WallpapersListActivity extends BaseFragment implements Notification } else { wallPapers.remove(catsWallpaper); } - wallPapers.add(0, catsWallpaper); if (themeWallpaper != null) { wallPapers.remove(themeWallpaper); } + boolean currentThemeDark = Theme.getCurrentTheme().isDark(); + Collections.sort(wallPapers, (o1, o2) -> { + if (o1 instanceof TLRPC.TL_wallPaper && o2 instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper wallPaper1 = (TLRPC.TL_wallPaper) o1; + TLRPC.TL_wallPaper wallPaper2 = (TLRPC.TL_wallPaper) o2; + if (wallPaper1.id == selectedBackground) { + return -1; + } else if (wallPaper2.id == selectedBackground) { + return 1; + } + int index1 = allWallPapers.indexOf(wallPaper1); + int index2 = allWallPapers.indexOf(wallPaper2); + if (wallPaper1.dark && wallPaper2.dark || !wallPaper1.dark && !wallPaper2.dark) { + if (index1 > index2) { + return 1; + } else if (index2 < index1) { + return -1; + } else { + return 0; + } + } else if (wallPaper1.dark && !wallPaper2.dark) { + if (currentThemeDark) { + return -1; + } else { + return 1; + } + } else { + if (currentThemeDark) { + return 1; + } else { + return -1; + } + } + } + return 0; + }); if (Theme.hasWallpaperFromTheme()) { if (themeWallpaper == null) { themeWallpaper = new FileWallpaper(Theme.THEME_BACKGROUND_ID, -2, -2); @@ -485,14 +898,26 @@ public class WallpapersListActivity extends BaseFragment implements Notification } else { themeWallpaper = null; } - if (selectedColor != 0) { + if (selectedBackground == -1 || selectedBackground != Theme.DEFAULT_BACKGROUND_ID && (selectedBackground < -100 || selectedBackground > 0) && allWallPapersDict.indexOfKey(selectedBackground) < 0) { + if (selectedPattern != 0) { + addedColorWallpaper = new ColorWallpaper(selectedBackground, selectedColor, selectedPattern, selectedIntensity, selectedBackgroundMotion, new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg")); + wallPapers.add(0, addedColorWallpaper); + } else if (selectedColor != 0) { + addedColorWallpaper = new ColorWallpaper(selectedBackground, selectedColor); + wallPapers.add(0, addedColorWallpaper); + } else { + addedFileWallpaper = new FileWallpaper(selectedBackground, new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"), new File(ApplicationLoader.getFilesDirFixed(), selectedBackgroundBlurred ? "wallpaper_original.jpg" : "wallpaper.jpg")); + wallPapers.add(0, addedFileWallpaper); + } + } else if (selectedColor != 0 && selectedBackground >= -100 && selectedPattern < -1) { addedColorWallpaper = new ColorWallpaper(selectedBackground, selectedColor); wallPapers.add(0, addedColorWallpaper); - } else if (selectedBackground == -1) { - addedFileWallpaper = new FileWallpaper(selectedBackground, new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg")); - wallPapers.add(0, addedFileWallpaper); } - + if (selectedBackground == Theme.DEFAULT_BACKGROUND_ID) { + wallPapers.add(0, catsWallpaper); + } else { + wallPapers.add(catsWallpaper); + } updateRows(); } @@ -514,175 +939,21 @@ public class WallpapersListActivity extends BaseFragment implements Notification } else { wallPaperStartRow = -1; } + if (currentType == TYPE_ALL) { + resetSectionRow = rowCount++; + resetRow = rowCount++; + resetInfoRow = rowCount++; + } else { + resetSectionRow = -1; + resetRow = -1; + resetInfoRow = -1; + } if (listAdapter != null) { + scrolling = true; listAdapter.notifyDataSetChanged(); } } - private void processSearch(EditText editText) { - if (editText.getText().toString().length() == 0) { - return; - } - searchResult.clear(); - searchResultKeys.clear(); - bingSearchEndReached = true; - searchImages(editText.getText().toString(), "", true); - lastSearchString = editText.getText().toString(); - if (lastSearchString.length() == 0) { - lastSearchString = null; - //if (type == 0) { - // emptyView.setText(LocaleController.getString("NoRecentPhotos", R.string.NoRecentPhotos)); - //} else if (type == 1) { - // emptyView.setText(LocaleController.getString("NoRecentGIFs", R.string.NoRecentGIFs)); - //} - } else { - //emptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); - } - updateSearchInterface(); - } - - private void updateSearchInterface() { - /*if (listAdapter != null) { - listAdapter.notifyDataSetChanged(); - } - if (searching && searchResult.isEmpty() || loadingWallpapers && lastSearchString == null) { - //emptyView.showProgress(); - } else { - //emptyView.showTextView(); - }*/ - } - - private void searchBotUser() { - if (searchingUser) { - return; - } - searchingUser = true; - TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); - req.username = MessagesController.getInstance(currentAccount).imageSearchBot; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (response != null) { - AndroidUtilities.runOnUIThread(() -> { - TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; - MessagesController.getInstance(currentAccount).putUsers(res.users, false); - MessagesController.getInstance(currentAccount).putChats(res.chats, false); - MessagesStorage.getInstance(currentAccount).putUsersAndChats(res.users, res.chats, true, true); - String str = lastSearchImageString; - lastSearchImageString = null; - searchImages(str, "", false); - }); - } - }); - } - - private void searchImages(final String query, final String offset, boolean searchUser) { - if (searching) { - searching = false; - if (imageReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); - imageReqId = 0; - } - } - - lastSearchImageString = query; - searching = true; - - TLObject object = MessagesController.getInstance(currentAccount).getUserOrChat(MessagesController.getInstance(currentAccount).imageSearchBot); - if (!(object instanceof TLRPC.User)) { - if (searchUser) { - searchBotUser(); - } - return; - } - TLRPC.User user = (TLRPC.User) object; - - TLRPC.TL_messages_getInlineBotResults req = new TLRPC.TL_messages_getInlineBotResults(); - req.query = query == null ? "" : query; - req.bot = MessagesController.getInstance(currentAccount).getInputUser(user); - req.offset = offset; - req.peer = new TLRPC.TL_inputPeerEmpty(); - - final int token = ++lastSearchToken; - imageReqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (token != lastSearchToken) { - return; - } - int addedCount = 0; - if (response != null) { - TLRPC.messages_BotResults res = (TLRPC.messages_BotResults) response; - nextImagesSearchOffset = res.next_offset; - boolean added = false; - - for (int a = 0, count = res.results.size(); a < count; a++) { - TLRPC.BotInlineResult result = res.results.get(a); - if (!"photo".equals(result.type)) { - continue; - } - if (searchResultKeys.containsKey(result.id)) { - continue; - } - - added = true; - MediaController.SearchImage bingImage = new MediaController.SearchImage(); - if (result.photo != null) { - TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, AndroidUtilities.getPhotoSize()); - TLRPC.PhotoSize size2 = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, 320); - if (size == null) { - continue; - } - bingImage.width = size.w; - bingImage.height = size.h; - bingImage.photoSize = size; - bingImage.photo = result.photo; - bingImage.size = size.size; - bingImage.thumbPhotoSize = size2; - } else { - if (result.content == null) { - continue; - } - for (int b = 0; b < result.content.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = result.content.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { - bingImage.width = attribute.w; - bingImage.height = attribute.h; - break; - } - } - if (result.thumb != null) { - bingImage.thumbUrl = result.thumb.url; - } else { - bingImage.thumbUrl = null; - } - bingImage.imageUrl = result.content.url; - bingImage.size = result.content.size; - } - - bingImage.id = result.id; - bingImage.type = 0; - bingImage.localUrl = ""; - - searchResult.add(bingImage); - - searchResultKeys.put(bingImage.id, bingImage); - addedCount++; - added = true; - } - bingSearchEndReached = !added || nextImagesSearchOffset == null; - } - searching = false; - if (addedCount != 0) { - listAdapter.notifyItemRangeInserted(searchResult.size(), addedCount); - } else if (bingSearchEndReached) { - listAdapter.notifyItemRemoved(searchResult.size() - 1); - } - if (searching && searchResult.isEmpty() || loadingWallpapers && lastSearchString == null) { - //emptyView.showProgress(); - } else { - //emptyView.showTextView(); - } - })); - ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(imageReqId, classGuid); - } - private void fixLayout() { if (listView != null) { ViewTreeObserver obs = listView.getViewTreeObserver(); @@ -720,6 +991,375 @@ public class WallpapersListActivity extends BaseFragment implements Notification //layoutManager.scrollToPosition(position); } + private class ColorCell extends View { + + private int color; + + public ColorCell(Context context) { + super(context); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(AndroidUtilities.dp(50), AndroidUtilities.dp(62)); + } + + public void setColor(int value) { + color = value; + } + + @Override + protected void onDraw(Canvas canvas) { + colorPaint.setColor(color); + canvas.drawCircle(AndroidUtilities.dp(25), AndroidUtilities.dp(31), AndroidUtilities.dp(18), colorPaint); + if (color == Theme.getColor(Theme.key_windowBackgroundWhite)) { + canvas.drawCircle(AndroidUtilities.dp(25), AndroidUtilities.dp(31), AndroidUtilities.dp(18), colorFramePaint); + } + } + } + + private class SearchAdapter extends RecyclerListView.SelectionAdapter { + + private Context mContext; + private RecyclerListView innerListView; + + private ArrayList searchResult = new ArrayList<>(); + private HashMap searchResultKeys = new HashMap<>(); + private boolean bingSearchEndReached = true; + private String lastSearchString; + private String selectedColor; + private String nextImagesSearchOffset; + private int imageReqId; + private int lastSearchToken; + private boolean searchingUser; + private String lastSearchImageString; + private Runnable searchRunnable; + + private class CategoryAdapterRecycler extends RecyclerListView.SelectionAdapter { + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = new ColorCell(mContext); + return new RecyclerListView.Holder(view); + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return true; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + ColorCell cell = (ColorCell) holder.itemView; + cell.setColor(searchColors[position]); + } + + @Override + public int getItemCount() { + return searchColors.length; + } + } + + public SearchAdapter(Context context) { + mContext = context; + } + + public RecyclerListView getInnerListView() { + return innerListView; + } + + public void onDestroy() { + if (imageReqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); + imageReqId = 0; + } + } + + public void clearColor() { + selectedColor = null; + processSearch(null, true); + } + + private void processSearch(String text, boolean now) { + if (text != null && selectedColor != null) { + text = "#color" + selectedColor + " " + text; + } + if (searchRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(searchRunnable); + searchRunnable = null; + } + if (TextUtils.isEmpty(text)) { + searchResult.clear(); + searchResultKeys.clear(); + bingSearchEndReached = true; + lastSearchString = null; + if (imageReqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); + imageReqId = 0; + } + searchEmptyView.showTextView(); + } else { + searchEmptyView.showProgress(); + final String textFinal = text; + if (now) { + doSearch(textFinal); + } else { + searchRunnable = () -> { + doSearch(textFinal); + searchRunnable = null; + }; + AndroidUtilities.runOnUIThread(searchRunnable, 500); + } + } + notifyDataSetChanged(); + } + + private void doSearch(String textFinal) { + searchResult.clear(); + searchResultKeys.clear(); + bingSearchEndReached = true; + searchImages(textFinal, "", true); + lastSearchString = textFinal; + notifyDataSetChanged(); + } + + private void searchBotUser() { + if (searchingUser) { + return; + } + searchingUser = true; + TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); + req.username = MessagesController.getInstance(currentAccount).imageSearchBot; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (response != null) { + AndroidUtilities.runOnUIThread(() -> { + TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + MessagesStorage.getInstance(currentAccount).putUsersAndChats(res.users, res.chats, true, true); + String str = lastSearchImageString; + lastSearchImageString = null; + searchImages(str, "", false); + }); + } + }); + } + + public void loadMoreResults() { + if (bingSearchEndReached || imageReqId != 0) { + return; + } + searchImages(lastSearchString, nextImagesSearchOffset, true); + } + + private void searchImages(final String query, final String offset, boolean searchUser) { + if (imageReqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); + imageReqId = 0; + } + lastSearchImageString = query; + + TLObject object = MessagesController.getInstance(currentAccount).getUserOrChat(MessagesController.getInstance(currentAccount).imageSearchBot); + if (!(object instanceof TLRPC.User)) { + if (searchUser) { + searchBotUser(); + } + return; + } + TLRPC.User user = (TLRPC.User) object; + + TLRPC.TL_messages_getInlineBotResults req = new TLRPC.TL_messages_getInlineBotResults(); + req.query = "#wallpaper " + query; + req.bot = MessagesController.getInstance(currentAccount).getInputUser(user); + req.offset = offset; + req.peer = new TLRPC.TL_inputPeerEmpty(); + + final int token = ++lastSearchToken; + imageReqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (token != lastSearchToken) { + return; + } + imageReqId = 0; + int oldCount = searchResult.size(); + if (response != null) { + TLRPC.messages_BotResults res = (TLRPC.messages_BotResults) response; + nextImagesSearchOffset = res.next_offset; + + for (int a = 0, count = res.results.size(); a < count; a++) { + TLRPC.BotInlineResult result = res.results.get(a); + if (!"photo".equals(result.type)) { + continue; + } + if (searchResultKeys.containsKey(result.id)) { + continue; + } + + MediaController.SearchImage bingImage = new MediaController.SearchImage(); + if (result.photo != null) { + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, AndroidUtilities.getPhotoSize()); + TLRPC.PhotoSize size2 = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, 320); + if (size == null) { + continue; + } + bingImage.width = size.w; + bingImage.height = size.h; + bingImage.photoSize = size; + bingImage.photo = result.photo; + bingImage.size = size.size; + bingImage.thumbPhotoSize = size2; + } else { + if (result.content == null) { + continue; + } + for (int b = 0; b < result.content.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = result.content.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { + bingImage.width = attribute.w; + bingImage.height = attribute.h; + break; + } + } + if (result.thumb != null) { + bingImage.thumbUrl = result.thumb.url; + } else { + bingImage.thumbUrl = null; + } + bingImage.imageUrl = result.content.url; + bingImage.size = result.content.size; + } + + bingImage.id = result.id; + bingImage.type = 0; + bingImage.localUrl = ""; + + searchResult.add(bingImage); + + searchResultKeys.put(bingImage.id, bingImage); + } + bingSearchEndReached = oldCount == searchResult.size() || nextImagesSearchOffset == null; + } + if (oldCount != searchResult.size()) { + int prevLastRow = oldCount % columnsCount; + int oldRowCount = (int) Math.ceil(oldCount / (float) columnsCount); + if (prevLastRow != 0) { + notifyItemChanged((int) Math.ceil(oldCount / (float) columnsCount) - 1); + } + int newRowCount = (int) Math.ceil(searchResult.size() / (float) columnsCount); + searchAdapter.notifyItemRangeInserted(oldRowCount, newRowCount - oldRowCount); + } + searchEmptyView.showTextView(); + })); + ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(imageReqId, classGuid); + } + + @Override + public int getItemCount() { + if (TextUtils.isEmpty(lastSearchString)) { + return 2; + } + return (int) Math.ceil(searchResult.size() / (float) columnsCount); + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() != 2; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = null; + switch (viewType) { + case 0: + view = new WallpaperCell(mContext) { + @Override + protected void onWallpaperClick(Object wallPaper, int index) { + presentFragment(new WallpaperActivity(wallPaper, null)); + } + }; + break; + case 1: + RecyclerListView horizontalListView = new RecyclerListView(mContext) { + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (getParent() != null && getParent().getParent() != null) { + getParent().getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onInterceptTouchEvent(e); + } + }; + horizontalListView.setItemAnimator(null); + horizontalListView.setLayoutAnimation(null); + LinearLayoutManager layoutManager = new LinearLayoutManager(mContext) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }; + horizontalListView.setPadding(AndroidUtilities.dp(7), 0, AndroidUtilities.dp(7), 0); + horizontalListView.setClipToPadding(false); + layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + horizontalListView.setLayoutManager(layoutManager); + horizontalListView.setAdapter(new CategoryAdapterRecycler()); + horizontalListView.setOnItemClickListener((view1, position) -> { + String color = LocaleController.getString("BackgroundSearchColor", R.string.BackgroundSearchColor); + Spannable spannable = new SpannableString(color + " " + LocaleController.getString(searchColorsNames[position], searchColorsNamesR[position])); + spannable.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_actionBarDefaultSubtitle)), color.length(), spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + searchItem.setSearchFieldCaption(spannable); + searchItem.setSearchFieldHint(null); + searchItem.setSearchFieldText("", true); + selectedColor = searchColorsNames[position]; + processSearch("", true); + }); + view = horizontalListView; + innerListView = horizontalListView; + break; + case 2: + view = new GraySectionCell(mContext); + break; + } + if (viewType == 1) { + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(60))); + } else { + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); + } + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + WallpaperCell wallpaperCell = (WallpaperCell) holder.itemView; + position *= columnsCount; + int totalRows = (int) Math.ceil(searchResult.size() / (float) columnsCount); + wallpaperCell.setParams(columnsCount, position == 0, position / columnsCount == totalRows - 1); + for (int a = 0; a < columnsCount; a++) { + int p = position + a; + Object wallPaper = p < searchResult.size() ? searchResult.get(p) : null; + wallpaperCell.setWallpaper(currentType, a, wallPaper, 0, null, false); + } + break; + } + case 2: { + GraySectionCell cell = (GraySectionCell) holder.itemView; + cell.setText(LocaleController.getString("SearchByColor", R.string.SearchByColor)); + break; + } + } + } + + @Override + public int getItemViewType(int position) { + if (TextUtils.isEmpty(lastSearchString)) { + if (position == 0) { + return 2; + } else { + return 1; + } + } + return 0; + } + } + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -748,23 +1388,31 @@ public class WallpapersListActivity extends BaseFragment implements Notification } case 1: { view = new ShadowSectionCell(mContext); + Drawable drawable = Theme.getThemedDrawable(mContext, wallPaperStartRow == -1 ? R.drawable.greydivider_bottom : 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 3: { + view = new TextInfoPrivacyCell(mContext); + Drawable drawable = Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow); + CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), drawable); + combinedDrawable.setFullsize(true); + view.setBackgroundDrawable(combinedDrawable); break; } case 2: default: { view = new WallpaperCell(mContext) { @Override - protected void onWallpaperClick(Object wallPaper) { - WallpaperActivity wallpaperActivity = new WallpaperActivity(wallPaper, null); - if (currentType == TYPE_COLOR) { - wallpaperActivity.setDelegate(WallpapersListActivity.this::removeSelfFromStack); - } - presentFragment(wallpaperActivity); + protected void onWallpaperClick(Object wallPaper, int index) { + onItemClick(this, wallPaper, index); } @Override - protected void onWallpaperLongClick(Object wallPaper) { - //presentFragment(new WallpaperActivity(wallPaper, null)); + protected boolean onWallpaperLongClick(Object wallPaper, int index) { + return onItemLongClick(this, wallPaper, index); } }; break; @@ -779,27 +1427,22 @@ public class WallpapersListActivity extends BaseFragment implements Notification case 0: { TextCell textCell = (TextCell) holder.itemView; if (position == uploadImageRow) { - if (disableFeatures) { - textCell.setTextAndIcon(LocaleController.getString("SelectImage", R.string.SelectImage), R.drawable.profile_photos, true); - } else { - textCell.setTextAndIcon(LocaleController.getString("UploadImage", R.string.UploadImage), R.drawable.profile_photos, true); - } + textCell.setTextAndIcon(LocaleController.getString("SelectFromGallery", R.string.SelectFromGallery), R.drawable.profile_photos, true); } else if (position == setColorRow) { textCell.setTextAndIcon(LocaleController.getString("SetColor", R.string.SetColor), R.drawable.menu_palette, false); + } else if (position == resetRow) { + textCell.setText(LocaleController.getString("ResetChatBackgrounds", R.string.ResetChatBackgrounds), false); } break; } - case 1: { - View sectionCell = holder.itemView; - sectionCell.setTag(position); - Drawable drawable = Theme.getThemedDrawable(mContext, wallPaperStartRow == -1 ? R.drawable.greydivider_bottom : R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow); - CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), drawable); - combinedDrawable.setFullsize(true); - sectionCell.setBackgroundDrawable(combinedDrawable); + case 3: { + TextInfoPrivacyCell cell = (TextInfoPrivacyCell) holder.itemView; + if (position == resetInfoRow) { + cell.setText(LocaleController.getString("ResetChatBackgroundsInfo", R.string.ResetChatBackgroundsInfo)); + } break; } - case 2: - default: { + case 2: { WallpaperCell wallpaperCell = (WallpaperCell) holder.itemView; position = (position - wallPaperStartRow) * columnsCount; wallpaperCell.setParams(columnsCount, position == 0, position / columnsCount == totalWallpaperRows - 1); @@ -807,6 +1450,18 @@ public class WallpapersListActivity extends BaseFragment implements Notification int p = position + a; Object wallPaper = p < wallPapers.size() ? wallPapers.get(p) : null; wallpaperCell.setWallpaper(currentType, a, wallPaper, selectedBackground, null, false); + long id; + if (wallPaper instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper object = (TLRPC.TL_wallPaper) wallPaper; + id = object.id; + } else { + id = 0; + } + if (actionBar.isActionModeShowed()) { + wallpaperCell.setChecked(a, selectedWallPapers.indexOfKey(id) >= 0, !scrolling); + } else { + wallpaperCell.setChecked(a, false, !scrolling); + } } break; } @@ -815,10 +1470,12 @@ public class WallpapersListActivity extends BaseFragment implements Notification @Override public int getItemViewType(int position) { - if (position == uploadImageRow || position == setColorRow) { + if (position == uploadImageRow || position == setColorRow || position == resetRow) { return 0; - } else if (position == sectionRow) { + } else if (position == sectionRow || position == resetSectionRow) { return 1; + } else if (position == resetInfoRow) { + return 3; } else { return 2; } @@ -828,7 +1485,8 @@ public class WallpapersListActivity extends BaseFragment implements Notification @Override public ThemeDescription[] getThemeDescriptions() { return new ThemeDescription[]{ - new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite), + new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_windowBackgroundWhite), + new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_windowBackgroundGray), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault), @@ -837,6 +1495,24 @@ public class WallpapersListActivity extends BaseFragment implements Notification new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), + + new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGray), + new ThemeDescription(listView, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4), + + new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGray), + + new ThemeDescription(listView, 0, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(listView, 0, new Class[]{TextCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteValueText), + new ThemeDescription(listView, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon), + + new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_graySectionText), + new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{GraySectionCell.class}, null, null, null, Theme.key_graySection), + + new ThemeDescription(searchEmptyView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_emptyListPlaceholder), + new ThemeDescription(searchEmptyView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_progressCircle), + new ThemeDescription(searchEmptyView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite), }; } } diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 8a49da2e8..78ae90347 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -49,7 +49,7 @@ رمز الدخول هو **%1$s**. قم بإدخاله في تطبيق تيليجرام الذي تحاول تسجيل الدخول منه.\n\nلا تعطِ هذا الرمز لأي شخص كان. اسمك - Please enter your full name and upload your profile picture. + يرجى إدخال اسمك الكامل ورفع صورتك الشخصية. الاسم الأول (مطلوب) اسم العائلة (اختياري) إلغاء التسجيل @@ -143,7 +143,7 @@ انضم %s لمحادثتك السرية. لقد انضممت للمحادثة السرية مسح محتوى المحادثة - History cleared. + تم مسح المحتوى. تم حذف المحادثة. تم حذف المجموعة. تم حذف القناة. @@ -193,7 +193,7 @@ ترقية إلى مشرف تعديل صلاحيات المشرف - لا يوجد مستخدمون محظورون + ما من مستخدمين تمت إزالتهم حذف المجموعة مغادرة المجموعة حذف المجموعة @@ -226,8 +226,8 @@ ثبت un1 ملفًا صوتيًا تمّت ترقية هذه المجموعة إلى مجموعة خارقة تمت ترقية %1$s إلى مجموعة خارقة - Users removed from the group by the admins can\'t rejoin via invite links. - Users removed from the channel by the admins can\'t rejoin via invite links. + لن يتمكن المستخدمون الذين أزالهم المشرفون من المجموعة إعادة الإنضمام عبر روابط الدعوة. + لن يتمكن المستخدمون الذين أزالهم المشرفون من القناة إعادة الإنضمام عبر روابط الدعوة. قناة جديدة اسم القناة إضافة جهات اتصالك لقناتك @@ -239,8 +239,8 @@ الوصف (اختياري) الوصف يمكنك إضافة وصف اختياري لقناتك. - You have changed some settings in this group. Apply changes? - You have changed some settings in this channel. Apply changes? + لقد قمت بتغيير بعض الإعدادات في هذه المجموعة. تطبيق التغييرات؟ + لقد قمت بتغيير بعض الإعدادات في هذه القناة. تطبيق التغييرات؟ قناة عامة مجموعة عامة يمكن العثور على القنوات العامة عبر البحث ويمكن لأي شخص الانضمام لها. @@ -249,7 +249,7 @@ مجموعة خاصة يمكن الانضمام للقنوات الخاصة عن طريق رابط الدعوة فقط. يمكن الانضمام للمجموعات الخاصة فقط في حال تمت دعوتك أو بواسطة رابط دعوة. - الرابط + رابط دائم رابط الدعوة إضافة أعضاء مغادرة القناة @@ -272,22 +272,22 @@ %1$s متاح. أعضاء إضافة إلى المجموعة - Add to channel + إضافة إلى القناة حذف من هذه القائمة "المشتركون " - المحظورون + مستخدمون تمت إزالتهم الصلاحيات ما هي صلاحيات أعضاء هذه المجموعة؟ إضافة استثناء - Search Exceptions - المستخدمون المحظورون + بحث في الاستثناءات + مستخدمون تمت إزالتهم المستخدمون المقيدون المشرفون حذف القناة حذف القناة مهلا! حذف هذه القناة سيزيل كافة أعضائها ويَحذف جميعَ رسائلها، هل ترغب حقًا في حذفها؟ هل ترغب حقًا في مغادرة القناة؟ - Are you sure you want to leave **%1$s**? + هل ترغب حقًا في مغادرة **%1$s**؟ ستَفقد كافة المنشورات في هذه القناة. تعديل فضلًا قم باختيار رابط لقناتك العامة ليتمكن الناس من إيجادها عبر البحث ومشاركتِها مع غيرهم.\n\nإذا لم ترغب بذلك، ننصحك بإنشاء قناة خاصة بدلا منها. @@ -301,12 +301,12 @@ كتم إلغاء الكتم إضافة مشرف - حظر مستخدم + إزالة مستخدم إلغاء الحظر اضغط باستمرار على المستخدم لرفع الحظر عنه الدعوة عبر رابط خاص إزالة المشرف - Edit permissions + تعديل الصلاحيات يمكن لمشرفي القناة فقط مشاهدة هذه القائمة. يمكن لمستخدمي تيليجرام الانضمام إلى قناتك عبر هذا الرابط. يمكنك إضافة مشرفين لمساعدتك في إدارة القناة، اضغط مطوَّلا على أيٍّ منهم لحذفه. @@ -361,13 +361,15 @@ إزالة المشرف حظر المستخدمين إضافة مستخدمين - دعوة مستخدمين من خلال الرابط + دعوة المستخدمين عبر الرابط تثبيت الرسائل - قام %1$s بإضافته + تمت ترقيته من قبل %1$s لا يمكنك تعديل صلاحيات هذا المشرف. - Removed by %1$s + لا يمكنك تعديل هذه الصلاحية. + هذه الصلاحية ليست متوفرة في المجموعات العامة. + تمت إزالته من قبل %1$s صلاحيات المستخدم - This option is disabled for all members in Group Permissions + تم تعطيل هذا الخيار لجميع الأعضاء في صلاحيات المجموعة. ما هي صلاحيات هذا المستخدم؟ قراءة الرسائل إرسال الرسائل @@ -375,18 +377,18 @@ إرسال الاستفتاءات إرسال الملصقات والصور المتحركة تضمين روابط - Change Chat Info - Pin Messages - Add Users - can\'t read - can\'t send messages + تغيير معلومات المحادثة + تثبيت الرسائل + إضافة مستخدمين + لا يمكنه قراءة الرسائل + لا يمكنه إرسال الرسائل بلا وسائط بلا استفتاءات - no stickers & GIFs - no embed links - can\'t change Info - no pins - can\'t add users + بلا ملصقات وصور متحركة + لا يمكنه تضمين روابط + لا يمكنه تغيير معلومات المجموعة + بلا تثبيت + لا يمكنه إضافة مستخدمين المدة للأبد حظر وإزالة من المجموعة @@ -420,10 +422,10 @@ اختيار من المعرض البحث في الويب الإحصائيات - Bots can only be added as administrators. - Sorry, bots can only be added to channels as administrators. - MAKE ADMIN - %1$s will be removed from admins if you restrict them. + يمكن إضافة البوتات فقط كمشرفين. + المعذرة، يمكن إضافة البوتات إلى القنوات فقط كمشرفين. + جعله مشرفًا + سيتم إزالة %1$s من المشرفين إذا قمت بتقييده. استفتاء جديد استفتاء @@ -507,12 +509,12 @@ un1 عطّل دعوات المجموعة فعّل un1 التواقيع عطّل un1 التواقيع - غير القيود الخاصة بـ %1$s\n\nلمدة: %2$s - changed default permissions + غيّر صلاحيات %1$s\n\nالمدة: %2$s + غيّر الصلاحيات الافتراضية إرسال الملصقات والصور المتحركة إرسال الوسائط تغيير المعلومات - Add users + إضافة مستخدمين تثبيت الرسائل إرسال الاستفتاءات إرسال الرسائل @@ -529,7 +531,7 @@ إضافة مستخدمين تثبيت الرسائل كافة الأحداث - قيود جديدة + استثناءات جديدة مشرفون جدد أعضاء جدد معلومات المجموعة @@ -701,7 +703,7 @@ أنت قمت بإنشاء **مجموعة**. يمكن للمجموعات: - إحتواء حتى 100,000 عضو + إحتواء حتى 200,000 عضو إمتلاك سجل محادثة موحّد إمتلاك روابط t.me عامة إمتلاك مشرفين بصلاحيات مختلفة @@ -729,9 +731,9 @@ مشرفو هذه المجموعة قيدوك من إرسال محتوى استعلامي إليها قام مشرفو هذه المجموعة بتقييدك من إرسال الملصقات. قام مشرفو هذه المجموعة بتقييدك من الكتابة هنا. - Sending media isn’t allowed in this group. - Inline bots aren’t allowed in this group. - Stickers aren’t allowed in this group. + ليس من المسموح إرسال الوسائط إلى هذه المجموعة. + ليس من المسموح إرسال أي محتوى استعلامي إلى هذه المجموعة. + ليس من المسموح إرسال الملصقات إلى هذه المجموعة. ليس من المسموح إرسال الرسائل إلى هذه المجموعة. مشرف "تثبيت ملفات APK محظور لهذا التطبيق، يمكنك السماح بهذا من إعدادات النظام. " @@ -871,8 +873,8 @@ شارك تيليجرام... هل ترغب في تحديث جهات الاتصال؟ اكتشف تيليجرام العديد من جهات الاتصال غير المزامَنة، هل ترغب في مزامنتها الآن؟ اختر «نعم» إذا كنت تستخدم جهازك الخاص وشريحتك وحساب جوجل الخاص بك. - مفروزة حسب الاسم - مفروزة حسب تاريخ آخر ظهور + مرتبة حسب الاسم + مرتبة حسب تاريخ آخر ظهور إضافة أشخاص... ستتمكن من إضافة أعضاء أكثر إذا انتهيت من إنشاء المجموعة وقمت بتحويلها إلى مجموعة خارقة. @@ -906,7 +908,7 @@ حظر من المجموعة مغادرة المجموعة وحذفها الإشعارات - Change permissions + تغيير صلاحيات العضو إزالة من المجموعة قم بالتحديث لمجموعة خارقة تحويل إلى مجموعة خارقة @@ -975,7 +977,7 @@ حدث خطأ ما. الملصقات والأقنعة - إضافة ملصق + إضافة الملصقات إضافة أقنعة إضافة إلى الملصقات إضافة للمفضلة @@ -1020,6 +1022,7 @@ النمط الوضع الليلي الآلي + Off معطّل مجدول تلقائي @@ -1041,16 +1044,18 @@ أغلق المحرر حفظ النمط نمط جديد + لون النمط + CREATE THEME تطبيق معاينة النمط اختر لونًا - إنشاء نمط جديد + Create new theme اضغط على أيقونة الألوان لاستعراض قائمة الخيارات في كل شاشة - ثم قم بتعديلها. - يمكنك إنشاء نمطك الخاص لتغيير الألوان داخل التطبيق. يمكنك العودةُ دائمًا لنمط تيليجرام الافتراضي من هنا. + You can create your own theme by changing colors within the app.\n\nYou can always switch back to the default Telegram theme here. تم تعيين كل الإشعارات إلى الوضع الافتراضي هل ترغب حقًا في إعادة تعيين جميع إعدادات الإشعارات إلى الوضع الافتراضي؟ - حجم خط الرسائل + حجم خط الرسائل اسأل سؤالًا تفعيل المؤثرات البصرية إعدادات المحادثات @@ -1108,14 +1113,45 @@ افتراضي الدعم فقط في وضع الصامت - Blurred - Motion - خلفية الدردشة + تأثير ضبابي + تأثير حركي + خلفية المحادثة + إعادة تعيين الخلفيات + لإزالة جميع الخلفيات المرفوعة وإستعادة الخلفيات الإفتراضية لجميع الأنماط. + هل ترغب حقًا في إعادة تعيين كافة خلفيات المحادثة؟ + Are you sure you want to delete the selected backgrounds? معاينة الخلفية - Hint: some background images look better with blur effect. + ملحوظة: بعض الخلفيات تصبح أجمل عند إضافة التأثير الضبابي. شكرًا لك! - SET BACKGROUND - Select a color + اسحب لليمين أو لليسار لرؤية المزيد من الألوان. + يابدع الورد .. يا جمال الورد + Reinhardt, we need to find you some new tunes 🎶. + Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff! + I can\'t even take you seriously right now. + Press \'Set\' to apply the background. + Enjoy the view. + تعيين كخلفية + بحث بواسطة اللون + البحث عن خلفيات + اللون: + Brightness + Hex color code + Color + نقش + Intensity + الأزرق + الأحمر + البرتقالي + الأصفر + الأخضر + الأخضر الفاتح + القرمزي + الزهري + البني + الأسود + الرمادي + الأبيض + اختيار لون رفع صورة تحديد صورة يتم تحميل الصورة... @@ -1152,7 +1188,7 @@ إعادة تشغيل التطبيق عند إيقافه. قم بالتفعيل لضمان ظهور الإشعارات. الاتصال في الخلفية البقاء على اتصال طفيف مع تيليجرام في الخلفية لضمان ظهور الإشعارات. - فرز حسب + ترتيب حسب استيراد جهات الاتصال الاسم الأول اسم العائلة @@ -1317,7 +1353,7 @@ المعلومات المطلوبة المعلومات المضافة ماهو جواز تيليجرام؟ - With Telegram Passport you can easily sign up for websites and services that require identity verification.\n\nYour information, personal data, and documents are protected by end-to-end encryption. Nobody, including Telegram, can access them without your permission.\n\nYou can visit our *FAQ* to learn more. + مع جواز تيليجرام يمْكنك التسجيل في المواقع والخدمات التي تتطلب توثيق الهوية الشخصية بسهولة.\n\nمعلوماتك، بياناتك الشخصية ووثائقك محمية ومشفرة من البداية للنهاية. لا أحد بما فيهم تيليجرام ذاتُه يمكنه الوصول إليها دون إذنك. \n\nلمزيد من التفاصيل يمكنك زيارة *الأسئلة الشائعة*. https://telegram.org/faq/ar#i7 "يرجى إنشاء كلمة مرور لحماية بياناتك الشخصية باستخدام التشفير من البداية للنهاية.\n\nستُطلب كلمة المرور هذه في كل مرة تقوم فيها بتسجيل الدخول لجهازٍ جديد. " إنشاء كلمة مرور @@ -1544,10 +1580,22 @@ مستشعر اللمس لم يتم التعرف على البصمة. حاول مرة أخرى. عرض المحتوى عند التبديل بين التطبيقات - إن تم التفعيل، ستتمكن من تصوير الشاشة داخل التطبيق، لكن سيعرض النظام محادثاتك في شاشة تعدد المهام حتى في حال تفعيل رمز القفل.\n\nقد تحتاج لإعادة تشغيل التطبيق ليتم تفعيل هذا الخيار. - This will hide the contents of your chats or chat list from the task switcher, but you will not be able to take screenshots on Telegram.\n\nYou may need to restart the app for this to take effect. + إن تم التعطيل، لن تتمكن من تصوير الشاشة داخل التطبيق، لكن سيتم إخفاء محتوى المحادثات في شاشة تعدد المهام. + سيؤدي هذا لإخفاء محتوى محادثاتك من شاشة تعدد المهام، لكن بالمقابل لن تتمكن من أخذ لقطات الشاشة في تيليجرام.\n\nقد تحتاج لإعادة تشغيل التطبيق ليتم تفعيل هذا الخيار. محاولات عديدة.\nأعد المحاولة خلال %1$s. + يناير + فبراير + مارس + أبريل + مايو + يونيو + يوليو + أغسطس + سبتمبر + أكتوبر + نوفمبر + ديسمبر ملفات وسائط روابط @@ -1612,6 +1660,7 @@ المعرض كافة الصور كافة الوسائط + جميع المقاطع المرئية لا توجد صور بعد فضلًا، قم بتنزيل الوسائط أولًا يرجى الانتظار إلى حين اكتمال تنزيل المقطع المرئي. @@ -1974,9 +2023,9 @@ هل ترغب حقًا في إنشاء محادثة سرية؟ هل ترغب حقًا في إلغاء التسجيل؟ هل ترغب حقًا في إيقاف عملية التحقق من رقم الهاتف؟ - هل ترغب حقًا في حذف محتوى المحادثة مع **%1$s**؟ - Are you sure you want to clear your secret chat history with **%1$s**? - Are you sure you want to clear the chat history in **%1$s**? + هل ترغب حقًا في مسح محتوى المحادثة مع **%1$s**؟ + هل ترغب حقًا في مسح محتوى المحادثة السرية مع **%1$s**؟ + هل ترغب حقًا في مسح محتوى محادثة **%1$s**؟ هل ترغب حقًا في مسح محتوى المحادثة؟ حذف كافة المحادثات والوسائط المتعلقة بهذه القناة من الذاكرة المؤقتة؟ حذف جميع الرسائل والوسائط المخزنة مؤقتًا من هذه المجموعة؟ @@ -2002,9 +2051,9 @@ المعذرة، مشرفو هذه المجموعة قيدوك من إرسال الملصقات. المعذرة، قام مشرفو هذه المجموعة بتقييدك من إرسال الوسائط. Sorry, the admins of this group have restricted you from sending polls. - Sorry, sending stickers is not allowed in this group. - Sorry, sending media is not allowed in this group. - Sorry, sending polls is not allowed in this group. + المعذرة، ليس من المسموح إرسال الملصقات إلى هذه المجموعة. + المعذرة، ليس من المسموح إرسال الوسائط إلى هذه المجموعة. + المعذرة، ليس من المسموح إرسال الاستفتاءات إلى هذه المجموعة. نحن متأسفون للغاية، ولكن هذا يعني أنه لا يمكنك الاشتراك بتيليجرام.\n\nعلى عكس الآخرين، نحن لا نستخدم بياناتك لاستهدافك بالإعلانات أو لأغراض تجارية أخرى. لا يخزن تيليجرام سوى المعلومات التي يحتاجها ليعمل كخدمة سحابية غنية بالميزات. يمكنك ضبط كيفية استخدامنا لبياناتك (مثل إعدادات حذف الجهات المزامَنة) في إعدادات الخصوصية والأمان.\n\nلكن إن كنت غير موافق على احتياجات تيليجرام المتواضعة بشكل عام، فلن يكون من الممكن لنا تقديم هذه الخدمة. التحقق من العمر سياسة الخصوصية وشروط الخدمة @@ -2099,7 +2148,7 @@ قيم المكالمة ماذا حدث؟ تضمين المعلومات التقنية - هذا لن يفصح عن محتوى محادثتك، لكن سيساعد في حل المشكلة بشكل أسرع. + لن تفصح عن محتوى محادثتك وستساعدنا على حل المشكلة بشكل أسرع. شكرًا لمساهمتك في تحسين مكالمات تيليجرام. سيتم الرد باسم %s الرد برسالة @@ -2112,13 +2161,13 @@ السماح برسائل مخصصة مكالمة تيليجرام مع %s لا يمكن إجراء مكالمة تيليجرام حاليًا. - I heard my own voice - I heard background noise - The other side kept disappearing - Speech was distorted + سمعتُ صوتي + سمعت ضوضاء في الخلفية + كان صوت الشخص الآخر يختفي + لم يكن الكلام واضحًا لم أتمكن من سماع الطرف الآخر - The other side couldn\'t hear me - Call ended unexpectedly + لم يسمعني الطرف الآخر + انتهت المكالمة فجأة لا يوجد مستقبلون مستقبل واحد @@ -2288,12 +2337,12 @@ %1$d استثناءات %1$d استثناء %1$d استثناء - %1$d removed users - %1$d removed user - %1$d removed users - %1$d removed users - %1$d removed users - %1$d removed users + %1$d مستخدم تمت إزالته + مستخدمٌ واحد تمت إزالته + مستخدمين إثنين تمت إزالتهم + %1$d مستخدمين تمت إزالتهم + %1$d مستخدمًا تمت إزالتهم + %1$d مستخدم تمت إزالته %1$d %1$d %1$d diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index 9b5d9b4b9..e4f883032 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -363,8 +363,10 @@ Nutzer hinzufügen Nutzer per Link einladen Nachrichten anheften - Hinzugefügt von %1$s + Befördert von %1$s Du kannst die Rechte dieses Admins nicht bearbeiten. + Diese Berechtigung kannst du nicht bearbeiten. + Diese Berechtigung ist in öffentlichen Gruppen nicht verfügbar. Entfernt von %1$s Nutzerberechtigungen In den Gruppenberechtigungen ist diese Option für alle deaktiviert worden @@ -529,7 +531,7 @@ Nutzer hinzufügen Nachrichten anheften Alle Aktionen - Neue Ausnahme + Neue Ausnahmen Neue Admins Neue Mitglieder Gruppen-Info @@ -701,7 +703,7 @@ Du Du hast eine **Gruppe** erstellt Gruppen bieten: - Platz für bis zu 100.000 Mitglieder + Platz für bis zu 200.000 Mitglieder Dauerhaften Chat-Verlauf Öffentliche Links, wie t.me/title Admins mit unterschiedlichen Rechten @@ -1020,6 +1022,7 @@ Thema Auto-Nachtmodus + Aus Aus Geplant Automatisch @@ -1040,17 +1043,19 @@ Einen Namen festlegen EDITOR SCHLIESSEN THEMA SPEICHERN - Neues Thema + Neues Farbthema + Farbthema + THEMA ERSTELLEN ANWENDEN Vorschau Farbe wählen - Neues Thema erstellen + Neues Thema erstellen Tippe auf das kleine Palettensymbol um eine Auswahl des jeweiligen Bildschirms anzuzeigen und wähle deine Wunschfarben. - Erstelle dein eigenes Thema, indem du die Farben innerhalb der App änderst. Hier kannst du jederzeit zum vorgegebenen Telegram Thema zurückwechseln. + Du kannst dein eigenes Farbthema erstellen, indem du die Farben innerhalb der App änderst.\n\nJederzeit kannst du hier zum Standard-Farbthema von Telegram zurückkehren. Alle Einstellungen für Mitteilungen zurücksetzen Möchtest du wirklich alle Benachrichtigungseinstellungen auf die Standardeinstellungen zurücksetzen? - Textgröße für Nachrichten + Textgröße für Nachrichten Eine Frage stellen Animationen aktivieren Chat-Einstellungen @@ -1111,10 +1116,41 @@ Unscharf Bewegung Chat-Hintergrundbild + Chat-Hintergrundbilder zurücksetzen + Das löscht alle hochgeladenen Chat-Hintergründe und stellt die vorinstallierten Hintergründe für alle Themen wieder her. + Möchtest du wirklich alle Chat-Hintergründe zurücksetzen? + Möchtest du wirklich die ausgewählten Hintergründe löschen? Hintergrundvorschau Tipp: Einige Bilder sehen unscharf besser aus. - Vielen Dank! + Juhu, danke. Das wird mein Leben verändern. + Für mehr Farben, nach links oder rechts wischen. + Lachs ist ein Fisch, keine Farbe. + Reinhardt, wir müssen dir unbedingt... + Oh je, ihr mit eurer Techno-Musik! Genießt lieber Klassiker, wie Hasselhoff! + Nicht wirklich dein Ernst, oder? + \'Festlegen\' antippen, um den Hintergrund anzuwenden. + Genieße die Ansicht HINTERGRUND FESTLEGEN + Nach Farbe suchen + Hintergrund suchen + Farbe: + Helligkeit + Hex-Farbcode + Farbe + Muster + Sichtbarkeit + Blau + Rot + Orange + Gelb + Grün + Blaugrün + Violett + Rosa + Braun + Schwarz + Grau + Weiß Wähle eine Farbe Bild hochladen Bild auswählen @@ -1544,10 +1580,22 @@ Berührungssensor Fingerabdruck wurde nicht erkannt. Bitte erneut versuchen. App-Inhalte nach Sperrung anzeigen - Wenn du diese Funktion deaktivierst, wird du keine Bildschirmfotos mehr in der App aufnehmen können und Chatinhalte werden in der Liste der geöffneten App ausgeblendet. + Wenn du diese Funktion deaktivierst, wirst du keine Bildschirmfotos mehr in der App aufnehmen können und Chatinhalte werden in der Liste der geöffneten App ausgeblendet. Das wird die Inhalte der Chatliste oder Chats in der Liste der geöffneten Apps verstecken, du wirst jedch keine Bildschirmfotos aufnehmen können. \n\nDu wirst die App nach der Änderung neu starten müssen. Zu viele Versuche.\nBitte erneut in %1$s versuchen. + Januar + Februar + März + April + Mai + Juni + Juli + August + September + Oktober + November + Dezember DATEIEN MEDIEN LINKS @@ -1612,6 +1660,7 @@ Galerie Alle Bilder Alle Medien + Alle Videos Noch keine Bilder Medien bitte zuerst herunterladen Bitte warte, bis das Video vollständig heruntergeladen wurde. @@ -1974,7 +2023,7 @@ Geheimen Chat starten? Bist du dir sicher, dass du die Registrierung abbrechen willst? "Möchtest du wirklich den Verifikationsvorgang stoppen? " - Wirklich deinen Verlauf with **%1$s** leeren? + Wirklich deinen Verlauf mit **%1$s** leeren? Wirklich den geheimen Verlauf bei dir und **%1$s** leeren? Wirklich den Verlauf mit **%1$s** leeren? Möchtest du wirklich den Verlauf löschen? @@ -2098,8 +2147,8 @@ Wenn diese Emoji genau so bei %1$s aussehen, ist euer Anruf 100%% sicher. Anruf bewerten Was klappte nicht? - Technische Infos senden - Das hilft uns das Problem schneller zu beseitigen. Die Inhalte deiner Konversation werden nicht angezeigt. + Technische Infos mitsenden + Wird die Inhalte deiner Chats nicht anzeigen und hilft uns das Problem schneller zu beseitigen. Danke, dass du uns hilfst, Telegram-Anrufe zu verbessern. Mit %s beantworten Mit Nachricht antworten @@ -2114,11 +2163,11 @@ Telegram-Anruf kann im Moment nicht geführt werden. Ich hörte ein Echo Ich hörte Rauschen - Die andere Seite war zwischendurch nicht zu hören + Partner war nicht immer zu hören Sprache klang verzerrt - Ich konnte die andere Seite nicht hören - Die andere Seite konnte mich nicht hören - Anruf wurde unerwartet beendet + Ich konnte nichts hören + Ich konnte nicht gehört werden + Anruf unerwartet beendet %1$d Empfänger %1$d Empfänger diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index e1f4500bc..cd6f06fa3 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -363,11 +363,13 @@ Añadir usuarios Invitar con un enlace Anclar mensajes - Añadido por %1$s + Promovido por %1$s No puedes editar los privilegios de este administrador. + No puedes editar este permiso. + Este permiso no está disponible en grupos públicos. Eliminado por %1$s Permisos de usuario - Esta opción está desactivada para todos los miembros en los permisos de grupo + Esta opción está desactivada para todos los miembros en los Permisos de grupo ¿Qué puede hacer este usuario? Leer mensajes Enviar mensajes @@ -529,7 +531,7 @@ Añadir usuarios Anclar mensajes Todas las acciones - Nueva excepción + Nuevas excepciones Nuevos administradores Nuevos miembros Información del grupo @@ -701,7 +703,7 @@ Has creado un **grupo**. Los grupos pueden tener: - Hasta 100 000 miembros + Hasta 200 000 miembros Historial de chat persistente Enlaces públicos como t.me/title Administradores con diferentes permisos @@ -1020,6 +1022,7 @@ Tema Modo nocturno automático + Desactivado Desactivado Programado Automático @@ -1041,16 +1044,18 @@ CERRAR EDITOR GUARDAR TEMA Nuevo tema + Tema + CREAR TEMA APLICAR Vista previa del tema Elegir color - Crear nuevo tema + Crear nuevo tema Toca sobre el icono de la paleta de colores para ver la lista de elementos en cada ventana y editarlos. - Puedes crear tu propio tema cambiando los colores en la aplicación. Siempre puedes volver al tema por defecto de Telegram aquí. + Puedes crear tu propio tema cambiando los colores dentro de la aplicación.\n\nSiempre puedes volver al tema por defecto de Telegram aquí. Restablecer las notificaciones ¿Quieres restablecer todos los ajustes de notificaciones? - Tamaño del texto + Tamaño del texto Hacer una pregunta Activar animaciones Ajustes de chat @@ -1111,10 +1116,41 @@ Difuminado Movimiento Fondo de chat + Restablecer fondos de chat + Elimina todos los fondos de chat subidos y restaura los preinstalados. + ¿Quieres restablecer todos los fondos de chat? + ¿Quieres eliminar los fondos seleccionados? Vista previa del fondo - Pista: algunas imágenes de fondo se ven mejor con el efecto difuminado. - ¡Gracias! + Pista: algunas imágenes de fondo se ven mejor difuminadas. + ¡Woo-hoo! ¡Gracias! + Desliza a la izquierda o derecha para ver más colores + Es salmón es un pez, no un color. + Reinhardt, necesitamos encontrarte algunas nuevas canciones 🎶. + ¡Ah! Los niños de hoy en día con la música tecno. Disfruten los clásicos, ¡como Hasselhoff! + Con eso ya no puedo tomarte en serio. + Pulsa Establecer para aplicar el fondo. + Disfruta de la vista. ESTABLECER FONDO + Buscar por color + Buscar fondos + Color: + Brillo + Código de color hexadecimal + Color + Patrón + Intensidad + Azul + Rojo + Naranja + Amarillo + Verde + Turquesa + Púrpura + Rosa + Marrón + Negro + Gris + Blanco Elige un color Subir imagen Elegir una imagen @@ -1502,7 +1538,7 @@ Sesiones activas Sesión actual Sin otras sesiones activas - Puedes iniciar sesión en Telegram desde otro móvil, tablet o computador, usando el mismo número de teléfono. Todos tus datos se sincronizarán al instante. + Puedes iniciar sesión en Telegram desde otro móvil, tablet o PC, usando el mismo número de teléfono. Todos tus datos se sincronizarán al instante. Sesiones activas Controla tus sesiones en otros dispositivos. Toca una sesión para cerrarla. @@ -1548,6 +1584,18 @@ Esto ocultará los contenidos de tus chats o tu lista de chats en la multitarea, pero no podrás hacer capturas de pantalla en Telegram.\n\nTendrás que reiniciar la app para que esto surta efecto. Demasiados intentos.\nPor favor, reinténtalo en %1$s. + Enero + Febrero + Marzo + Abril + Mayo + Junio + Julio + Agosto + Septiembre + Octubre + Noviembre + Diciembre ARCHIVOS MEDIA ENLACES @@ -1612,6 +1660,7 @@ Galería Todas las fotos Toda la multimedia + Todos los videos Aún no hay fotos Por favor, primero descarga la multimedia Por favor, espera hasta que se descargue el video completamente. @@ -2099,7 +2148,7 @@ Evaluar llamada ¿Qué salió mal? Incluir información técnica - Esto no revelará los contenidos de tu conversación, pero nos ayudará a resolver el problema más pronto. + Esto no revela los contenidos de tu chat y nos ayuda a resolver el problema antes. Gracias por ayudarnos a mejorar las llamadas de Telegram. Contestando como %s Responder con mensaje @@ -2114,7 +2163,7 @@ No se puede establecer una llamada de Telegram en este momento. Escuché mi propia voz Escuché ruido de fondo - La otra parte siguió desapareciendo + La otra parte desaparecía El habla estaba distorsionada No pude escuchar a la otra parte La otra parte no me pudo escuchar diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 56ecf033b..0fe41f933 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -231,8 +231,8 @@ Nuovo canale Nome del canale Aggiungi contatti al tuo canale - Le persone possono condividere questo link con gli altri e trovare il tuo canale usando la ricerca di Telegram. - Le persone possono condividere questo link con gli altri e trovare il tuo gruppo usando la ricerca di Telegram. + Se imposti un link permanente, le altre persone potranno trovare il tuo canale e unirsi.\n\nPuoi usare a-z, 0-9 e underscore .\nLa lunghezza minima è di 5 caratteri. + Se imposti un link permanente, le altre persone potranno trovare il tuo gruppo e unirsi.\n\nPuoi usare a-z, 0-9 e underscore .\nLa lunghezza minima è di 5 caratteri. link Le persone possono unirsi al tuo canale seguendo questo link. Puoi revocare il link in ogni momento. Le persone possono unirsi al tuo gruppo seguendo questo link. Puoi revocare il link in ogni momento. @@ -364,7 +364,9 @@ Invitare utenti tramite link Fissare messaggi Promosso da %1$s - Non puoi modificare i privilegi di questo amministratore. + Non puoi modificare i permessi di questo amministratore. + Non puoi modificare questo permesso. + Questo permesso non è disponibile nei gruppi pubblici. Rimosso da %1$s Permessi utente Questa opzione è disattivata per tutti i membri nei permessi del gruppo. @@ -375,18 +377,18 @@ Inviare sondaggi Inviare stickers e GIF Inviare link con anteprima - Change Chat Info + Cambiare le info chat Fissare messaggi Aggiungere utenti - can\'t read - can\'t send messages - no media - no polls - no stickers & GIFs - no embed links - can\'t change Info - no pins - can\'t add users + non legge + non invia messaggi + niente media + niente sondaggi + niente sticker e GIF + niente link + non cambia le info + non fissa + non aggiunge utenti Durata Sempre Blocca e rimuovi dal gruppo @@ -518,7 +520,7 @@ Inviare messaggi Inviare link con anteprima Leggere messaggi - ha cambiato i privilegi di %1$s + ha cambiato i permessi di %1$s Modificare le info del canale Modificare le info del gruppo Pubblicare messaggi @@ -588,7 +590,7 @@ %1$s sta inviando una foto... APERTURA RAPIDA APRI GRUPPO - VIEW BACKGROUND + VISUALIZZA SFONDO APRI CANALE APRI MESSAGGIO Il tema scuro si attiverà automaticamente durante la notte @@ -701,10 +703,10 @@ Tu Hai creato un **gruppo**. I gruppi possono avere: - Fino a 100.000 membri + Fino a 200.000 membri Cronologia chat permanente Link pubblici come t.me/title - Amministratori con privilegi diversi + Amministratori con permessi diversi Inoltra i messaggi qui per salvarli Invia media e file per archiviarli Accedi alla chat da ogni dispositivo @@ -1020,6 +1022,7 @@ Tema Modalità notte automatica + No Disattivata Programmata Automatica @@ -1041,16 +1044,18 @@ CHIUDI EDITOR SALVA TEMA Nuovo tema + Tema + CREA TEMA APPLICA Anteprima tema Seleziona colore - Crea nuovo tema + Crea nuovo tema Tocca sull\'icona della tavolozza per vedere la lista degli elementi in ogni schermata - e modificarli. - Puoi creare il tuo tema cambiando i colori all\'interno dell\'app. Puoi sempre tornare al tema predefinito di Telegram qui. + Puoi creare il tuo tema cambiando i colori all\'interno dell\'app.\n\nPuoi sempre tornare al tema Telegram di default qui. Ripristina tutte le impostazioni di notifica predefinite Sei sicuro di voler ripristinare tutte le impostazioni di notifica sui valori predefiniti? - Dimensione testo messaggi + Dimensione testo messaggi Fai una domanda Attiva animazioni Impostazioni chat @@ -1111,10 +1116,41 @@ Sfocato Prospettiva Sfondo chat + Ripristina sfondi chat + Rimuove tutti gli sfondi chat caricati e ripristina quelli predefiniti. + Sei sicuro di voler ripristinare tutti gli sfondi chat? + Sei sicuro di voler eliminare gli sfondi selezionati? Anteprima sfondo - Suggerimento: alcuni sfondi appaiono migliori con l\'effetto sfocato. - Grazie! + Suggerimento: alcuni sfondi appaiono migliori quando sfocati. + Woo-hoo! Grazie! + Scorri a sinistra o destra per vedere altri colori. + Il salmone è un pesce, non un colore. + Reinhart, dobbiamo trovarti qualche nuova canzone 🎶. + Ah, i ragazzi di oggi con la musica techno! Godetevi i classici, come Hasselhoff! + Non posso prenderti sul serio adesso. + Premi \'Imposta\' per applicare lo sfondo. + Goditi la vista. IMPOSTA SFONDO + Cerca per colore + Cerca sfondi + Colore: + Luminosità + Codice colore esadecimale + Colore + Motivo + Intensità + Blu + Rosso + Arancione + Giallo + Verde + Turchese + Viola + Rosa + Marrone + Nero + Grigio + Bianco Seleziona un colore Carica immagine Seleziona immagine @@ -1317,7 +1353,7 @@ Informazioni richieste Informazioni fornite\n Cos\'è Telegram Passport? - With Telegram Passport you can easily sign up for websites and services that require identity verification.\n\nYour information, personal data, and documents are protected by end-to-end encryption. Nobody, including Telegram, can access them without your permission.\n\nYou can visit our *FAQ* to learn more. + Con Telegram Passport puoi facilmente iscriverti a siti web e servizi che richiedono la verifica dell\'identità.\n\nLe tue informazioni, i tuoi dati personali e i tuoi documenti sono protetti dalla crittografia end-to-end. Nessuno, incluso Telegram, può accedervi senza la tua autorizzazione.\n\nPuoi visitare le nostre *FAQ* per saperne di più. https://telegram.org/faq/it/#passport Per favore crea una password per rendere sicuri i tuoi dati personali tramite crittografia end-to-end.\n\nQuesta password sarà inoltre richiesta ogni volta che accedi a Telegram su un nuovo dispositivo. CREA UNA PASSWORD @@ -1543,11 +1579,23 @@ Conferma impronta digitale per continuare Sensore touch Impronta digitale non riconosciuta. Riprova. - Consenti cattura schermo + Mosta contenuto nelle app recenti Se disattivata, non potrai fare screenshot nell\'app, ma il sistema nasconderà il contenuto delle chat nella lista delle app recenti. - This will hide the contents of your chats or chat list from the task switcher, but you will not be able to take screenshots on Telegram.\n\nYou may need to restart the app for this to take effect. + Questo nasconderà il contenuto delle chat o dell\'elenco chat dalla lista della app recenti, ma non sarà possibile effettuare screenshot su Telegram.\n\nPotrebbe essere necessario riavviare l\'applicazione affinché questo abbia effetto. Troppi tentativi.\nPer favore riprova tra %1$s. + Gennaio + Febbraio + Marzo + Aprile + Maggio + Giugno + Luglio + Agosto + Settembre + Ottobre + Novembre + Dicembre FILE MEDIA LINK @@ -1612,6 +1660,7 @@ Galleria Tutte le foto Tutti i media + Tutti i video Ancora nessuna foto Scarica prima il file Per favore attendi che il video sia scaricato completamente. @@ -2084,7 +2133,7 @@ L\'app di **%1$s** non supporta le chiamate. Deve aggiornare la sua app prima che tu possa chiamarlo. Per favore valuta la qualità della tua chiamata Telegram Telegram deve accedere al microfono per poter effettuare chiamate. - Aggiungi un commento opzionale + Aggiungi un commento facoltativo Richiama Richiama Default @@ -2099,7 +2148,7 @@ Valuta la chiamata Cosa è andato storto? Includi informazioni tecniche - Questo non rivelerà i contenuti della tua conversazione, ma ci aiuterà a risolvere il problema più velocemente. + Non rivela i contenuti della chat e ci aiuta a risolvere il problema più velocemente. Grazie per aver contribuito a rendere le chiamate di Telegram migliori. Rispondi come %s Rispondi con messaggio @@ -2114,11 +2163,11 @@ Impossibile effettuare una chiamata Telegram al momento. Sentivo la mia stessa voce Sentivo dei rumori di fondo - Gli altri continuavano a sparire + Sentivo gli altri a tratti La voce era distorta Non riuscivo a sentire gli altri Gli altri non riuscivano a sentirmi - La chiamata è terminata inaspettatamente + Chiamata terminata inaspettatamente %1$d destinatari %1$d destinatario diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 29153562d..1c9acd2d8 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -49,13 +49,13 @@ Your login code is **%1$s**. Enter it in the Telegram app where you are trying to log in.\n\nDo not give this code to anyone. 성명 - Please enter your full name and upload your profile picture. + 회원님의 성함을 입력하고 프로필 사진을 업로드해 주세요. 이름 (필수) 성 (선택) 가입 취소 - %3$s의 %1$s어치 금액을 %2$s에 송금하셨습니다 - %1$s어치 금액을 %2$s에 송금하셨습니다 + %2$s에 %1$s어치 %3$s에 대한 금액을 송금하셨습니다 + " %2$s에 %1$s 금액을 송금하셨습니다" 체크아웃 배송 방법 죄송합니다. 회원님의 주소로는 배송해 드리기가 어렵습니다. @@ -82,7 +82,7 @@ 성명 결제 정보 저장 향후 사용을 위하여 결제 정보를 저장할 수 있습니다. - 이 기능을 사용하려면 *2단계 인증을 켜* 주세요. + 이 기능을 사용하려면 *2단계 인증을 활성화*해 주세요. 거래내역 확인 %3$s에 대한 %1$s 금액을 %2$s 봇에게 전송하시겠습니까? 전체 @@ -110,7 +110,7 @@ 결제 정보를 보호하려면 비밀번호를 만들어 주세요. 로그인 할 때 입력하라는 메시지가 나타날 것입니다. 복구 이메일 이메일 주소 - 정확한 이메일을 입력해 주세요. 분실한 비밀번호를 찾으실 유일한 방법입니다. + 정확한 이메일을 입력해 주세요. 잊어버린 비밀번호를 되찾으실 유일한 수단입니다. 전화번호가 %1$s 님에게 결제 정보로서 전달됩니다. 이메일이 %1$s 님에게 결제 정보로서 전달됩니다. 전화번호와 이메일이 %1$s 님에게 청구서 정보로서 전달됩니다. @@ -143,10 +143,10 @@ %s 님이 비밀 대화에 들어왔습니다. 비밀 대화에 들어오셨습니다. 대화 내용 비우기 - History cleared. - Chat deleted. - 그룹이 삭제되었습니다. - Channel deleted. + 내용을 비웠습니다. + 대화방을 삭제했습니다. + 그룹을 삭제했습니다. + 채널을 삭제했습니다. 되돌리기 캐시에서 삭제 삭제하고 나가기 @@ -172,13 +172,13 @@ 링크 미리보기 임시 저장 대화 내용을 비웠습니다 - %1$s 이내 + %1$s 작성 %1$s, %2$s 작성 미리보기에 대한 의견 남기기 스티커 보내기 - 팩 보기 + 묶음 들여다보기 맨 위에 고정 - Sorry, you can pin no more than %1$s to the top. + 죄송합니다. %1$s까지 위쪽에 고정하실 수 있습니다. 맨 위 고정 해제 읽지 않음으로 표시 읽음으로 표시 @@ -192,18 +192,18 @@ 텔레그램에 있는 회원님의 연락처 관리자로 승격 - Edit admin rights - 차단된 사용자가 없습니다 + 관리자 권한 수정 + 추방된 사용자가 없습니다 그룹 삭제 그룹 나가기 그룹 삭제 그룹에 있는 메시지가 모두 사라집니다. 그룹을 관리하는 데 도움을 줄 관리자를 추가하실 수 있습니다. 관리자를 제명하려면 길게 누르세요. - 잠깐! 그룹을 삭제하면 참가자가 모두 추방되고 메시지는 모두 사라집니다. 그래도 그룹을 삭제할까요? + 잠깐! 그룹을 삭제하시면 참가자와 메시지가 모두 사라집니다. 그래도 그룹을 삭제할까요? 그룹 만들어짐 un1 님이 회원님을 이 그룹에 초대했습니다 정말 그룹에서 나가시겠습니까? - 정말 **%1$s** 그룹을 나가시겠습니까? + 정말 **%1$s** 그룹에서 나가시겠습니까? 죄송합니다. 이 사용자는 그룹에 추가하실 수 없습니다. 죄송합니다, 그룹의 인원이 최대치입니다. 죄송합니다. 이 사용자는 스스로 그룹에서 나갔기에, 다시 초대하실 수 없습니다. @@ -226,30 +226,30 @@ un1 님이 오디오 파일을 고정했습니다 그룹이 슈퍼그룹으로 업그레이드되었습니다 %1$s 그룹이 슈퍼그룹으로 업그레이드됐습니다 - Users removed from the group by the admins can\'t rejoin via invite links. - Users removed from the channel by the admins can\'t rejoin via invite links. + 관리자가 그룹에서 추방시킨 사용자는 초대 링크를 통해 다시 들어올 수 없습니다. + 관리자가 채널에서 추방시킨 사용자는 초대 링크를 통해 다시 들어올 수 없습니다. 채널 만들기 채널명 채널에 연락 상대 추가 - 사람들이 위 링크를 공유하거나 텔레그램 검색을 이용하여 채널을 찾을 수 있습니다. - 사람들이 위 링크를 공유하거나 텔레그램 검색을 이용하여 그룹을 찾을 수 있습니다. + 영구 링크를 설정하시면, 다른 사람들이 회원님의 채널을 찾아 들어올 수 있습니다.\n\na부터 z 사이 글자, 0부터 9 사이 숫자와 밑줄을 사용하실 수 있습니다.\n최소 길이는 다섯 자입니다. + 영구 링크를 설정하시면, 다른 사람들이 회원님의 그룹을 찾아 들어올 수 있습니다.\n\na부터 z 사이 글자, 0부터 9 사이 숫자와 밑줄을 사용하실 수 있습니다.\n최소 길이는 다섯 자입니다. 링크 사람들이 위 링크를 따라 회원님의 채널에 들어올 수 있습니다. 링크는 언제든지 폐기하실 수 있습니다. 사람들이 위 링크를 따라 그룹에 들어올 수 있습니다. 링크는 언제든지 폐기하실 수 있습니다. 설명 (선택) 안내 - 채널에 대해 안내해 주실 수 있습니다. - You have changed some settings in this group. Apply changes? - You have changed some settings in this channel. Apply changes? + 채널에 관해 안내해 주실 수 있습니다. + 몇 가지 그룹 설정을 바꾸셨습니다. 변경 사항을 적용할까요? + 몇 가지 채널 설정을 바꾸셨습니다. 변경 사항을 적용할까요? 공개 채널 공개 그룹 공개 채널은 검색으로 찾을 수 있으며, 누구나 들어올 수 있습니다. - 공개 그룹은 검색으로 찾을 수 있으며 누구나 들어올 수 있습니다. + 공개 그룹은 검색으로 찾을 수 있고, 모두에게 대화 내용이 공개되며, 누구나 들어갈 수 있습니다. 비공개 채널 비공개 그룹 비공개 채널에는 초대 링크로만 들어올 수 있습니다. - 비공개 그룹에는 초대되거나 초대 링크가 있는 경우에만 들어올 수 있습니다. - 링크 + 비공개 그룹은 초대되거나 초대 링크가 있는 경우에만 들어갈 수 있습니다. + 영구 링크 초대 링크 참가자 추가 채널 나가기 @@ -271,23 +271,23 @@ 이름 확인 중.. %1$s을(를) 사용하실 수 있습니다. 참가자 - Add to group - Add to channel - Delete from this list + 그룹에 추가 + 채널에 추가 + 이 목록에서 삭제 구독자 - 블랙리스트 - Permissions - What can members of this group do? - Add Exception - Search Exceptions - 차단된 사용자 + 추방된 사용자 + 권한 + 이 그룹의 참가자가 할 수 있는 일 + 예외 추가 + 예외 검색 + 추방된 사용자 제한된 사용자 관리자 채널 삭제 채널 삭제 잠깐만요! 이 채널을 삭제하시면 안에 있는 모든 참가자와 메시지가 사라집니다. 무시하고 삭제할까요? 채널에서 나가시겠습니까? - Are you sure you want to leave **%1$s**? + 정말 **%1$s** 채널에서 나가시겠습니까? 채널에 있는 메시지가 모두 사라집니다. 수정 사람들이 이 채널을 검색하여 찾고 공유할 수 있도록 링크를 설정해 주세요.\n\n이를 꺼리신다면, 비공개 채널을 추천해 드립니다. @@ -301,12 +301,12 @@ 음소거 음소거 취소 관리자 추가 - 사용자 차단 + 사용자 추방 차단 해제 차단을 해제하려면 사용자를 길게 누르세요. 링크로 초대 관리자 권한 회수 - Edit permissions + 권한 수정 채널 관리자만 이 목록을 볼 수 있습니다. 누구나 텔레그램을 설치했다면 위 링크를 따라 회원님의 채널에 들어올 수 있습니다. 채널을 관리하는 데 도움을 줄 만한 관리자를 추가하실 수 있습니다. 관리자를 제명하려면 길게 누르세요. @@ -342,15 +342,15 @@ %1$s 채널이 오디오 파일을 게시했습니다 %1$s 채널이 스티커를 게시했습니다 %1$s 채널이 %2$s 스티커를 올렸습니다 - 누가 참가자를 추가할 수 있나요? + 참가자를 추가할 수 있는 사람 모든 참가자 관리자만 글을 게시하시면 참가자들이 알림을 받습니다 참가자들이 조용히 알림을 받습니다 메시지 서명 메시지에 게시한 관리자의 이름을 추가합니다. - 관리자 수정 - 이 관리자는 무엇을 할 수 있나요? + 관리자 권한 + 이 관리자가 할 수 있는 일 채널 정보 수정 그룹 정보 수정 메시지 게시 @@ -363,35 +363,37 @@ 사용자 추가 링크로 사용자 초대 메시지 고정 - %1$s 님이 추가함 + %1$s 님이 승격시킴 이 관리자의 권한을 수정하실 수 없습니다. - Removed by %1$s - 사용자 제한 - This option is disabled for all members in Group Permissions - 이 사용자는 무엇을 할 수 있나요? + 이 권한을 수정하실 수 없습니다. + 이 권한은 공개 그룹에서 부여되지 않습니다. + %1$s 님이 추방함 + 사용자 권한 + 이 설정은 그룹 권한을 가진 참가자 모두에게서 꺼져 있습니다 + 이 사용자가 할 수 있는 일 메시지 읽기 메시지 보내기 미디어 보내기 - Send Polls + 설문 보내기 스티커 및 GIF 보내기 링크 저장 - Change Chat Info - Pin Messages - Add Users - can\'t read - can\'t send messages - no media - no polls - no stickers & GIFs - no embed links - can\'t change Info - no pins - can\'t add users - Duration + 대화방 정보 수정 + 메시지 고정 + 사용자 추가 + 읽기 금지 + 메시지 보내기 금지 + 미디어 금지 + 설문 금지 + 스티커 및 GIF 금지 + 링크 추가 금지 + 정보 수정 금지 + 고정 금지 + 사용자 추가 금지 + 기간 영원히 차단하고 그룹에서 추방 - Apply Changes? - You have changed this user\'s rights in **%1$s**. Apply changes? + 변경 사항을 적용할까요? + **%1$s**에서 사용자의 권한을 수정하셨습니다. 변경 사항을 적용할까요? 그룹 관리 채널 관리 그룹 관리 @@ -401,29 +403,29 @@ 새로운 참가자는 들어오기 전부터 있던 메시지를 볼 수 있습니다. 숨김 새로운 참가자는 이전 메시지를 볼 수 없습니다. - New members won\'t see more than 100 earlier messages. + 새로 온 참가자는 100개 이전의 메시지를 볼 수 없습니다. 채널 들어가기 그룹 들어가기 그룹 종류 채널 종류 - Group type - Channel type - Group Settings - Channel Settings + 그룹 종류 + 채널 종류 + 그룹 설정 + 채널 설정 비공개 공개 비공개 공개 사진 선택 - 사진 + 카메라 갤러리 - Select from gallery + 갤러리 웹 검색 통계 - Bots can only be added as administrators. - Sorry, bots can only be added to channels as administrators. - MAKE ADMIN - %1$s will be removed from admins if you restrict them. + 봇에게 관리자 권한을 부여해야만 추가하실 수 있습니다. + 죄송합니다. 봇에게 관리자 권한을 부여해야만 채널에 추가하실 수 있습니다. + 관리자 세우기 + %1$s 님을 제한하시면 이 사용자가 관리자에서 제명됩니다. 새로운 설문 설문 @@ -465,7 +467,7 @@ **검색하신 활동이 없습니다**\n\n검색어에 해당하는 최근 활동을 찾지 못했습니다. \'**%1$s**\'에 관한 최근 활동을 찾지 못했습니다. 최근 활동이 무엇인가요? - 지난 48시간 사이에 그룹 참가자와 관리자가 활동한 기록입니다. + 지난 48시간 사이에 그룹의 참가자와 관리자가 행한 모든 서비스 활동 기록입니다. 지난 48시간 사이에 채널 관리자가 활동한 기록입니다. un1 님이 그룹명을 \"%1$s\"(으)로 바꿨습니다 un1 님이 채널명을 \"%1$s\"(으)로 바꿨습니다 @@ -499,22 +501,22 @@ un1 님이 채널 링크를 제거했습니다 기존 링크 un1 님이 그룹 설명을 바꿨습니다: - un1 님이 채널 설명을 바꿨습니다: - 기존 설명 + un1 님이 채널 안내를 수정했습니다: + 기존 안내 un1 님이 새로운 참가자에게 이전 대화 내용을 보이도록 설정했습니다 un1 님이 새로운 참가자에게 이전 대화 내용이 보이지 않도록 설정했습니다 un1 님이 그룹 초대를 허용함 un1 님이 그룹 초대 기능을 껐습니다 un1 님이 서명 기능을 켰습니다 un1 님이 서명 기능을 껐습니다 - %1$s 님에 대한 제한을 수정했습니다\n\n기한: %2$s - changed default permissions + %1$s 님의 권한을 수정했습니다\n\n기한: %2$s + 기본 권한 수정 스티커 및 GIF 보내기 미디어 보내기 - Change info - Add users - Pin messages - Send polls + 정보 수정 + 사용자 추가 + 메시지 고정 + 설문 보내기 메시지 보내기 링크 넣기 메시지 읽기 @@ -529,7 +531,7 @@ 사용자 추가 메시지 고정 모든 활동 - 새로운 제한 + 새로운 예외 새로운 관리자 새로운 참가자 그룹 정보 @@ -588,7 +590,7 @@ %1$s 님이 사진을 보내는 중... 즉시 보기 그룹 보기 - VIEW BACKGROUND + 배경 보기 채널로 이동 메시지 보기 어두운 테마가 밤 시간에 자동으로 켜집니다 @@ -661,10 +663,10 @@ 죄송합니다. 지금은 서로 연락처를 교환한 경우에만 메시지를 보내실 수 있습니다. 죄송합니다. 서로의 연락처를 공유해야만 그룹에 초대하실 수 있습니다. 죄송합니다. 현재 회원님은 공개 그룹에 게시하실 수 없습니다. - 더 보기 + 더 알아보기 대화방 선택 설명을 적으세요... - 저장된 GIF 파일을 보려면 탭하세요. + 저장한 GIF 파일을 보려면 탭하세요. 고정 모든 참가자에게 알리기 고정 해제 @@ -699,12 +701,12 @@ 저장한 메시지 저장하려면 여기로 전달하세요 - You have created a **group**. - Groups can have: - Up to 100,000 members - Persistent chat history - Public links such as t.me/title - Admins with different rights + **그룹**을 만드셨습니다. + 그룹에는 + 200,000명까지 참가할 수 있습니다 + 대화 내용이 보존됩니다 + 공개 링크를 t.me/제목 따위로 둘 수 있습니다 + 관리자를 세울 수 있습니다 여기로 메시지를 전달해 저장하세요 미디어와 파일을 보내어 저장하세요 어느 기기에서나 이 대화방에 드나드세요. @@ -730,8 +732,8 @@ 그룹의 관리자가 회원님이 스티커를 보내시지 못하도록 제한했습니다. 그룹의 관리자가 회원님이 메시지를 적으실 수 없도록 제한했습니다. 이 그룹에서는 미디어를 보내실 수 없습니다. - 이 그룹에서는 인라인 봇이 금지됩니다. - 이 그룹에서는 스티커가 금지됩니다. + 그룹에서 인라인 봇을 금지합니다. + 그룹에서 스티커를 금지합니다. 이 그룹에서는 메시지를 작성하실 수 없습니다. 관리자 이 앱에서는 APK 설치가 제한됩니다. 시스템 설정에서 이를 허용하실 수 있습니다. @@ -750,7 +752,7 @@ 자동 삭제 타이머를 %1$s(으)로 맞추셨습니다 %1$s 님이 자동 삭제 타이머를 껐습니다 자동 삭제 타이머를 끄셨습니다 - 새로운 메시지 + 새로운 메시지가 왔습니다 %1$s: %2$s %1$s 님이 회원님에게 %2$s을(를) 보냈습니다 %1$s 님이 회원님에게 %2$s을(를) 전달했습니다 @@ -799,7 +801,7 @@ %1$s 님이 회원님을 %2$s 그룹에서 추방했습니다 %1$s 님이 %2$s 그룹에서 나갔습니다 %1$s 님이 텔레그램에 가입했습니다! - %1$s 님,\n%2$s에 새로운 기기에서 회원님 계정으로 로그인한 것이 감지됐습니다.\n\n기기: %3$s\n위치: %4$s\n\n본인이 접속하지 않았다면, \'개인 정보 및 보안\' 설정에서 해당 세션을 종료하세요.\n\n만약 누군가 강제로 접속했다는 의심이 가신다면, \'개인 정보 및 보안\' 설정에서 2단계 인증을 활성화하실 수 있습니다.\n\n텔레그램 팀 드림 + %1$s 님,\n%2$s에 새로운 기기가 회원님의 계정에 로그인한 것을 감지했습니다.\n\n기기: %3$s\n위치: %4$s\n\n본인이 아니라면 설정 — 모든 세션 보기에서 그 세션을 종료하실 수 있습니다.\n\n누군가가 회원님의 뜻과 달리 계정에 접속했다고 생각하시면, 설정에서 2단계 인증을 활성화하실 수 있습니다.\n\n감사합니다.\n\n텔레그램 팀 %1$s 님이 프로필 사진을 업데이트했습니다 초대 링크를 통해 %1$s 님이 %2$s 그룹에 들어왔습니다. %1$s 님이 %2$s 그룹에 %3$s을(를) 보냈습니다 @@ -872,7 +874,7 @@ 연락처를 업데이트할까요? 텔레그램이 아직 동기화되지 않은 여러 연락처를 찾아냈습니다. 연락처를 동기화하시겠습니까? 본인의 기기, SIM 카드와 Google 계정을 사용하는 중이라면 \'확인\'을 누르십시오. 이름순으로 정렬 - 마지막 접속 시간순으로 정렬 + 마지막 접속순으로 정렬 사람들을 추가하세요... 이 그룹을 마저 만들고 슈퍼그룹으로 변환한 뒤에 사용자를 더 추가하실 수 있습니다. @@ -887,7 +889,7 @@ 이메일을 클립보드에 복사했습니다 링크로 그룹에 초대하기 초대 링크 - 정말 이 초대 링크를 폐기할까요? 앞으로는 아무도 이 링크를 통해서 들어올 수 없습니다. + 정말 이 초대 링크를 폐기할까요? 앞으로 이 링크를 통하여 아무도 들어올 수 없습니다. 이전 초대 링크는 현재 비활성화됐습니다. 새 초대 링크가 만들어졌습니다. 폐기 링크 폐기 @@ -906,7 +908,7 @@ 그룹에서 차단 그룹 삭제하고 나가기 알림 - 권한 바꾸기 + 권한 수정 그룹에서 추방 슈퍼그룹으로 업그레이드 슈퍼그룹으로 변환 @@ -1020,10 +1022,11 @@ 테마 자동 야간 모드 + 끄기 끄기 예약 자동 - 스케쥴 + 예약 지역 일몰 및 일출 시간 사용 위치 갱신 일몰 및 일출 시간을 계산하려면 회원님의 대략적인 위치를 한 번 확인해야 합니다. 이 위치는 회원님의 기기에만 로컬로 보관됩니다.\n\n일몰: %1$s\n일출: %2$s @@ -1036,21 +1039,23 @@ 검푸른색 파랑 이 테마를 삭제하시겠습니까? - 올바르지 않은 테마 파일 + 올바르지 않은 테마 파일입니다 테마명을 입력하세요 편집기 닫기 테마 저장 - 새로운 테마 + 새로운 색 테마 + 색 테마 + 새로운 테마 적용 테마 미리보기 색깔 선택 - 새로운 테마 만들기 + 새로운 테마 만들기 각 화면의 구성 요소 목록을 보려면 팔레트 아이콘을 누르세요. 이들을 수정하실 수 있습니다. - 앱 안 구석구석 색깔을 바꿔 회원님만의 테마를 만드실 수 있습니다. 언제든지 여기서 텔레그램 테마를 기본으로 돌리실 수 있습니다. + 앱 안에서 색들을 바꾸어 회원님만의 테마를 만드실 수 있습니다.\n\n여기서 언제든지 기본 텔레그램 테마로 돌리실 수 있습니다. 모든 알림 설정이 초기화됐습니다 정말 모든 알림 설정을 기본으로 초기화하시겠습니까? - 메시지 글자 크기 + 메시지 글자 크기 질문하기 화면 전환 효과 사용 대화방 설정 @@ -1071,7 +1076,7 @@ 앱 사용 중 미리보기 초기화 모든 알림 설정 초기화 - 연락처와 그룹, 채널에 대한 모든 맞춤 알림 설정을 처음 상태로 돌립니다. + 연락처와 그룹에 대한 모든 맞춤 알림 설정을 처음 상태로 되돌립니다. 알림 및 소리 맞춤 알림 팝업 알림 @@ -1090,12 +1095,12 @@ 폰트 크기 보라색 주황색 - LED는 일부 기기에서 새로운 메시지를 받았음을 나타내는 반짝이는 작은 빛입니다. + LED는 몇몇 기기에 있는 반짝이는 작은 빛으로 새로운 메시지가 왔음을 나타냅니다. 우선순위가 높은 알림은 휴대폰이 방해 금지 상태이더라도 작동합니다. 일반 음소거됨 음소거 해제 - 켜짐 + %1$s까지 끔 기본 (켬) @@ -1111,20 +1116,51 @@ 흐림 효과가 적용됨 모션 효과 대화방 배경 + 대화방 배경 초기화 + 업로드된 대화방 배경을 모두 제거하고 기본으로 설치된 배경을 복구합니다. + 정말 모든 대화방 배경을 초기화하시겠습니까? + 정말 선택한 배경을 삭제하시겠습니까? 배경 미리보기 팁: 몇몇 배경에는 흐림 효과가 잘 어울립니다. - 감사합니다! - 배경 설정 + 야호! 감사합니다 + 좌우로 넘겨 다양한 색을 입혀 보세요 + Salmon is a fish, not a color. + 라인하르트, 새 음악도 좀 들어보시지 그래요🎶? + 요즘 젊은이들은 테크노인지 뭔지 하는 것만 좋아한다니까! 핫셀호프 같은 고전 음악을 들어 보라고! + 이게 진심으로 하는 말이라니. 아으! + \'설정\'을 눌러 배경을 적용하세요. + 경치가 장관이로구나! + 배경으로 설정 + 색으로 검색 + 배경 검색 + 색: + 밝기 + Hex 색깔 코드 + + 무늬 + 세기 + 파란색 + 빨간색 + 주황색 + 노란색 + 초록색 + 청록색 + 보라색 + 분홍색 + 갈색 + 검은색 + 회색 + 하얀색 색 선택 이미지 업로드 이미지 선택 - 전체 이미지 로딩 중... + 이미지 전체 불러오는 중... 색 설정 메시지 엔터 키로 보내기 이벤트 친구의 텔레그램 가입 - 고정된 메시지 + 메시지 고정 언어 맞춤 언어를 바꿀까요? @@ -1134,8 +1170,8 @@ 비공식 언어 해당 언어가 없습니다. 이미 이 언어 묶음(**%1$s**)을 사용하고 계십니다. 설정에서 언제든 언어를 바꾸실 수 있습니다. - 안타깝게도 이 맞춤 언어 묶음(**%1$s**)에는 안드로이드 텔레그램용 데이터가 들어 있지 않습니다. - 텔레그램에 관한 질문은 자원봉사자들이 답변해 드립니다. 신속하게 응답하기 위해 노력하지만, 다소 시간이 걸릴 수 있습니다.\n\n 자주 묻는 질문]]>을 확인해 보세요. 잦은 질문에 대한 답과 문제 해결]]>을 위한 중요한 조언이 있습니다. + 안타깝게도 이 맞춤 언어 묶음(**%1$s**)에는 Android 텔레그램용 데이터가 들어 있지 않습니다. + 텔레그램 지원 사항은 자원봉사자들이 처리합니다. 신속하게 응답해 드리고자 노력하지만, 다소 시간이 걸릴 수 있습니다.\n\n 자주 묻는 질문]]>을 확인해 보세요. 잦은 질문에 대한 답과 문제 해결]]>을 위한 중요한 조언이 있습니다. 봉사자에게 질문하기 자주 묻는 질문 자주 묻는 질문 @@ -1148,8 +1184,8 @@ https://telegram.org/privacy 언어를 삭제할까요? 언어 파일이 올바르지 않습니다 - 항상 활성화 서비스 - 앱이 닫히면 재시작합니다. 신뢰할 수 있는 알림을 사용하도록 설정합니다. + 항상 실행 서비스 + 앱이 닫히면 다시 실행합니다. 신뢰할 수 있는 알림을 활성화합니다. 백그라운드 연결 안정적인 알림을 위해 텔레그램의 백그라운드 연결을 최소로 유지합니다. 정렬 @@ -1171,7 +1207,7 @@ 미디어 자동 다운로드 미디어 자동 다운로드 자동 다운로드 설정 초기화 - 자동 다운로드 설정을 정말 초기화하시겠습니까? + 정말 자동 다운로드 설정을 초기화하시겠습니까? 모바일 데이터를 사용할 때 Wi-Fi에 연결할 때 로밍할 때 @@ -1191,8 +1227,8 @@ 긴급 사용 안 함 알림 반복 - 텔레그램 번호를 여기서 바꾸실 수 있습니다. 계정과 클라우드에 저장된 메시지나 미디어, 연락처 등이 새 번호로 옮겨집니다.\n\n**중요:** 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있으며 차단되지 않은 모두에게 회원님의 **새 전화번호**가 추가됩니다. - 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있고 차단되지 않은 모두에게 회원님의 새 전화번호가 추가됩니다. + 텔레그램 번호를 여기서 바꾸실 수 있습니다. 회원님의 계정과 메시지와 미디어, 연락처 따위의 모든 클라우드 데이터가 새 번호로 옮겨집니다.\n\n**중요:** 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있으며 차단되지 않은 모두에게 회원님의 **새 전화번호**가 추가됩니다. + 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있고 차단되지 않은 모두에게 회원님의 새 전화번호가 저장됩니다. 번호 바꾸기 새 번호 회원님의 새 번호로 인증 코드가 담긴 SMS를 보내겠습니다. @@ -1282,14 +1318,14 @@ 스티커 및 마스크 맞춤 색 배합 선택 대화방 알림 - 비공개 대화방 + 개인 대화방 그룹 채널 - **%1$s**은(는) 예외로 분류되며 이번 변경 사항에 영향을 받지 않는다는 점을 유의해 주세요. - **%1$s** 님은 예외로 분류되어 이번 변경에 영향을 받지 않는다는 점을 유의하시기 바랍니다. + **%1$s**는 예외로 분류되어 이번 변경에 영향을 받지 않는다는 점을 알아 두세요. + **%1$s**는 예외로 분류되어 이번 변경에 영향을 받지 않는다는 점을 알아 두세요. 예외 보기 그룹 알림 - 비공개 대화방 알림 + 개인 대화방 알림 채널 알림 바꾸려면 누르세요 @@ -1317,10 +1353,10 @@ "요청 받은 정보 " 제공한 정보 텔레그램 패스포트가 무엇인가요? - With Telegram Passport you can easily sign up for websites and services that require identity verification.\n\nYour information, personal data, and documents are protected by end-to-end encryption. Nobody, including Telegram, can access them without your permission.\n\nYou can visit our *FAQ* to learn more. + 텔레그램 패스포트와 함께라면, 신분 인증이 필요한 여러 웹 사이트와 서비스에 손쉽게 로그인하실 수 있습니다.\n\n회원님의 정보와 개인 데이터, 서류들은 단대단 암호화로 보호됩니다. 텔레그램을 포함하여, 그 누구도 회원님의 허가 없이 이들에 접근할 수 없습니다. https://telegram.org/faq#passport 단대단 암호화로 개인 데이터를 보호하려면 비밀번호를 만드셔야 합니다.\n\n새로운 기기로 텔레그램에 로그인할 때 이 비밀번호가 필요할 것입니다. - 비밀번호를 만드세요 + 비밀번호 만들기 텔레그램 패스포트 삭제 정말 텔레그램 패스포트를 삭제하시겠습니까? 로마자만 사용해 주세요. @@ -1450,7 +1486,7 @@ %1$s 또는 %2$s 성명 %1$s 성명 - 거주하시는 국가의 언어(%1$s)로 쓰인 성명입니다. + 거주하시는 국가의 언어(%1$s)로 성명을 작성하세요. 성명이 올바른지 확인해 주세요.\n\n%1$s %2$s %3$s 아랍어 아제르바이잔어 @@ -1499,13 +1535,13 @@ 우즈베크어 베트남어 - 활성화된 세션 + 활성 세션 현재 세션 활성화된 다른 세션이 없습니다 동일한 전화번호를 사용하여 다른 모바일, 태블릿, 데스크탑 장치에서 텔레그램에 로그인하실 수 있습니다. 모든 데이터가 즉시 동기화됩니다. - 활성화된 세션 - 다른 기기 세션 관리 - 세션을 종료하려면 짧게 누르세요 + 활성 세션 + 다른 기기의 세션을 관리하세요. + 세션을 종료하려면 짧게 누르세요. 이 세션을 종료할까요? 이곳 밖의 모든 기기에서 로그아웃합니다. 정말 다른 기기에 로그인된 세션을 모두 종료하시겠습니까? @@ -1521,19 +1557,19 @@ 모든 웹 사이트와 연결 끊기 정말로 텔레그램을 사용하여 로그인한 모든 웹사이트의 연결을 해제하시겠습니까? 텔레그램으로 로그인하기를 지원하는 웹 사이트에 로그인하실 수 있습니다. - 로그인 시도가 완료되지 않았습니다 + 완료되지 않은 로그인 시도 위 기기가 메시지에 접근할 수 없습니다. 코드는 알맞게 입력하셨으나, 비밀번호가 잘못되었습니다. 암호 잠금 암호 바꾸기 - 암호를 설정하시면 대화창에 잠금 아이콘이 표시됩니다. 텔레그램을 잠그거나 잠금 해제하려면 이 아이콘을 누르세요.\n\n주의: 암호를 잊어버리면 앱을 지우고 재설치하셔야 합니다. 이 경우 모든 비밀 대화가 사라집니다. + 암호를 설정하시면, 대화방 화면에 잠금 아이콘이 나타납니다. 이 아이콘을 눌러 텔레그램을 잠그거나 잠금 해제하실 수 있습니다.\n\n주의: 암호를 잊어버리면 앱을 삭제하고 다시 설치하셔야 합니다. 이 경우 모든 비밀 대화가 사라집니다. PIN 암호 현재 암호를 임력하세요 - 암호를 입력하세요. + 암호를 입력하세요 새 암호를 입력하세요 암호를 입력하세요 - 새 암호를 입력하세요 + 암호를 다시 입력하세요 암호가 일치하지 않습니다. 자동 잠금 일정 시간이 지나면 텔레그램을 잠급니다. @@ -1543,11 +1579,23 @@ 계속하려면 지문인식 절차를 거치세요 터치 센서 지문이 인식되지 않았습니다. 다시 시도해 주세요. - 화면 캡처 허용 - 위 기능을 켜면, 앱 안에서 스크린샷을 찍으실 수 있으나, 암호가 설정된 경우에도 주고받은 대화가 최근 실행한 앱 목록에서 보입니다.\n적용이 안 된다면 앱을 재시작하세요. - This will hide the contents of your chats or chat list from the task switcher, but you will not be able to take screenshots on Telegram.\n\nYou may need to restart the app for this to take effect. + 앱 전환 화면에서 대화 내용 드러내기 + 위 기능을 끄면, 앱 안에서 화면을 캡처하실 수 없지만 앱 전환 화면에서 대화 내용이 숨겨집니다. + 앱 전환 화면에서 대화 내용이나 목록이 숨겨지지만, 텔레그램에서 스크린샷을 찍으실 수 없습니다.\n\n이 기능을 사용하려면 앱을 다시 시작하셔야 할 수도 있습니다. 너무 많이 시도하셨습니다.\n%1$s초 뒤에 다시 시도해 주세요. + 1월 + 2월 + 3월 + 4월 + 5월 + 6월 + 7월 + 8월 + 9월 + 10월 + 11월 + 12월 파일 미디어 링크 @@ -1579,13 +1627,13 @@ 정말로 %1$s 님과 실시간 위치 공유를 중단하시겠습니까? 정말로 %1$s 님과 실시간 위치 공유를 중단하시겠습니까? 정말로 실시간 위치 공유를 중단하시겠습니까? - 움직임을 따라 실시간으로 갱신됩니다 + 움직임을 따라 실시간으로 갱신합니다 선택한 위치 보내기 위치 장소 %1$s 반경 내 정확함 아니면 장소 선택 - 근처 장소를 확인하려면 위로 당기세요 + 근처 장소를 보려면 쓸어 올리세요 실시간 위치 15분 동안 1시간 동안 @@ -1612,6 +1660,7 @@ 갤러리 모든 사진 모든 미디어 + 모든 동영상 사진이 없습니다 먼저 미디어를 다운로드해 주세요 동영상을 완전히 다운로드할 때까지 기다려 주세요. @@ -1663,14 +1712,14 @@ 일반 초기화 원본 - 정사각형 + 정방형 미디어를 개별 메시지로 보내기 미디어를 하나의 메시지로 묶기 2단계 인증 2단계 인증 개별 비밀번호 설정 - 새로운 기기에 로그인할 때 SMS로 받는 코드와는 별개로 입력해야 하는 비밀번호를 설정하실 수 있습니다. + 새로운 기기에 로그인할 때 SMS로 받는 코드와 별개로 입력해야 하는 비밀번호를 설정하실 수 있습니다. 비밀번호 비밀번호를 입력하세요 비밀번호 입력 @@ -1680,14 +1729,14 @@ 이메일 이메일 코드 %1$s 편으로 받은 코드를 입력하여 이메일 주소를 인증해 주세요. - 올바른 이메일을 입력해 주세요. 잊어버린 비밀번호를 복구하실 수 있는 유일한 수단입니다. + 정확한 이메일을 추가해 주세요. 잊어버린 비밀번호를 되찾으실 유일한 수단입니다. 건너뛰기 경고 비밀번호 분실시\n\n텔레그램에 대한 모든 접속 권한을 상실하시게 됩니다.\n비밀번호 분실시 복구는 불가능 합니다. 거의 다 됐어요! 2단계 인증 설정을 완료하시려면 이메일을 (스팸 폴더도 잊지 않고) 확인해 주세요. 성공! - 2단계 인증 비밀번호가 활성화됐습니다. + 2단계 인증 비밀번호가 활성화되었습니다. 2단계 인증용 복구 이메일이 이제 작동합니다. 비밀번호 바꾸기 비밀번호 끄기 @@ -1719,14 +1768,14 @@ 이 작업은 되돌릴 수 없습니다.\n\n계정을 초기화하시면, 메시지와 대화방이 모두 삭제됩니다. 계정 초기화 비밀번호 - 2단계 인증을 켜셨기에, 계정이 추가 비밀번호로 보호됩니다. + 2단계 인증이 활성화되어, 계정이 추가 비밀번호로 보호됩니다. 비밀번호를 잊어버리셨나요? 비밀번호 복구 코드 비밀번호 비활성화 코드 다시 보내기 인증 코드를 이메일로 보냈습니다. - 2단계 인증을 켜셨습니다.\n회원님의 텔레그램 계정에 로그인하려면 여기서 설정한 비밀번호가 필요합니다. + 2단계 인증이 활성화되었습니다.\n회원님의 텔레그램 계정에 로그인하려면 여기서 설정하신 비밀번호가 필요합니다. 데이터 및 저장소 디스크 및 네트워크 사용량 @@ -1762,7 +1811,7 @@ 클라우드 임시 저장 모두 삭제 모두 내 연락 상대 - 아무도 없음 + 없음 전체 공개 (-%1$d) 내 연락 상대만 (+%1$d) 내 연락 상대만 (-%1$d) @@ -1780,8 +1829,8 @@ 계정 자동 탈퇴 고급 다음 기간 내 미접속 시 계정 탈퇴 - 이 기간 안에 최소 한 번 온라인으로 들어오시지 않으면, 모든 그룹, 메시지, 연락처와 더불어 회원님의 계정이 사라집니다. - 누가 내 마지막 접속 시간을 볼 수 있나요? + 이 기간 안에 한 번이라도 접속하시지 않으면, 모든 그룹, 메시지, 연락처와 더불어 회원님의 계정이 사라집니다. + 내 마지막 접속 시간을 볼 수 있는 사람 예외 추가 중요: 회원님의 마지막 접속 시간을 공유받지 않는 사람의 마지막 접속 시간은 보실 수 없습니다. 대신 최근, 일주일 이내, 한달 이내와 같이 간략하게 보일 것입니다. 항상 공유 @@ -1795,18 +1844,18 @@ 죄송합니다. 개인 정보 설정을 너무 많이 바꾸셨습니다. 잠시 기다리세요. 사용자를 삭제하려면 길게 누르세요. 그룹 - 누가 나를 그룹 대화방에 초대할 수 있나요? + 나를 그룹 대화방에 추가할 수 있는 사람 회원님을 그룹과 채널에 추가할 수 있는 사람을 세세하게 정하실 수 있습니다. 항상 허용 항상 거부 항상 허용... 항상 거부... 위 사용자는 앞선 설정과 무관하게 회원님을 그룹과 채널에 추가하지 못합니다. - 그룹이나 채널에 회원님을 추가할 수 있는 사람을 정하세요. + 회원님을 그룹과 채널에 추가할 수 있는 사람을 정하세요. 죄송합니다, 이 이용자는 개인 설정으로 인하여 그룹에 초대 할 수 없습니다. 죄송합니다, 이 이용자는 개인 설정으로 인하여 채널에 초대 할 수 없습니다. 죄송합니다. 이 사용자들의 개인 설정으로 인해 함께 그룹을 만드실 수 없습니다. - 피어투피어를 끄시면, 회원님의 IP 주소를 노출시키지 않도록 모든 전화가 텔레그램 서버를 통해 전달됩니다. 다만 음성 품질이 약간 저하될 수 있습니다. + 단대단을 끄시면, 회원님의 IP 주소를 노출시키지 않도록 모든 전화가 텔레그램 서버를 통해 전달됩니다. 다만 음성 품질이 약간 저하될 수 있습니다. 동기화된 연락처 삭제 자주 이용하는 연락처 추천 "신속한 연락을 위해 검색 구역 위쪽에 자주 대화하는 사람을 내보이세요. " @@ -1824,9 +1873,9 @@ 메시지 접근 권한 없음 이 봇은 무엇을 할 수 있나요? 시작 - 재시작 + 다시 시작 봇 정지 - 봇 재시작 + 봇 다시 시작 완료 열기 @@ -1842,7 +1891,7 @@ 삭제 삭제하고 정지 전달 - 재전송 + 다시 보내기 카메라 갤러리 사진 제거 @@ -1906,7 +1955,7 @@ 임차 계약서 전화번호 이메일 주소 - 이 메시지는 현재 텔레그램 버전에서 지원되지 않습니다. 메시지를 보시려면 http://telegram.org/update에서 앱을 업데이트하세요. + 이 메시지는 현재 텔레그램 버전에서 지원되지 않습니다. 메시지를 보시려면 http://telegram.org/update 에서 앱을 업데이트하세요. 사진 동영상 자동 삭제되는 사진 @@ -1951,7 +2000,7 @@ %1$s 님에게 메시지를 보낼까요? %1$s 님에게 게임을 공유할까요? %1$s 님에게 연락처를 보낼까요? - 정말 로그아웃하시겠습니까?\n\n텔레그램은 여러 기기에서 동시에 사용이 가능합니다.\n\n로그아웃 시 모든 비밀 대화가 사라지는 점을 유의하시기 바랍니다. + 정말 로그아웃하시겠습니까?\n\n텔레그램은 여러 기기에서 동시에 이용하실 수 있습니다.\n\n로그아웃 시 모든 비밀 대화가 사라지는 점을 유의하시기 바랍니다. 이 그룹에서 정말 나가시겠습니까? 정말 **%1$s** 그룹을 삭제하고 나가시겠습니까? 정말 이 대화방을 삭제하시겠습니까? @@ -1991,7 +2040,7 @@ 죄송합니다. 메시지를 수정할 수 없습니다. 텔레그램이 SMS를 받을 수 있도록 허락해 주셔야 자동으로 코드를 입력해 드릴 수 있습니다. 텔레그램이 전화를 수신 할 수 있도록 설정해주셔야 자동으로 코드 입력이 가능합니다. - 텔레그램이 전화와 SMS를 받을 수 있도록 허락해 주셔야 자동으로 전화번호를 채워 넣고, 코드를 보내고, 입력해 드릴 수 있습니다. + 텔레그램이 전화를 받을 수 있도록 허용해 주셔야 회원님의 전화번호를 자동으로 확인할 수 있습니다. 텔레그램이 전화를 받을 수 있도록 허용해 주시면 전화번호가 자동으로 확인됩니다. 죄송합니다. 이 작업은 진행하실 수 없습니다. 죄송합니다. 차단된 사용자나 봇은 그룹에 추가하실 수 없습니다. 먼저 차단을 해제하세요. @@ -2058,9 +2107,9 @@ 벨소리 이 연락처에서 전화가 걸려올 때 울리는 벨소리를 맞춤하실 수 있습니다. 전화 - 위 사용자와 통화할 때는 앞선 설정과 무관하게 단대단이 사용되거나 사용되지 않습니다. + 위 사용자와 통화할 때에는 앞선 설정과 무관하게 단대단이 사용되거나 사용되지 않습니다. 단대단을 사용하여 통화할 사람 - 누가 나에게 전화할 수 있나요? + 나에게 전화할 수 있는 사람 회원님에게 전화할 수 있는 사람을 제한하실 수 있습니다. 위 사용자는 앞선 설정과 무관하게 회원님에게 전화를 걸지 못합니다. 안 함 @@ -2084,7 +2133,7 @@ **%1$s** 님의 텔레그램은 전화를 지원하지 않습니다. 앱을 업데이트한 뒤 전화할 수 있습니다. 텔레그램 전화의 품질을 평가해주세요. 전화를 걸려면 텔레그램에게 마이크 접근 권한을 부여하셔야 합니다. - 코멘트 추가 + 코멘트를 입력하실 수 있습니다 답신 전화 다시 전화 걸기 기본 @@ -2099,12 +2148,12 @@ 전화 평가 무엇이 잘못됬나요? 기술적 정보 포함 - 이 작업은 대화의 내용이 노출되지 않지만, 향 후 문제해결에 도움이 됩니다. + 대화 내용이 공개되지 않으며 빠른 시일 내로 문제를 해결해 드리는 데 도움이 됩니다. 텔레그램 전화를 개선할 수 있도록 도와주셔서 감사합니다. %s(으)로서 수신 중 문자로 응답 - 이러한 빠른 응답 문자들로 전화가 걸려올 때 텔레그램 메시지를 보내어 응답하실 수 있습니다. 무엇이든지 원하는 말로 바꾸세요. - 지금 대화할 수 없어요. 무슨 일이죠? + 이 빠른 응답 문구들을 전화가 걸려올 때 텔레그램 메시지로 보내실 수 있습니다. 무엇이든지 원하는 말로 바꾸세요. + 지금 대화할 수 없어요. 무슨 일인가요? 곧바로 전화할게요. 나중에 전화할게요. 지금 대화할 수 없어요. 나중에 전화 주시겠어요? @@ -2112,20 +2161,20 @@ 맞춤 허용 %s님에게 텔레그램으로 전화 지금은 텔레그램으로 전화하실 수 없습니다. - 제 목소리가 울립니다 + 제 목소리가 울렸습니다 잡음이 들렸습니다 상대가 번번이 사라졌습니다 소리가 왜곡되었습니다 - 상대의 목소리가 들리지 않습니다 - 제 목소리가 상대에게 들리지 않습니다 + 상대의 목소리가 들리지 않았습니다 + 제 목소리가 상대에게 들리지 않았습니다 통화가 예기치 않게 종료되었습니다 - %1$d명의 수신자 - %1$d명의 수신자 - %1$d명의 수신자 - %1$d명의 수신자 - %1$d명의 수신자 - %1$d명의 수신자 + 받는 사람 %1$d명 + 받는 사람 %1$d명 + 받는 사람 %1$d명 + 받는 사람 %1$d명 + 받는 사람 %1$d명 + 받는 사람 %1$d명 온라인 %1$d명 온라인 %1$d명 온라인 %1$d명 @@ -2144,18 +2193,18 @@ 안녕하세요, %1$d명의 친구와 텔레그램이라는 메신저를 사용하고 있어요. 함께 사용해요! 여기서 다운로드하세요: %2$s 안녕하세요, %1$d명의 친구와 텔레그램이라는 메신저를 사용하고 있어요. 함께 사용해요! 여기서 다운로드하세요: %2$s 안녕하세요, %1$d명의 친구와 텔레그램이라는 메신저를 사용하고 있어요. 함께 사용해요! 여기서 다운로드하세요: %2$s - 대화 %1$d개 - 대화 %1$d개 - 대화 %1$d개 - 대화 %1$d개 - 대화 %1$d개 - 대화 %1$d개 - 대화방 %1$d곳 - 대화방 %1$d곳 - 대화방 %1$d곳 - 대화방 %1$d곳 - 대화방 %1$d곳 - 대화방 %1$d곳 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 + 대화방 %1$d개 채널 %1$d개 채널 %1$d개 채널 %1$d개 @@ -2428,7 +2477,7 @@ yyyy.MMM.dd, HH:mm MMM dd, a h:mm MMM dd, HH:mm - yyyy LLLL + yyyy년 LLLL LLLL M\'월\' d\'일\' yy.MM.dd. diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index f444f120a..2b1176e06 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -363,8 +363,10 @@ Leden toevoegen Uitnodigen via link Berichten vastzetten - Toegevoegd door %1$s + Gepromoveerd door %1$s Je kunt de machtigingen van deze beheerder niet aanpassen. + Je kunt deze rechten niet aanpassen. + Dit recht is niet beschikbaar in publieke groepen. Verwijderd door %1$s Gebruikersrechten Deze optie is voor alle leden uitgeschakeld via de groepsrechten @@ -529,7 +531,7 @@ Leden toevoegen Berichten vastzetten Alle gebeurtenissen - Nieuwe beperking + Nieuwe uitzonderingen Nieuwe beheerders Nieuwe leden Groepsinformatie @@ -701,7 +703,7 @@ Jij Je hebt een **groep** gemaakt Groepskenmerken: - Tot 100000 leden + Tot 200000 leden Blijvende chatgeschiedenis Publieke links zoals t.me/titel Beheerders met aangepaste rechten @@ -729,9 +731,9 @@ Je bent beperkt in het sturen van inline-content door de groepsbeheerders. Je bent beperkt in het sturen van stickers door de groepsbeheerders. Je bent beperkt in het plaatsen van berichten door de groepsbeheerders. - Media plaatsen is niet toegestaan in deze groep. - Inline-content plaatsen is niet toegestaan in deze groep. - Stickers plaatsen is niet toegestaan in deze groep. + Media sturen is niet toegestaan in deze groep. + Inline-bots zijn niet toegestaan in deze groep. + Stickers zijn niet toegestaan in deze groep. Berichten schrijven is niet toegestaan in deze groep. beheerder APK-installatie is beperkt voor deze app. Je kunt dit inschakelen via de systeeminstellingen. @@ -1020,6 +1022,7 @@ Thema Automatisch nachtthema + Off Uitgeschakeld Geplande tijd Automatisch @@ -1041,16 +1044,18 @@ BEWERKER SLUITEN THEME OPSLAAN Nieuw Thema + Kleurenthema + THEMA MAKEN TOEPASSEN Thema-voorbeeld Selecteer kleur - Nieuw thema maken + Nieuw thema maken Tik op het palet-icoon om een lijst met elementen voor elk scherm te zien en deze te bewerken. - Door het veranderen van de kleuren in de app kun je je eigen thema maken. Je kunt hier altijd terugschakelen naar het standaardthema. + Je kunt je eigen thema maken door kleuren in de app aan te passen.\n\nJe kunt hier altijd het standaardthema weer instellen. Meldingen gereset Alle meldingsinstellingen herstellen naar de standaardwaarden? - Tekstgrootte berichten + Berichttekstgrootte Een vraag stellen Animaties Chatinstellingen @@ -1111,10 +1116,41 @@ Vervaagd Beweging Achtergrond kiezen + Chatachtergronden resetten + Verwijder alle geüploade chatachtergronden en herstel de voorgeïnstalleerde achtergronden. + Echt alle chatachtergronden resetten? + Achtergrond echt verwijderen? Achtergrondvoorvertoning Sommige achtergrondafbeeldingen zien er vervaagd beter uit. Bedankt! + Veeg naar links of rechts om meer kleuren te zien + Zalm is een vis, geen kleur. + Godfried, ben jij het echt? + Ik zit mij voor het vensterglas onnoemlijk te vervelen. + Ik wou dat ik twee hondjes was, dan kon ik samen spelen + Press \'Set\' to apply the background. + Enjoy the view. ACHTERGROND INSTELLEN + Zoek op kleur + Zoek Achtergronden + Kleur: + Helderheid + Kleur in hexidecimaal + Kleur + Patroon + Intensiteit + Blauw + Rood + Oranje + Geel + Groen + Groenblauw + Paars + Roze + Bruin + Zwart + Grijs + Wit Kies een kleur Afbeelding uploaden Kies afbeelding @@ -1548,6 +1584,18 @@ Hiermee verberg je de inhoud van je chats of chatoverzicht in je taakbeheer, ook kun je geen schermafdrukken maken in Telegram.\n\nHet kan zijn dat je de app moet herstarten voordat dit actief is. Teveel pogingen.\nProbeer het opnieuw over %1$s. + January + February + March + April + May + June + July + August + September + October + November + December BESTANDEN MEDIA LINKS @@ -1612,6 +1660,7 @@ Galerij Alle foto\'s Alle media + Alle video\'s Nog geen foto\'s Download media eerst Wacht todat de video volledig is gedownload. @@ -2099,7 +2148,7 @@ Beoordeel deze oproep Wat is er misgegaan? Technische informatie versturen - We hebben geen inzage in je gesprek, maar kunnen hiermee het probleem wel sneller oplossen. + Geeft geen inzage in je gesprek, maar we kunnen hiermee het probleem wel sneller oplossen. Bedankt voor je hulp bij het verbeteren van Telegram-oproepen. Antwoorden als %s Antwoord met bericht diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index 94de629e5..bfe52e5d2 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -22,7 +22,7 @@ Ative para sincronizar continuamente contatos deste dispositivos com a sua conta. Contatos deste dispositivo foram adicionados a sua conta. - Verificação do tel. + Verificar Número Enviamos um SMS com um código de ativação para **%1$s**. Nós enviamos o código para o aplicativo do **Telegram** em seu outro dispositivo. Confira suas mensagens no Telegram @@ -49,7 +49,7 @@ Seu código de login é **%1$s**. Digite ele no app do Telegram no qual você está tentando fazer o login.\n\nNão informe esse código para ninguém. Seu nome - Por favor, digite seu nome completo e envie sua foto de perfil. + Por favor, digite seu nome completo e coloque uma foto de perfil. Nome (obrigatório) Sobrenome (opcional) Cancelar registro @@ -365,6 +365,8 @@ Fixar Mensagens Promovido por %1$s Você não tem permissão para editar os direitos desse admin. + Você não pode editar essa permissão. + Esta permissão não está disponível em grupos públicos. Removido por %1$s Permissões do Usuário Esta opção está desativada para todos os membros nas Permissões do Grupo @@ -490,7 +492,7 @@ un1 fixou essa mensagem: un1 desafixou essa mensagem: un1 encerrou a enquete: - un1 removeu essa mensagem: + un1 apagou esta mensagem: un1 alterou o pacote de sticker do grupo un1 removeu o pacote de sticker do grupo un1 alterou o link do grupo: @@ -511,7 +513,7 @@ alterou as permissões padrão Enviar Stickers & GIFs Enviar mídias - Alterar Info + Alterar info Adicionar usuários Fixar mensagens Enviar enquetes @@ -519,7 +521,7 @@ Prévia de links Ler Mensagens alterou os privilégios de %1$s - Alterar Info do canal + Alterar Info do Canal Alterar Info do grupo Postar mensagens Editar mensagens @@ -537,7 +539,7 @@ Mensagens apagadas Mensagens editadas Mensagens fixadas - Membros saindo + Membros saindo do grupo Nova Lista de Transmissão Digite o nome da lista @@ -701,10 +703,10 @@ Você Você criou um **grupo**. Grupos podem ter: - Até 100,000 membros + Até 200.000 membros "Histórico persistente do chat " Links públicos, como t.me/nome - Admins com direitos diferentes + Admins com permissões diferentes Encaminhe mensagens aqui para salvá-las Envie mídias e arquivos aqui para salvá-los Acesse este chat de qualquer dispositivo @@ -722,11 +724,11 @@ Você tem certeza de que deseja parar de gravar e descartar sua mensagem de vídeo? Descartar Os admins do grupo restringiram você de enviar mídias aqui até %1$s - Os admins do grupo restringiram você de usar bots inline aqui até %1$s + Os admins do grupo restringiram você de usar conteúdo inline aqui até %1$s. Os admins do grupo restringiram você de enviar stickers aqui até %1$s Os admins do grupo restringiram você de escrever aqui até %1$s Os admins do grupo restringiram você de enviar mídias aqui. - Os admins do grupo restringiram você de usar bots inline aqui + Os admins do grupo restringiram você de usar conteúdo inline aqui. Os admins do grupo restringiram você de enviar stickers aqui. Os admins do grupo restringiram você de escrever aqui. Não é permitido enviar mídias neste grupo. @@ -845,7 +847,7 @@ %1$s fixou um arquivo de áudio Telegram - Selecionar Contato + Selecione um Contato COMPARTILHAR CONTATO Ainda não há contatos Ei, estou usando o Telegram para conversar. Vem comigo! Baixe aqui: %1$s @@ -871,8 +873,8 @@ Compartilhar Telegram... Atualizar contatos? O Telegram detectou muitos contatos não sincronizados, você gostaria de sincronizá-los agora? Escolha \'OK\' se você está usando seu próprio celular, cartão SIM e conta do Google. - Ordernado por Nome - Ordenado por Visto por Último + Listado por Nome + Listado por Visto por Último Adicionar pessoas... Você poderá adicionar mais usuários após finalizar a criação do grupo e convertê-lo em supergrupo. @@ -967,7 +969,7 @@ O nome de usuário deve ter pelo menos 5 caracteres. O nome de usuário não pode exceder 32 caracteres. Desculpe, o nome de usuário não pode começar com um número. - Você pode escolher um nome de usuário no **Telegram**. Assim, outras pessoas poderão te encontrar pelo nome de usuário e entrar em contato sem precisar saber seu telefone.\n\nVocê pode usar **a–z**, **0–9** e underline. O tamanho mínimo é **5** caracteres. + Você pode escolher um nome de usuário no **Telegram**. Assim, outras pessoas poderão te encontrar pelo nome de usuário e entrar em contato sem precisar saber seu telefone.\n\nVocê pode usar **a–z**, **0–9** e underline.\nO tamanho mínimo é de **5** caracteres. Este link abre um chat com você:\n%1$s Verificando nome de usuário... %1$s está disponível. @@ -1020,6 +1022,7 @@ Tema Modo Noturno Automático + Desativado Desativado Programado Automático @@ -1040,17 +1043,19 @@ Insira o nome do tema FECHAR EDITOR SALVAR TEMA - Novo Tema + Novo tema de cores + Tema de cores + CRIAR TEMA APLICAR Prévia do Tema Selecionar cor - Criar Novo Tema + Criar novo tema Toque no ícone da paleta para visualizar a lista de elementos de cada tela - e editá-los. - Você pode criar seu próprio tema alterando as cores do app. Você pode voltar ao tema padrão do Telegram aqui. + Você pode criar seu próprio tema alterando as cores dentro do aplicativo.\n\nVocê sempre pode voltar para o tema padrão do Telegram aqui. Restaurar todas as configurações de notificação Deseja mesmo resetar as configurações de notificação para o padrão? - Tamanho do Texto + Tamanho do texto das mensagens Fazer uma Pergunta Permitir Animações Configurações de Chats @@ -1111,15 +1116,46 @@ Desfoque Movimento Papel de Parede + Redefinir Papéis de Parede + Remove todos os papéis de parede enviados e restaura os pré-instalados. + Deseja mesmo redefinir todos os papéis de parede? + Deseja mesmo apagar os papéis de parede selecionados? Prévia do Papel de Parede - Dica: alguns papéis de parede ficam melhores com o efeito de desfoque. - Obrigado! + Dica: alguns papéis de parede ficam melhores desfocados. + Valeu! + Deslize para os lados para ver mais cores + Salmão é um peixe, não uma cor. + Reinhardt, temos que achar umas músicas novas pra você. 🎶. + Ahh, vocês crianças de hoje em dia com essas músicas eletrônicas! Ouçam os clássicos, como Hasselhoff! + Não consigo nem te levar a sério agora. + Press \'Set\' to apply the background. + Enjoy the view. DEFINIR PAPEL DE PAREDE + Buscar por cor + Buscar Papéis de Parede + Cor: + Brilho + Código hex da cor + Cor + Textura + Intensidade + Azul + Vermelho + Laranja + Amarelo + Verde + Turquesa + Roxo + Rosa + Marrom + Preto + Cinza + Branco Selecionar uma cor Enviar imagem Selecionar imagem carregando imagem completa... - Definir uma Cor + Definir uma cor Mensagens Enviar usando \'Enter\' Eventos @@ -1146,13 +1182,13 @@ Termos de Serviço Ao se cadastrar,\nvocê concorda com os *Termos de Serviço*. https://telegram.org/privacy - Apagar localização? + Apagar tradução? Arquivo de localização incorreto Manter Serviço Ativo Reinicia o app quando ele tiver sido fechado. Ative para notificações mais estáveis. Conexão em Segundo Plano Mantém uma conexão de baixo impacto para que o Telegram receba notificações mais estáveis. - Ordenar Por + Listar Por Importar Contatos Primeiro nome Último nome @@ -1544,10 +1580,22 @@ Toque o sensor Digital não reconhecida, tente de novo. Mostrar Conteúdo do App nos Recentes - Se desativado, você não poderá fazer capturas de tela no aplicativo, mas o conteúdo do chat ficará oculto no alternador de tarefas. - Isso ocultará o conteúdo de seus chats ou lista de chats do alternador de tarefas, mas você não poderá tirar capturas de tela no Telegram.\n\nPode ser necessário reiniciar o aplicativo para que isso entre em vigor. + Se desativado, você não poderá fazer capturas de tela no aplicativo, mas o conteúdo do chat ficará oculto no multitarefas. + Isso ocultará o conteúdo de seus chats ou lista de chats do multitarefas, mas você não poderá tirar capturas de tela no Telegram.\n\nPode ser necessário reiniciar o aplicativo para que isso entre em vigor. Muitas tentativas.\nPor favor, tente de novo em %1$s. + janeiro + fevereiro + março + abril + maio + junho + julho + agosto + setembro + outubro + novembro + dezembro ARQUIVOS MÍDIA LINKS @@ -1556,7 +1604,7 @@ Arquivos Compartilhados Conteúdo Compartilhado Links Compartilhados - Música Compartilhada + Músicas Compartilhadas Compartilhar fotos e vídeos no chat e acessá-los em qualquer um de seus dispositivos. Compartilhe músicas neste chat e acesse-as de qualquer um de seus dispositivos. Compartilhar arquivos e documentos no chat e acessá-los de qualquer um de seus dispositivos. @@ -1612,11 +1660,12 @@ Galeria Todas as fotos Todas as mídias + Todos os vídeos Ainda não há fotos Por favor, baixe a mídia primeiro Aguarde que o vídeo seja baixado completamente. Este vídeo não está otimizado para streaming. Talvez você precise baixá-lo para assistir. - O app não conseguiu reproduzir o vídeo. Tentar reproduzir em um player externo? + O app não conseguiu reproduzir o vídeo. Deseja abrir em um player externo? Nenhuma foto recente Nenhum GIF recente BUSCAR IMAGENS @@ -2099,7 +2148,7 @@ Avaliar Chamada O que aconteceu de errado? Incluir informação técnica - Isso não irá revelar o conteúdo de sua conversa, mas nos ajudará a resolver o problema. + Não revela o conteúdo do chat e nos ajudará a corrigir o problema mais rápido. Agradecemos por ajudar a tornar as chamadas do Telegram melhores. Respondendo como %s Responder com Texto @@ -2116,9 +2165,9 @@ Ouvi barulho no fundo A outra pessoa ficou sumindo Fala distorcida - Eu não consegui ouvir a outra pessoa + Não consegui ouvir a outra pessoa A outra pessoa não conseguiu me ouvir - Chamada encerrada inesperadamente + Chamada encerrada do nada %1$d destinatários %1$d destinatário diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 831c33b61..aa4a239ac 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -531,7 +531,7 @@ Add users Pin messages All actions - New exception + New exceptions New admins New members Group info @@ -703,7 +703,7 @@ You You have created a **group**. Groups can have: - Up to 100,000 members + Up to 200,000 members Persistent chat history Public links such as t.me/title Admins with different rights @@ -731,10 +731,10 @@ The admins of this group have restricted you from sending inline content here The admins of this group have restricted you from sending stickers. The admins of this group have restricted you from writing here. - Sending media isn’t allowed in this group. - Inline bots aren’t allowed in this group. - Stickers aren’t allowed in this group. - Writing messages isn’t allowed in this group. + Sending media isn\'t allowed in this group. + Inline bots aren\'t allowed in this group. + Stickers aren\'t allowed in this group. + Writing messages isn\'t allowed in this group. admin APK installation is restricted for this app. You can enable this in system settings. Unread Messages @@ -1022,6 +1022,7 @@ Theme Auto-Night Mode + Off Disabled Scheduled Automatic @@ -1042,17 +1043,19 @@ Enter theme name CLOSE EDITOR SAVE THEME - New Theme + New color theme + Color theme + CREATE THEME APPLY Theme Preview Select color - Create New Theme + Create new theme Tap on the palette icon to view the list of elements on each screen - and edit them. - You can create your own theme by changing colors within the app. You can always switch back to the default Telegram theme here. + You can create your own theme by changing colors within the app.\n\nYou can always switch back to the default Telegram theme here. Reset all notification settings to default Are you sure you want to reset all notification settings to default? - Messages Text Size + Messages text size Ask a Question Enable Animations Chat Settings @@ -1113,10 +1116,41 @@ Blurred Motion Chat Background + Reset Chat Backgrounds + Remove all uploaded chat backgrounds and restore the pre-installed ones. + Are you sure you want to reset all chat backgrounds? + Are you sure you want to delete the selected backgrounds? Background Preview - Hint: some background images look better with blur effect. - Thank you! + Hint: some background images look better when blurred. + Woo-hoo! Thanks + Swipe left or right to see more colors. + Salmon is a fish, not a color. + Reinhardt, we need to find you some new tunes 🎶. + Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff! + I can\'t even take you seriously right now. + Press \'Set\' to apply the background. + Enjoy the view. SET BACKGROUND + Search by color + Search Backgrounds + Color: + Brightness + Hex color code + Color + Pattern + Intensity + Blue + Red + Orange + Yellow + Green + Teal + Purple + Pink + Brown + Black + Gray + White Select a color Upload image Select image @@ -1210,6 +1244,8 @@ Default Smart Notifications Exceptions + Add an Exception + New Exception This section will list all chats with non-default notification settings.\n\nYou can customize notifications for a chat by opening its profile and choosing \'Notifications\'. None %1$d / %2$s @@ -1550,6 +1586,18 @@ This will hide the contents of your chats or chat list from the task switcher, but you will not be able to take screenshots on Telegram.\n\nYou may need to restart the app for this to take effect. Too many tries.\nPlease try again in %1$s. + January + February + March + April + May + June + July + August + September + October + November + December FILES MEDIA LINKS @@ -1614,6 +1662,7 @@ Gallery All photos All media + All videos No photos yet Please download media first Please wait for the video to be fully downloaded. @@ -2101,7 +2150,7 @@ Rate Call What went wrong? Include technical information - This won\'t reveal the contents of your conversation, but will help us fix the issue sooner. + Doesn\'t reveal chat contents and helps us fix the issue sooner. Thank you for helping make Telegram calls better. Answering as %s Respond with Text