diff --git a/Telegram/Resources/all_files.style b/Telegram/Resources/all_files.style index f6a7ca6d6..442ad90d7 100644 --- a/Telegram/Resources/all_files.style +++ b/Telegram/Resources/all_files.style @@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org using "basic_types.style"; using "basic.style"; +using "boxes/boxes.style"; using "dialogs/dialogs.style"; using "history/history.style"; using "overview/overview.style"; diff --git a/Telegram/Resources/art/sprite.png b/Telegram/Resources/art/sprite.png index 809d0201a..932c1d990 100644 Binary files a/Telegram/Resources/art/sprite.png and b/Telegram/Resources/art/sprite.png differ diff --git a/Telegram/Resources/art/sprite_200x.png b/Telegram/Resources/art/sprite_200x.png index 2c1270a99..dcad41196 100644 Binary files a/Telegram/Resources/art/sprite_200x.png and b/Telegram/Resources/art/sprite_200x.png differ diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index 8516585ce..94f8555f6 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -1868,6 +1868,9 @@ stickersSettings: sprite(140px, 124px, 21px, 22px); savedGifsOver: sprite(329px, 286px, 21px, 22px); savedGifsActive: sprite(350px, 286px, 21px, 22px); +stickersSettingsUnreadSize: 17px; +stickersSettingsUnreadPosition: point(4px, 5px); + emojiPanCategories: #f7f7f7; rbEmoji: flatCheckbox { @@ -2141,7 +2144,9 @@ mvCaptionRadius: 2px; mvCaptionBg: #11111180; mvCaptionFont: font(fsize); -medviewSaveMsgCheck: sprite(311px, 309px, 22px, 18px); +medviewSaveMsgCheck: icon { + { "mediaview_save_check", #ffffff } +}; medviewSaveMsgFont: font(16px); medviewSaveMsgPadding: margins(55px, 19px, 29px, 20px); medviewSaveMsgCheckPos: point(23px, 21px); diff --git a/Telegram/Resources/icons/media_fullscreen_from.png b/Telegram/Resources/icons/media_fullscreen_from.png index 6d241d992..7b3ae509d 100644 Binary files a/Telegram/Resources/icons/media_fullscreen_from.png and b/Telegram/Resources/icons/media_fullscreen_from.png differ diff --git a/Telegram/Resources/icons/media_fullscreen_from@2x.png b/Telegram/Resources/icons/media_fullscreen_from@2x.png index 448b42b0f..10b1ce125 100644 Binary files a/Telegram/Resources/icons/media_fullscreen_from@2x.png and b/Telegram/Resources/icons/media_fullscreen_from@2x.png differ diff --git a/Telegram/Resources/icons/media_fullscreen_to.png b/Telegram/Resources/icons/media_fullscreen_to.png index 43c7a54c7..9ce7f75af 100644 Binary files a/Telegram/Resources/icons/media_fullscreen_to.png and b/Telegram/Resources/icons/media_fullscreen_to.png differ diff --git a/Telegram/Resources/icons/media_fullscreen_to@2x.png b/Telegram/Resources/icons/media_fullscreen_to@2x.png index cf386f13d..723630333 100644 Binary files a/Telegram/Resources/icons/media_fullscreen_to@2x.png and b/Telegram/Resources/icons/media_fullscreen_to@2x.png differ diff --git a/Telegram/Resources/icons/media_pause.png b/Telegram/Resources/icons/media_pause.png index 2ae4e1ebb..f4291828d 100644 Binary files a/Telegram/Resources/icons/media_pause.png and b/Telegram/Resources/icons/media_pause.png differ diff --git a/Telegram/Resources/icons/media_pause@2x.png b/Telegram/Resources/icons/media_pause@2x.png index ffba955ad..24a8b16f0 100644 Binary files a/Telegram/Resources/icons/media_pause@2x.png and b/Telegram/Resources/icons/media_pause@2x.png differ diff --git a/Telegram/Resources/icons/media_play.png b/Telegram/Resources/icons/media_play.png index 018ef78e9..4b845b519 100644 Binary files a/Telegram/Resources/icons/media_play.png and b/Telegram/Resources/icons/media_play.png differ diff --git a/Telegram/Resources/icons/media_play@2x.png b/Telegram/Resources/icons/media_play@2x.png index 44805a939..74911abe6 100644 Binary files a/Telegram/Resources/icons/media_play@2x.png and b/Telegram/Resources/icons/media_play@2x.png differ diff --git a/Telegram/Resources/icons/mediaview_save_check.png b/Telegram/Resources/icons/mediaview_save_check.png new file mode 100644 index 000000000..33be1af78 Binary files /dev/null and b/Telegram/Resources/icons/mediaview_save_check.png differ diff --git a/Telegram/Resources/icons/mediaview_save_check@2x.png b/Telegram/Resources/icons/mediaview_save_check@2x.png new file mode 100644 index 000000000..d9d3bd85b Binary files /dev/null and b/Telegram/Resources/icons/mediaview_save_check@2x.png differ diff --git a/Telegram/Resources/icons/stickers_add.png b/Telegram/Resources/icons/stickers_add.png new file mode 100644 index 000000000..ac6c2a166 Binary files /dev/null and b/Telegram/Resources/icons/stickers_add.png differ diff --git a/Telegram/Resources/icons/stickers_add@2x.png b/Telegram/Resources/icons/stickers_add@2x.png new file mode 100644 index 000000000..de8948d66 Binary files /dev/null and b/Telegram/Resources/icons/stickers_add@2x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 771cd8a25..f356cc219 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -190,6 +190,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_reset_account" = "Reset your account"; "lng_signin_sure_reset" = "Warning!\n\nYou will lose all your chats and messages, along with any media and files you shared!\n\nDo you want to reset your account?"; "lng_signin_reset" = "Reset"; +"lng_signin_reset_wait" = "Since the account {phone_number} is active and protected by a password, we will delete it in 1 week for security purposes. You can cancel this process at any time.\n\nYou’ll be able to reset your account in:\n{when}"; +"lng_signin_reset_in_days" = "{count_days:0 days|# day|# days} {count_hours:0 hours|# hour|# hours} {count_minutes:0 minutes|# minute|# minutes}"; +"lng_signin_reset_in_hours" = "{count_hours:0 hours|# hour|# hours} {count_minutes:0 minutes|# minute|# minutes}"; +"lng_signin_reset_in_minutes" = "{count_minutes:0 minutes|# minute|# minutes}"; +"lng_signin_reset_cancelled" = "Your recent attempts to reset this account have been cancelled by its active user. Please try again in 7 days."; "lng_signup_title" = "Information and photo"; "lng_signup_desc" = "Please enter your name and\nupload a photo."; @@ -602,6 +607,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_group_invite_want_join_channel" = "Do you want to join the channel «{title}»?"; "lng_group_invite_join" = "Join"; +"lng_group_invite_members" = "{count:_not_used_|# member|# members}, among them:"; + "lng_group_invite_link" = "Invite link:"; "lng_group_invite_create" = "Create an invite link"; "lng_group_invite_about" = "Telegram users will be able to join\nyour group by following this link."; @@ -664,6 +671,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_emoji_category6" = "Objects"; "lng_emoji_category7" = "Symbols & Flags"; +"lng_recent_stickers" = "Frequently used"; "lng_switch_stickers" = "Stickers"; "lng_switch_stickers_gifs" = "GIFs & Stickers"; "lng_switch_emoji" = "Emoji"; @@ -680,12 +688,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_stickers_add_pack" = "Add stickers"; "lng_stickers_share_pack" = "Share Stickers"; "lng_stickers_not_found" = "Sticker pack not found."; -"lng_stickers_too_many_packs" = "You have too many sticker packs. Please remove some first."; +"lng_stickers_packs_archived" = "Some of your unused stickers have been archived to make room for the sets you've activated."; +"lng_stickers_archived" = "Archived Stickers"; "lng_stickers_copied" = "Sticker pack link copied to clipboard."; "lng_stickers_default_set" = "Great Minds"; "lng_stickers_you_have" = "Manage and reorder sticker packs"; "lng_stickers_packs" = "Sticker Packs"; "lng_stickers_reorder" = "Click and drag to reorder sticker packs"; +"lng_stickers_featured" = "Trending Stickers"; +"lng_stickers_clear_recent" = "Clear"; +"lng_stickers_clear_recent_sure" = "Are you sure you want to clear your frequently used stickers list?"; "lng_stickers_remove" = "Delete"; "lng_stickers_return" = "Undo"; "lng_stickers_restore" = "Restore"; @@ -922,12 +934,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}"; "lng_new_version_minor" = "— Bug fixes and other minor improvements"; -"lng_new_version_text" = "— Fixed photo viewer to handle screen resolution change correctly\n— Fixed forwarding photos via drag-n-drop\n— Various design improvements and other bug fixes"; +"lng_new_version_text" = "— Trending stickers. Check out and install noteworthy sticker packs from the new tab in Settings.\n— Archived stickers. Unused stickers are now archived automatically when you go over the 200 limit.\n— Group previews. Preview groups before joining them via invite link – see who else is in the group before joining.\n— New internal video player.\n— Improved design for chats."; "lng_menu_insert_unicode" = "Insert Unicode control character"; "lng_full_name" = "{first_name} {last_name}"; +"lng_confirm_phone_link_invalid" = "This link is broken or has expired."; +"lng_confirm_phone_title" = "Cancel account reset"; +"lng_confirm_phone_about" = "Somebody with access to your phone number {phone} has requested to delete your Telegram account and reset your 2-Step Verification password.\n\nIf this wasn't you, please enter the code we've just sent you via SMS to your number."; +"lng_confirm_phone_success" = "Success!\n\nThe deletion process was cancelled for your account {phone}. You may close this window now."; +"lng_confirm_phone_send" = "Send"; +"lng_confirm_phone_enter_code" = "Please enter the code."; + // Not used "lng_topbar_info" = "Info"; diff --git a/Telegram/Resources/langs/lang_de.strings b/Telegram/Resources/langs/lang_de.strings index 5a27b31c2..052545c7e 100644 --- a/Telegram/Resources/langs/lang_de.strings +++ b/Telegram/Resources/langs/lang_de.strings @@ -190,6 +190,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_reset_account" = "Konto zurücksetzen"; "lng_signin_sure_reset" = "Hinweis!\n\nDu verlierst du alle Chats und Nachrichten, ebenso deine geteilten Bilder und Videos.\n\nKonto wirklich zurücksetzen?"; "lng_signin_reset" = "Zurücksetzen"; +"lng_signin_reset_wait" = "Da dein Konto {phone_number} aktiv und durch ein Kennwort geschützt ist, löschen wir es aus Sicherheitsgründen in einer Woche. Du kannst den Vorgang jederzeit abbrechen.\n\nDu kannst dein Konto zurücksetzen in:\n{when}"; +"lng_signin_reset_in_days" = "{count_days:0 Tage|# Tag|# Tage} {count_hours:0 Stunden|# Stunde|# Stunden} {count_minutes:0 Minuten|# Minute|# Minuten}"; +"lng_signin_reset_in_hours" = "{count_hours:0 Stunden|# Stunde|# Stunden} {count_minutes:0 Minuten|# Minute|# Minuten}"; +"lng_signin_reset_in_minutes" = "{count_minutes:0 Minuten|# Minute|# Minuten}"; +"lng_signin_reset_cancelled" = "Deine vorherigen Versuche das Konto zurückzusetzen wurden durch den aktiven Nutzer abgebrochen. Bitte in 7 Tagen erneut probieren."; "lng_signup_title" = "Information und Bild"; "lng_signup_desc" = "Bitte trage deinen Namen ein \nund lade ein Bild hoch."; @@ -602,6 +607,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_group_invite_want_join_channel" = "Möchtest du dem Kanal «{title}» beitreten?"; "lng_group_invite_join" = "Beitreten"; +"lng_group_invite_members" = "{count:_not_used_|# Mitglied|# Mitglieder}, darunter:"; + "lng_group_invite_link" = "Einladungslink:"; "lng_group_invite_create" = "Neuer Link"; "lng_group_invite_about" = "Jeder, der Telegram installiert hat,\nkann anhand dieses Links in deine Gruppe."; @@ -664,6 +671,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_emoji_category6" = "Objekte"; "lng_emoji_category7" = "Symbole & Flaggen"; +"lng_recent_stickers" = "Häufig genutzt"; "lng_switch_stickers" = "Sticker"; "lng_switch_stickers_gifs" = "GIFs & Sticker"; "lng_switch_emoji" = "Emoji"; @@ -680,11 +688,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_stickers_add_pack" = "Sticker hinzufügen"; "lng_stickers_share_pack" = "Sticker teilen"; "lng_stickers_not_found" = "Sticker-Paket nicht gefunden."; +"lng_stickers_packs_archived" = "Einige deiner unbenutzen Sticker wurden archiviert, damit du Platz für neue Sticker hast."; +"lng_stickers_archived" = "Archivierte Sticker"; "lng_stickers_copied" = "Sticker-Paket Link in die Zwischenablage kopiert."; "lng_stickers_default_set" = "Große Denker"; "lng_stickers_you_have" = "Sticker-Pakete verwalten"; "lng_stickers_packs" = "Sticker-Pakete"; "lng_stickers_reorder" = "Paket gedrückt halten und verschieben um die Anordnung zu ändern"; +"lng_stickers_featured" = "Angesagte Sticker"; +"lng_stickers_clear_recent" = "Leeren"; +"lng_stickers_clear_recent_sure" = "Zuletzt benutzte Sticker leeren?"; "lng_stickers_remove" = "Löschen"; "lng_stickers_return" = "Rückgängig"; "lng_stickers_restore" = "Zeigen"; @@ -881,7 +894,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_selected_forward" = "Weiterleiten"; "lng_selected_count" = "{count:_not_used_|# Nachricht|# Nachrichten}"; "lng_selected_cancel_sure_this" = "Upload abbrechen?"; -"lng_selected_upload_stop" = "Abbrechen"; +"lng_selected_upload_stop" = "Stoppen"; "lng_selected_delete_sure_this" = "Diese Nachricht wirklich löschen?"; "lng_selected_delete_sure" = "Willst du {count:_not_used_|# Nachricht|# Nachrichten} löschen?"; "lng_delete_photo_sure" = "Dieses Bild wirklich löschen?"; @@ -921,12 +934,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}"; "lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen"; -"lng_new_version_text" = "— Fehlerbehebung: Bildbetrachter sollte Änderungen der Bildschirmauflösung korrekt handhaben\n— Fehlerbehebung: Bilder per Drag’n’Drop weiterleiten\n— Verschiedene optische Verbesserungen und sonstige Fehlerbehebungen"; +"lng_new_version_text" = "— Angesagte Sticker: In den Einstellungen, im Bereich Sticker, stehen interessante Stickerpakete bereit.\n— Archivierte Sticker: Unbenutze Sticker werden automatisch archiviert, sobald das Limit (200) erreicht wird.\n— Gruppenvorschau: Vor dem Betreten der Gruppe wird dir angezeigt, wer bereits Mitglied ist.\n— Neuer interner Videoplayer.\n— Verbessertes Chatdesign."; "lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen"; "lng_full_name" = "{first_name} {last_name}"; +"lng_confirm_phone_link_invalid" = "Dieser Link ist abgelaufen oder ungültig."; +"lng_confirm_phone_title" = "Zurücksetzung abbrechen"; +"lng_confirm_phone_about" = "Jemand mit Zugang zu deiner Telefonnummer {phone} hat die Kontolöschung und Zurücksetzung der zweistufige Bestätigung beantragt.\n\nWenn du das nicht selbst gewesen bist, tippe den Code der SMS ein, den wir dir gerade gesendet haben."; +"lng_confirm_phone_success" = "Geschafft!\n\nDer Löschvorgang für dein Konto {phone} wurde abgebrochen. Du kannst dieses Fenster jetzt schließen."; +"lng_confirm_phone_send" = "Senden"; +"lng_confirm_phone_enter_code" = "Bitte den Code eingeben."; + // Not used "lng_topbar_info" = "Info"; diff --git a/Telegram/Resources/langs/lang_es.strings b/Telegram/Resources/langs/lang_es.strings index c44a14d84..005bc2fa4 100644 --- a/Telegram/Resources/langs/lang_es.strings +++ b/Telegram/Resources/langs/lang_es.strings @@ -190,6 +190,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_reset_account" = "Restablecer tu cuenta"; "lng_signin_sure_reset" = "¡Advertencia!\n\n¡Perderás todos tus chats y mensajes, junto con la multimedia y archivos compartidos!\n\n¿Quieres restablecer tu cuenta?"; "lng_signin_reset" = "Restablecer"; +"lng_signin_reset_wait" = "Como la cuenta {phone_number} está activa y protegida con una contraseña, la eliminaremos en 1 semana, por motivos de seguridad. Puedes cancelar el proceso en cualquier momento.\n\nPodrás restablecer tu cuenta en:\n{when}"; +"lng_signin_reset_in_days" = "{count_days:0 días|# día|# días} {count_hours:0 horas|# hora|# horas} {count_minutes:0 minutos|# minuto|# minutos}"; +"lng_signin_reset_in_hours" = "{count_hours:0 horas|# hora|# horas} {count_minutes:0 minutos|# minuto|# minutos}"; +"lng_signin_reset_in_minutes" = "{count_minutes:0 minutos|# minuto|# minutos}"; +"lng_signin_reset_cancelled" = "Tus intentos recientes para restablecer la cuenta fueron cancelados por su usuario activo. Por favor, reinténtalo en 7 días."; "lng_signup_title" = "Información y foto"; "lng_signup_desc" = "Por favor, pon tu nombre \ny una foto."; @@ -602,6 +607,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_group_invite_want_join_channel" = "¿Quieres unirte al canal «{title}»?"; "lng_group_invite_join" = "Unirme"; +"lng_group_invite_members" = "{count:_not_used_|# miembro|# miembros}, entre ellos:"; + "lng_group_invite_link" = "Enlace de invitación:"; "lng_group_invite_create" = "Crear un enlace de invitación"; "lng_group_invite_about" = "Los usuarios de Telegram podrán unirse\na tu grupo a través de este enlace."; @@ -664,6 +671,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_emoji_category6" = "Objetos"; "lng_emoji_category7" = "Símbolos y banderas"; +"lng_recent_stickers" = "Uso frecuente"; "lng_switch_stickers" = "Stickers"; "lng_switch_stickers_gifs" = "GIF y stickers"; "lng_switch_emoji" = "Emoji"; @@ -680,11 +688,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_stickers_add_pack" = "Añadir stickers"; "lng_stickers_share_pack" = "Compartir stickers"; "lng_stickers_not_found" = "Pack de stickers no encontrado."; +"lng_stickers_packs_archived" = "Algunos de los stickers que no usas fueron archivados. Así tendrás más espacio para los packs que activaste."; +"lng_stickers_archived" = "Stickers archivados"; "lng_stickers_copied" = "Enlace del pack de stickers copiado al portapapeles."; "lng_stickers_default_set" = "Grandes personajes"; "lng_stickers_you_have" = "Administrar y ordenar los packs de stickers"; "lng_stickers_packs" = "Packs de stickers"; "lng_stickers_reorder" = "Haz clic y arrastra para ordenar los packs"; +"lng_stickers_featured" = "Stickers destacados"; +"lng_stickers_clear_recent" = "Borrar"; +"lng_stickers_clear_recent_sure" = "¿Quieres borrar la lista de stickers usados frecuentemente?"; "lng_stickers_remove" = "Eliminar"; "lng_stickers_return" = "Deshacer"; "lng_stickers_restore" = "Restaurar"; @@ -880,7 +893,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_selected_delete" = "Eliminar"; "lng_selected_forward" = "Reenviar"; "lng_selected_count" = "{count:_not_used_|# mensaje|# mensajes}"; -"lng_selected_cancel_sure_this" = "¿Cancelar envío?"; +"lng_selected_cancel_sure_this" = "¿Detener el envío?"; "lng_selected_upload_stop" = "Detener"; "lng_selected_delete_sure_this" = "¿Quieres eliminar este mensaje?"; "lng_selected_delete_sure" = "¿Quieres eliminar {count:_not_used_|# mensaje|# mensajes}?"; @@ -921,12 +934,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop ha sido actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}"; "lng_new_version_minor" = "— Corrección de errores y otras mejoras menores"; -"lng_new_version_text" = "— Corrección en el visor de fotos, para manejar correctamente el cambio de la resolución de la pantalla\n— Corrección en el reenvío de fotos a través de arrastrar y soltar \n— Varias mejoras de diseño y corrección de otros errores"; +"lng_new_version_text" = "— Stickers destacados. Mira e instala packs de stickers desde la nueva pestaña en Ajustes.\n— Stickers archivados. Ahora, los packs de stickers que no usas, se archivan automáticamente cuando superas el límite de 200.\n— Vista previa de grupos. Mira un grupo antes de unirte a él a través del enlace de invitación. Mira quién está en el grupo antes de unirte.\n— Nuevo reproductor interno de vídeo.\n— Diseño mejorado de chats."; "lng_menu_insert_unicode" = "Insertar caracteres de control Unicode"; "lng_full_name" = "{first_name} {last_name}"; +"lng_confirm_phone_link_invalid" = "El enlace está roto o ha expirado."; +"lng_confirm_phone_title" = "No restablecer la cuenta"; +"lng_confirm_phone_about" = "Alguien, con acceso a tu número de teléfono {phone}, solicitó eliminar tu cuenta de Telegram y restablecer tu contraseña de la verificación en dos pasos.\n\nSi no eras tú, por favor, inserta el código que enviamos por SMS a tu número."; +"lng_confirm_phone_success" = "¡Listo!\n\nEl proceso de eliminación de la cuenta {phone} fue cancelado. Puedes cerrar esta ventana ahora."; +"lng_confirm_phone_send" = "Enviar"; +"lng_confirm_phone_enter_code" = "Por favor, pon el código."; + // Not used "lng_topbar_info" = "Información"; diff --git a/Telegram/Resources/langs/lang_it.strings b/Telegram/Resources/langs/lang_it.strings index b1fc73663..b90c6fee3 100644 --- a/Telegram/Resources/langs/lang_it.strings +++ b/Telegram/Resources/langs/lang_it.strings @@ -190,6 +190,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_reset_account" = "Ripristina il tuo account"; "lng_signin_sure_reset" = "Attenzione!\n\nPerderai tutte le chat e i messaggi, insieme a tutti i media e i file condivisi!\n\nVuoi ripristinare il tuo account?"; "lng_signin_reset" = "Ripristina"; +"lng_signin_reset_wait" = "Dato che l'account {phone_number} è attivo e protetto da una password, lo elimineremo tra 1 settimana per motivi di sicurezza. Puoi annullare questo processo in qualsiasi momento.\n\nSarai in grado di ripristinare il tuo account tra:\n{when}"; +"lng_signin_reset_in_days" = "{count_days:0 giorni|# giorno|# giorni} {count_hours:0 ore|# ora|# ore} {count_minutes:0 minuti|# minuto|# minuti}"; +"lng_signin_reset_in_hours" = "{count_hours:0 ore|# ora|# ore} {count_minutes:0 minuti|# minuto|# minuti}"; +"lng_signin_reset_in_minutes" = "{count_minutes:0 minuti|# minuto|# minuti}"; +"lng_signin_reset_cancelled" = "I tuoi tentativi recenti di ripristinare questo account sono stati annullati dal suo utente attivo. Per favore riprova tra 7 giorni."; "lng_signup_title" = "Info e foto"; "lng_signup_desc" = "Inserisci il tuo nome e\ncarica una foto."; @@ -202,7 +207,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_dlg_new_channel_name" = "Nome canale"; "lng_no_contacts" = "Non hai contatti"; "lng_no_chats" = "Le tua chat saranno qui"; -"lng_contacts_loading" = "Caricamento..."; +"lng_contacts_loading" = "Carico..."; "lng_contacts_not_found" = "Nessun contatto trovato"; "lng_dlg_search_chat" = "Cerca in questa chat"; "lng_dlg_search_channel" = "Cerca in questo canale"; @@ -211,7 +216,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_settings_save" = "Salva"; "lng_settings_upload" = "Imposta foto profilo"; "lng_settings_crop_profile" = "Seleziona un riquadro per la tua foto profilo"; -"lng_settings_uploading_photo" = "Caricamento foto..."; +"lng_settings_uploading_photo" = "Carico foto..."; "lng_username_title" = "Username"; "lng_username_about" = "Puoi scegliere un username su Telegram.\nSe lo fai, le altre persone potranno trovarti\ntramite questo username e contattarti \nsenza conoscere il tuo numero di telefono.\n\nPuoi usare a-z, 0-9 e underscore.\nLa lunghezza minima è di 5 caratteri."; @@ -348,7 +353,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_cloud_password_email" = "Inserisci email di recupero"; "lng_cloud_password_bad_email" = "E-mail non valida, riprova con un'altra."; "lng_cloud_password_about" = "La password sarà richiesta quando ti connetti da un nuovo dispositivo insieme al codice."; -"lng_cloud_password_about_recover" = "Attenzione! Sei sicuro di non voler\naggiungere un'e-mail di recupero?\n\nSe dimentichi la tua password, perderai\nl'accesso al tuo account Telegram."; +"lng_cloud_password_about_recover" = "Attenzione! Sicuro di non voler\naggiungere un'e-mail di recupero?\n\nSe dimentichi la tua password, perderai\nl'accesso al tuo account Telegram."; "lng_cloud_password_skip_email" = "Salta e-mail"; "lng_cloud_password_almost" = "Abbiamo inviato un link di conferma\nall'e-mail che ci hai fornito. La verifica in due passaggi sarà attivata non appena aprirai quel link."; "lng_cloud_password_was_set" = "Verifica in due passaggi abilitata."; @@ -445,7 +450,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_profile_sure_kick" = "Rimuovere {user} dal gruppo?"; "lng_profile_sure_kick_channel" = "Rimuovere {user} dal canale?"; "lng_profile_sure_kick_admin" = "Rimuovere {user} dagli amministratori?"; -"lng_profile_loading" = "Caricamento..."; +"lng_profile_loading" = "Carico..."; "lng_profile_shared_media" = "Media condivisi"; "lng_profile_no_media" = "Nessun media in questa chat."; "lng_profile_photos" = "{count:_not_used_|# foto|# foto}"; @@ -528,10 +533,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_sure_delete_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi con {contact}?\n\nQuesta azione non può essere annullata."; "lng_sure_delete_group_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi in «{group}»?\n\nQuesta azione non può essere annullata."; "lng_sure_delete_and_exit" = "Sicuro di voler eliminare tutta la cronologia dei messaggi e abbandonare «{group}»?\n\nQuesta azione non può essere annullata."; -"lng_sure_leave_channel" = "Sei sicuro di voler lasciare\nquesto canale?"; -"lng_sure_delete_channel" = "Sei sicuro di voler eliminare questo canale? Tutti i membri verranno rimossi e i messaggi verranno persi."; +"lng_sure_leave_channel" = "Sicuro di voler lasciare\nquesto canale?"; +"lng_sure_delete_channel" = "Sicuro di voler eliminare questo canale? Tutti i membri verranno rimossi e i messaggi verranno persi."; "lng_sure_leave_group" = "Sicuro di voler lasciare questo gruppo?\nQuesta azione non può essere annullata."; -"lng_sure_delete_group" = "Sei sicuro di voler eliminare questo gruppo? Tutti i membri verranno rimossi e i messaggi verranno persi."; +"lng_sure_delete_group" = "Sicuro di voler eliminare questo gruppo? Tutti i membri verranno rimossi e i messaggi verranno persi."; "lng_message_empty" = "Messaggio vuoto"; "lng_message_unsupported" = "Questo messaggio non è supportato dalla tua versione di Telegram Desktop. Per favore, aggiorna all'ultima versione dalle Impostazioni o installalo da {link}"; @@ -585,7 +590,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_profile_convert_about" = "Nei supergruppi:"; "lng_profile_convert_feature1" = "— I nuovi membri vedono tutta la cronologia"; "lng_profile_convert_feature2" = "— I messaggi eliminati scompaiono per tutti"; -"lng_profile_convert_feature3" = "— Gli amministratori possono fissare i messaggi"; +"lng_profile_convert_feature3" = "— Gli admin possono fissare i messaggi importanti"; "lng_profile_convert_feature4" = "— Il creatore può creare un link pubblico per il gruppo"; "lng_profile_convert_warning" = "{bold_start}Nota:{bold_end} Questa azione non può essere annullata"; "lng_profile_convert_confirm" = "Converti"; @@ -602,6 +607,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_group_invite_want_join_channel" = "Vuoi unirti al canale «{title}»?"; "lng_group_invite_join" = "Unisciti"; +"lng_group_invite_members" = "{count:_not_used_|# membro|# membri}, tra cui:"; + "lng_group_invite_link" = "Link di invito:"; "lng_group_invite_create" = "Crea un link di invito"; "lng_group_invite_about" = "Gli utenti di Telegram potranno \nunirsi al tuo gruppo aprendo il link."; @@ -655,7 +662,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_media_auto_groups" = "Gruppi e canali"; "lng_media_auto_play" = "Autoriproduzione"; -"lng_emoji_category0" = "Utilizzate di frequente"; +"lng_emoji_category0" = "Usate di frequente"; "lng_emoji_category1" = "Persone"; "lng_emoji_category2" = "Natura"; "lng_emoji_category3" = "Cibo e bevande"; @@ -664,6 +671,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_emoji_category6" = "Oggetti"; "lng_emoji_category7" = "Simboli e bandiere"; +"lng_recent_stickers" = "Usati di frequente"; "lng_switch_stickers" = "Sticker"; "lng_switch_stickers_gifs" = "GIF e Sticker"; "lng_switch_emoji" = "Emoji"; @@ -680,15 +688,20 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_stickers_add_pack" = "Aggiungi sticker"; "lng_stickers_share_pack" = "Condividi sticker"; "lng_stickers_not_found" = "Set di sticker non trovato."; +"lng_stickers_packs_archived" = "Alcuni dei tuoi sticker non usati sono stati archiviati per fare spazio ai set che hai attivato."; +"lng_stickers_archived" = "Sticker archiviati"; "lng_stickers_copied" = "Link degli sticker copiato negli appunti."; "lng_stickers_default_set" = "Grandi menti"; "lng_stickers_you_have" = "Organizza e riordina i set di sticker"; "lng_stickers_packs" = "Set di sticker"; "lng_stickers_reorder" = "Clicca e trascina per riordinare i set di sticker"; +"lng_stickers_featured" = "Sticker in primo piano"; +"lng_stickers_clear_recent" = "Cancella"; +"lng_stickers_clear_recent_sure" = "Sicuro di voler cancellare la lista degli sticker usati di recente?"; "lng_stickers_remove" = "Elimina"; "lng_stickers_return" = "Annulla"; "lng_stickers_restore" = "Ripristina"; -"lng_stickers_count" = "{count:Caricamento...|# sticker|# sticker}"; +"lng_stickers_count" = "{count:Carico...|# sticker|# sticker}"; "lng_in_dlg_photo" = "Foto"; "lng_in_dlg_video" = "File video"; @@ -704,9 +717,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_report_spam" = "Segnala spam"; "lng_report_spam_hide" = "Nascondi"; "lng_report_spam_thanks" = "Grazie per la tua segnalazione!"; -"lng_report_spam_sure" = "Sei sicuro di voler segnalare questo utente come spam?"; -"lng_report_spam_sure_group" = "Sei sicuro di voler segnalare dello spam in questo gruppo?"; -"lng_report_spam_sure_channel" = "Sei sicuro di voler segnalare dello spam in questo canale?"; +"lng_report_spam_sure" = "Sicuro di voler segnalare questo utente come spam?"; +"lng_report_spam_sure_group" = "Sicuro di voler segnalare dello spam in questo gruppo?"; +"lng_report_spam_sure_channel" = "Sicuro di voler segnalare dello spam in questo canale?"; "lng_report_spam_ok" = "Segnala"; "lng_cant_send_to_not_contact" = "Spiacenti, ma al momento puoi scrivere\nsolo ai contatti reciproci.\n{more_info}"; "lng_cant_invite_not_contact" = "Spiacenti, ma al momento puoi aggiungere\nai gruppi solo contatti reciproci.\n{more_info}"; @@ -921,12 +934,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli aggiornamenti è disponibile qui:\n{link}"; "lng_new_version_minor" = "— Risoluzione di problemi e altri miglioramenti minori"; -"lng_new_version_text" = "— Il visualizzatore delle foto ora gestisce i cambi di risoluzione dello schermo correttamente\n— Risolto l'inoltro di foto via drag-n-drop\n— Miglioramenti di design e risoluzione di problemi"; +"lng_new_version_text" = "— Sticker in primo piano. Visualizza e installa set di sticker degni di nota dalla nuova scheda nelle Impostazioni.\n— Sticker archiviati. Gli sticker non utilizzati sono ora archiviati automaticamente quando vai oltre il limite dei 200 set.\n— Anteprime dei gruppi. Visualizza l'anteprima dei gruppi prima di unirti tramite link di invito - guarda chi è nel gruppo prima di unirti.\n— Nuovo lettore video interno.\n— Design migliorato per le chat."; "lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode"; "lng_full_name" = "{first_name} {last_name}"; +"lng_confirm_phone_link_invalid" = "Questo link non funziona o è scaduto."; +"lng_confirm_phone_title" = "Annulla ripristino account"; +"lng_confirm_phone_about" = "Qualcuno con accesso al tuo numero di telefono {phone} ha richiesto l'eliminazione del tuo account Telegram e il ripristino della password della verifica in due passaggi.\n\nSe non sei stato tu, per favore inserisci il codice che abbiamo appena inviato come SMS al tuo numero."; +"lng_confirm_phone_success" = "Fatto!\n\nIl processo di eliminazione per il tuo account {phone} è stato annullato. Puoi chiudere questa finestra ora."; +"lng_confirm_phone_send" = "Invia"; +"lng_confirm_phone_enter_code" = "Per favore inserisci il codice."; + // Not used "lng_topbar_info" = "Info"; diff --git a/Telegram/Resources/langs/lang_ko.strings b/Telegram/Resources/langs/lang_ko.strings index 40d4bf50a..9d341f089 100644 --- a/Telegram/Resources/langs/lang_ko.strings +++ b/Telegram/Resources/langs/lang_ko.strings @@ -190,6 +190,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_reset_account" = "계정 초기화"; "lng_signin_sure_reset" = "경고!\n\n계정 초기화 진행시 모든 대화,\n메시지 및 공유받은 미디어와 파일이 삭제가 됩니다.\n\n계정 초기화를 진행하시겠습니까?"; "lng_signin_reset" = "초기화"; +"lng_signin_reset_wait" = "{phone_number} 계정이 사용중이고 비밀번호 설정이 되어져 있어, 보안을 위하여 1주일 이후에 삭제가 될 예정입니다. 이 설정은 언제든지 취소 할 수 있습니다.\n\n계정은 다음시간 이후에 초기화가 됩니다:\n{when}"; +"lng_signin_reset_in_days" = "{count_days:0 일|# 일|# 일} {count_hours:0 시간|# 시간|# 시간} {count_minutes:0 분|# 분|# 분}"; +"lng_signin_reset_in_hours" = "{count_hours:0 시간|# 시간|# 시간} {count_minutes:0 분|# 분|# 분}"; +"lng_signin_reset_in_minutes" = "{count_minutes:0 분|# 분|# 분}"; +"lng_signin_reset_cancelled" = "현재 사용중인 사용자가 요청하신 계정 초기화를 취소 하였습니다.\n7일 이후에 다시 시도해주세요."; "lng_signup_title" = "개인정보 및 사진"; "lng_signup_desc" = "이름을 입력해주시고,\n사진을 업로드해주세요."; @@ -442,8 +447,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_profile_delete_and_exit" = "나가기"; "lng_profile_kick" = "삭제"; "lng_profile_admin" = "관리자"; -"lng_profile_sure_kick" = "{user}를 추방하시겠습니까?"; -"lng_profile_sure_kick_channel" = "{user}를 추방하시겠습니까?"; +"lng_profile_sure_kick" = "{user}를 내보내시겠습니까?"; +"lng_profile_sure_kick_channel" = "{user}를 내보내시겠습니까?"; "lng_profile_sure_kick_admin" = "{user}를 관리자에서 제외 하시겠습니까?"; "lng_profile_loading" = "로드중.."; "lng_profile_shared_media" = "공유된 미디어"; @@ -544,7 +549,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_you_joined" = "채널에 입장하였습니다."; "lng_action_add_you_group" = "{from}님께서 그룹에 초대해주셨습니다."; "lng_action_you_joined_group" = "그룹방에 참여하였습니다."; -"lng_action_kick_user" = "{from} 님께서 {user} 님을 추방하셨습니다."; +"lng_action_kick_user" = "{from} 님께서 {user} 님을 내보내셨습니다."; "lng_action_user_left" = "{from} 님이 그룹을 나가셨습니다."; "lng_action_user_joined" = "{from} 님이 그룹에 들어오셨습니다."; "lng_action_user_joined_by_link" = "초대링크를 타고 {from} 님이 그룹에 참여하였습니다."; @@ -602,6 +607,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_group_invite_want_join_channel" = "«{title}» 채널에 참여하시겠습니까?"; "lng_group_invite_join" = "참여"; +"lng_group_invite_members" = "{count:_not_used_|# 회원|# 회원}, 참여자 현황:"; + "lng_group_invite_link" = "초대링크: "; "lng_group_invite_create" = "초대링크 생성"; "lng_group_invite_about" = "이 링크를 통하여,\n그룹방에 초대가 가능합니다."; @@ -664,6 +671,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_emoji_category6" = "물건"; "lng_emoji_category7" = "심볼 및 국기"; +"lng_recent_stickers" = "자주 사용"; "lng_switch_stickers" = "스티커"; "lng_switch_stickers_gifs" = "GIF & 스티커"; "lng_switch_emoji" = "이모티콘"; @@ -680,11 +688,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_stickers_add_pack" = "스티커 추가"; "lng_stickers_share_pack" = "스티커 공유"; "lng_stickers_not_found" = "스티커 팩을 찾을 수 없습니다."; +"lng_stickers_packs_archived" = "활성화된 스티커를 사용할 수 있는 공간이 필요하여 미사용 스티커중 일부는 보관되어집니다."; +"lng_stickers_archived" = "보관된 스티커"; "lng_stickers_copied" = "클립보드에 스티커 팩 링크가 복사 되었습니다."; "lng_stickers_default_set" = "Great Minds"; "lng_stickers_you_have" = "스티커팩 관리 및 변경"; "lng_stickers_packs" = "스티커팩"; "lng_stickers_reorder" = "클릭과 드래그를 통하여 스태커 팩을 변경하세요"; +"lng_stickers_featured" = "인기 스티커"; +"lng_stickers_clear_recent" = "초기화"; +"lng_stickers_clear_recent_sure" = "자주 사용하는 스티커 리스트를 초기화 하겠습니까?"; "lng_stickers_remove" = "삭제"; "lng_stickers_return" = "실행취소"; "lng_stickers_restore" = "복구"; @@ -921,12 +934,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}"; "lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상"; -"lng_new_version_text" = "— 해상도 변경에 따라 사진 뷰어가 정상적으로 표시되도록 수정\n— 드래그앤드롭으로 사진 전송 수정\n— 디자인 및 버그 수정"; +"lng_new_version_text" = "— 인기스티커. 설정내 새로운 탭으로 인기있는 스티커를 확인하고 설치\n— 보관스티커. 스티커 개수가 200개 이상일 경우 미사용 스티커는 보관으로 자동이관\n— 그룹방 미리보기. 초대링크로 입장하기전에 미리보기 - 그룹방 참여인원 확인가능\n— 새로운 내부 비디오 플레이어\n— 대화 디자인 향상"; "lng_menu_insert_unicode" = "유니코드 문자를 입력하세요."; "lng_full_name" = "{last_name} {first_name}"; +"lng_confirm_phone_link_invalid" = "링크가 깨졌거나 폐기되었습니다."; +"lng_confirm_phone_title" = "계정 초기화 취소"; +"lng_confirm_phone_about" = "{phone} 번호에 접근이 가능한 누군가가 해당 계정 및 2단계 비밀번호 초기화를 요청하였습니다.\n\n만약 본인이 아니실 경우 방금 보내드린 코드를 본인 번호에 SMS로 전송해주세요."; +"lng_confirm_phone_success" = "성공!\n\n{phone} 계정에 대한 삭제 프로세스가 취소 되었습니다. 이창을 당으셔도 됩니다."; +"lng_confirm_phone_send" = "보내기"; +"lng_confirm_phone_enter_code" = "코드를 입력해주세요"; + // Not used "lng_topbar_info" = "정보"; diff --git a/Telegram/Resources/langs/lang_nl.strings b/Telegram/Resources/langs/lang_nl.strings index a3ccbc221..1f0de9a1b 100644 --- a/Telegram/Resources/langs/lang_nl.strings +++ b/Telegram/Resources/langs/lang_nl.strings @@ -123,11 +123,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_server_error" = "Interne serverfout."; "lng_flood_error" = "Teveel pogingen. Probeer het later opnieuw."; "lng_gif_error" = "Er is iets een fout opgetreden bij het lezen van de GIF :("; -"lng_edit_error" = "Je mag dit bericht niet bewerken"; +"lng_edit_error" = "Je mag dit bericht niet wijzigen"; "lng_join_channel_error" = "Je bent lid van teveel kanalen of supergroepen, verlaat er wat om hier lid te worden."; "lng_edit_deleted" = "Bericht is gewist"; "lng_edit_too_long" = "Je bericht is te lang"; -"lng_edit_message" = "Bericht bewerken"; +"lng_edit_message" = "Bericht wijzigen"; "lng_edit_message_text" = "Nieuw bericht..."; "lng_deleted" = "Onbekend"; "lng_deleted_message" = "Verwijderd bericht"; @@ -190,6 +190,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_reset_account" = "Account resetten"; "lng_signin_sure_reset" = "Let op:\n\nAl je chats, berichten en alle andere data gaan verloren als je verder gaat!\n\nEcht je account resetten?"; "lng_signin_reset" = "Reset"; +"lng_signin_reset_wait" = "Account {phone_number} is actief en beveiligd met een wachtwoord, het verwijderen stellen we daarom 1 week uit.\nJe kunt dit proces ieder moment annuleren.\n\nJe account kan gereset worden over:\n{when}"; +"lng_signin_reset_in_days" = "{count_days:0 dagen|# dag|# dagen} {count_hours:0 uur|# uur|# uur} {count_minutes:0 minuten|# minuut|# minuten}"; +"lng_signin_reset_in_hours" = "{count_hours:0 uur|# uur|# uur} {count_minutes:0 minuten|# minuut|# minuten}"; +"lng_signin_reset_in_minutes" = "{count_minutes:0 minuten|# minuut|# minuten}"; +"lng_signin_reset_cancelled" = "De actieve gebruiker heeft de recente poging om dit account te resetten geannuleerd. Probeer het over 7 dagen nog eens."; "lng_signup_title" = "Informatie en foto"; "lng_signup_desc" = "Voer je naam en\nupload een foto."; @@ -602,6 +607,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_group_invite_want_join_channel" = "Wil je lid worden van het kanaal \"{title}\"?"; "lng_group_invite_join" = "Lid worden"; +"lng_group_invite_members" = "{count:_not_used_|# lid|# leden}, waaronder:"; + "lng_group_invite_link" = "Uitnodigingslink:"; "lng_group_invite_create" = "Uitnodigingslink maken"; "lng_group_invite_about" = "Gebruikers kunnen lid worden\nvan je groep via deze link."; @@ -618,9 +625,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_forwarded_channel_via" = "Doorgestuurd van {channel} via {inline_bot}"; "lng_forwarded_signed" = "{channel} ({user})"; "lng_in_reply_to" = "Antwoord op"; -"lng_edited" = "bewerkt"; -"lng_edited_date" = "Bewerkt: {date}"; -"lng_cancel_edit_post_sure" = "Bewerken annuleren?"; +"lng_edited" = "gewijzigd"; +"lng_edited_date" = "Gewijzigd: {date}"; +"lng_cancel_edit_post_sure" = "Wijzigen annuleren?"; "lng_cancel_edit_post_yes" = "Ja"; "lng_cancel_edit_post_no" = "Nee"; @@ -664,6 +671,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_emoji_category6" = "Objecten"; "lng_emoji_category7" = "Symbolen en vlaggen"; +"lng_recent_stickers" = "Veelgebruikt"; "lng_switch_stickers" = "Stickers"; "lng_switch_stickers_gifs" = "GIF's & stickers"; "lng_switch_emoji" = "Emoji"; @@ -680,11 +688,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_stickers_add_pack" = "Stickers toevoegen"; "lng_stickers_share_pack" = "Stickers delen"; "lng_stickers_not_found" = "Stickerbundel niet gevonden."; +"lng_stickers_packs_archived" = "Een aantal ongebruikte stickers zijn gearchiveerd om ruimte te maken voor je nieuwe stickerbundels"; +"lng_stickers_archived" = "Gearchiveerde stickers"; "lng_stickers_copied" = "Stickerbundel-link gekopieerd naar klembord"; "lng_stickers_default_set" = "Grote geesten"; "lng_stickers_you_have" = "Beheer en sorteer stickerbundels"; "lng_stickers_packs" = "Stickerbundels"; "lng_stickers_reorder" = "Klik en sleep om stickerbundels te herschikken"; +"lng_stickers_featured" = "Populaire stickers"; +"lng_stickers_clear_recent" = "Wissen"; +"lng_stickers_clear_recent_sure" = "Lijst met veelgebruikte stickers echt wissen?"; "lng_stickers_remove" = "Verwijder"; "lng_stickers_return" = "Ongedaan maken"; "lng_stickers_restore" = "Herstellen"; @@ -813,7 +826,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_context_save_gif" = "GIF opslaan"; "lng_context_to_msg" = "Naar bericht gaan"; "lng_context_reply_msg" = "Antwoord"; -"lng_context_edit_msg" = "Bewerken"; +"lng_context_edit_msg" = "Wijzig"; "lng_context_forward_msg" = "Bericht doorsturen"; "lng_context_delete_msg" = "Bericht verwijderen"; "lng_context_select_msg" = "Bericht kiezen"; @@ -851,12 +864,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_contact_phone" = "Telefoonnummer"; "lng_enter_contact_data" = "Nieuw contact"; -"lng_edit_group_title" = "Groepsnaam bewerken"; -"lng_edit_contact_title" = "Naam bewerken"; +"lng_edit_group_title" = "Groepsnaam wijzigen"; +"lng_edit_contact_title" = "Naam wijzigen"; "lng_edit_channel_title" = "Kanaal wijzigen"; "lng_edit_sign_messages" = "Ondertekenen"; -"lng_edit_group" = "Groep bewerken"; -"lng_edit_self_title" = "Je naam bewerken"; +"lng_edit_group" = "Groep wijzigen"; +"lng_edit_self_title" = "Je naam wijzigen"; "lng_confirm_contact_data" = "Nieuw contact"; "lng_add_contact" = "Opslaan"; "lng_add_contact_button" = "Nieuw contact"; @@ -921,12 +934,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}"; "lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen"; -"lng_new_version_text" = "— Probleem met foto-weergave opgelost\n— Probleem met doorsturen via slepen opgelost\n— Diverse designverbeteringen en andere opgeloste problemen"; +"lng_new_version_text" = "— Populaire stickers. Zoek je nieuwe stickerbundels om te installeren? Populaire stickerbundels zijn nu te vinden onder instellingen.\n— Gearchiveerde stickers. Ongebruikte stickers archiveren we automatisch als je over de limiet van 200 stickerbundels gaat.\n— Voorvertoningen van groepen. Bekijk een groep voordat je besluit lid te worden.\n— Nieuwe ingebouwde videospeler.\n— Designverbeteringen voor de chatinterface."; "lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen"; "lng_full_name" = "{first_name} {last_name}"; +"lng_confirm_phone_link_invalid" = "Deze link is defect of verlopen."; +"lng_confirm_phone_title" = "Account reset annuleren"; +"lng_confirm_phone_about" = "Iemand met toegang tot nummer {phone} heeft geprobeerd om je Telegram account te verwijderen en je twee-staps-verificatie wachtwoord te resetten.\n\nAls jij dit niet was, geef dan de code in die we zojuist per SMS hebben gestuurd."; +"lng_confirm_phone_success" = "De verwijdering van account: {phone} is geannuleerd.\nJe kunt dit venster nu sluiten."; +"lng_confirm_phone_send" = "Stuur"; +"lng_confirm_phone_enter_code" = "Geef de code in."; + // Not used "lng_topbar_info" = "Info"; diff --git a/Telegram/Resources/langs/lang_pt_BR.strings b/Telegram/Resources/langs/lang_pt_BR.strings index 26a4c1491..0be537892 100644 --- a/Telegram/Resources/langs/lang_pt_BR.strings +++ b/Telegram/Resources/langs/lang_pt_BR.strings @@ -178,7 +178,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_password" = "Sua senha"; "lng_signin_code" = "Código do e-mail"; "lng_signin_recover" = "Esqueceu sua senha?"; -"lng_signin_recover_title" = "Resetar senha"; +"lng_signin_recover_title" = "Redefinir senha"; "lng_signin_hint" = "Dica: {password_hint}"; "lng_signin_recover_hint" = "Código enviado para {recover_email}"; "lng_signin_bad_password" = "Você colocou uma senha errada."; @@ -190,6 +190,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_signin_reset_account" = "Apagar sua conta"; "lng_signin_sure_reset" = "Atenção!\n\nVocê perderá todos seus chats e mensagens, juntamente com quaisquer mídias e arquivos!\n\nVocê deseja apagar sua conta?"; "lng_signin_reset" = "Apagar"; +"lng_signin_reset_wait" = "Uma vez que a conta {phone_number} está ativa e protegida por senha, nós iremos desativá-la em 1 semana, por questões de segurança. Você pode cancelar esse processo a qualquer momento.\n\nVocê poderá restaurar sua conta em:\n{when}"; +"lng_signin_reset_in_days" = "{count_days:0 dia|# dia|# dias} {count_hours:0 hora|# hora|# horas} {count_minutes:0 minuto|# minuto|# minutos}"; +"lng_signin_reset_in_hours" = "{count_hours:0 hora|# hora|# horas} {count_minutes:0 minuto|# minuto|# minutos}"; +"lng_signin_reset_in_minutes" = "{count_minutes:0 minuto|# minuto|# minutos}"; +"lng_signin_reset_cancelled" = "Suas tentativas recentes de restaurar essa conta foram canceladas pelo usuário ativo. Tente novamente em 7 dias."; "lng_signup_title" = "Informação e foto"; "lng_signup_desc" = "Por favor, insira nome e\ncarregue uma foto."; @@ -214,7 +219,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_settings_uploading_photo" = "Carregando foto..."; "lng_username_title" = "Nome de usuário"; -"lng_username_about" = "Você pode escolher um nome de usuário no Telegram.\nAssim, outras pessoas poderão te encontrar\npelo nome de usuário e entrar em contato\nsem precisar saber seu telefone.\n\nVocê pode usar a-z, 0-9 e underline.\nO tamanho mínimo é 5 caracteres."; +"lng_username_about" = "Você pode escolher um nome de usuário.\nAssim, outras pessoas poderão encontrar\nvocê pelo nome de usuário e entrar em\ncontato sem precisar saber seu telefone.\n\nVocê pode usar a-z, 0-9 e underline.\nO tamanho mínimo é de 5 caracteres."; "lng_username_choose" = "Escolha seu nome de usuário"; "lng_username_invalid" = "Nome de usuário inválido."; "lng_username_occupied" = "Nome de usuário ocupado."; @@ -602,6 +607,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_group_invite_want_join_channel" = "Você deseja entrar no canal «{title}»?"; "lng_group_invite_join" = "Entrar"; +"lng_group_invite_members" = "{count:_not_used_|# membro|# membros}, entre eles:"; + "lng_group_invite_link" = "Link de convite:"; "lng_group_invite_create" = "Criar um link de convite"; "lng_group_invite_about" = "Usuários do Telegram poderão entrar\nem seu grupo clicando no link."; @@ -655,7 +662,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_media_auto_groups" = "Grupos e canais"; "lng_media_auto_play" = "Reproduzir automaticamente"; -"lng_emoji_category0" = "Frequentemente usado"; +"lng_emoji_category0" = "Usados frequentemente"; "lng_emoji_category1" = "Pessoas"; "lng_emoji_category2" = "Natureza"; "lng_emoji_category3" = "Comidas e Bebidas"; @@ -664,6 +671,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_emoji_category6" = "Objetos"; "lng_emoji_category7" = "Símbolos e Bandeiras"; +"lng_recent_stickers" = "Usados frequentemente"; "lng_switch_stickers" = "Stickers"; "lng_switch_stickers_gifs" = "GIFs e Stickers"; "lng_switch_emoji" = "Emoji"; @@ -680,11 +688,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_stickers_add_pack" = "Adicionar aos Stickers"; "lng_stickers_share_pack" = "Compartilhar Stickers"; "lng_stickers_not_found" = "Pacote de sticker não encontrado."; +"lng_stickers_packs_archived" = "Alguns de seus stickers não usados foram arquivados para dar espaço aos pacotes que você ativou."; +"lng_stickers_archived" = "Stickers Arquivados"; "lng_stickers_copied" = "Link copiado para a área de transferência."; "lng_stickers_default_set" = "Grandes Mentes"; "lng_stickers_you_have" = "Gerenciar e reordenar os pacotes de sticker"; "lng_stickers_packs" = "Pacotes de Sticker"; "lng_stickers_reorder" = "Clique e arraste para reordenar os pacotes"; +"lng_stickers_featured" = "Stickers Populares"; +"lng_stickers_clear_recent" = "Limpar"; +"lng_stickers_clear_recent_sure" = "Você tem certeza que deseja limpar seu histórico de stickers frequentes?"; "lng_stickers_remove" = "Remover"; "lng_stickers_return" = "Desfazer"; "lng_stickers_restore" = "Restaurar"; @@ -921,12 +934,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}"; "lng_new_version_minor" = "— Resolução de bugs e outras melhorias menores"; -"lng_new_version_text" = "— O visualizador de fotos agora maneja corretamente a mudança de resolução da tela\n— O bug ao encaminhar fotos arrastando e soltando foi resolvido. \n— Várias melhorias de design e outras resoluções de bugs"; +"lng_new_version_text" = "— Stickers populares. Veja e instale pacotes de stickers em destaque através da nova aba em Configurações.\n— Stickers arquivados. Stickers sem uso agora são arquivados automaticamente quando você chegar ao limite dos 200.\n— Pré-visualização de grupos. Visualize os grupos antes de entrar através do link de convite - veja quem mais está no grupo antes de entrar.\n— Novo reprodutor de vídeo interno.\n— Design melhorado nas conversas."; "lng_menu_insert_unicode" = "Inserir caractere de controle Unicode"; "lng_full_name" = "{first_name} {last_name}"; +"lng_confirm_phone_link_invalid" = "Esse link está quebrado ou expirado."; +"lng_confirm_phone_title" = "Cancelar exclusão da conta"; +"lng_confirm_phone_about" = "Alguém com acesso ao seu número de telefone {phone} solicitou a exclusão de sua conta do Telegram e redefiniu sua senha de Verificação em Duas Etapas.\n\nSe não foi você, por favor insira o código que te enviamos via SMS."; +"lng_confirm_phone_success" = "Sucesso!\n\nO processo de exclusão foi cancelado em sua conta {phone}. Você pode fechar essa janela agora."; +"lng_confirm_phone_send" = "Enviar"; +"lng_confirm_phone_enter_code" = "Por favor, insira o código."; + // Not used "lng_topbar_info" = "Info"; diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index e4f013b17..1f9b3443e 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,60,0 - PRODUCTVERSION 0,9,60,0 + FILEVERSION 0,10,0,0 + PRODUCTVERSION 0,10,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -51,10 +51,10 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Telegram Messenger LLP" - VALUE "FileVersion", "0.9.60.0" + VALUE "FileVersion", "0.10.0.0" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.9.60.0" + VALUE "ProductVersion", "0.10.0.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 64ed6a32d..5b7b96389 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,60,0 - PRODUCTVERSION 0,9,60,0 + FILEVERSION 0,10,0,0 + PRODUCTVERSION 0,10,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,10 +43,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram Messenger LLP" VALUE "FileDescription", "Telegram Updater" - VALUE "FileVersion", "0.9.60.0" + VALUE "FileVersion", "0.10.0.0" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.9.60.0" + VALUE "ProductVersion", "0.10.0.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 08c4da448..5f5086f4f 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -923,12 +923,12 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) _stickerSetRequests.remove(setId); if (result.type() != mtpc_messages_stickerSet) return; - const auto &d(result.c_messages_stickerSet()); + auto &d(result.c_messages_stickerSet()); if (d.vset.type() != mtpc_stickerSet) return; - const auto &s(d.vset.c_stickerSet()); + auto &s(d.vset.c_stickerSet()); - Stickers::Sets &sets(Global::RefStickerSets()); + auto &sets = Global::RefStickerSets(); auto it = sets.find(setId); if (it == sets.cend()) return; @@ -936,7 +936,9 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) it->hash = s.vhash.v; it->shortName = qs(s.vshort_name); it->title = stickerSetTitle(s); - it->flags = s.vflags.v; + auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special); + it->flags = s.vflags.v | clientFlags; + it->flags &= ~MTPDstickerSet_ClientFlag::f_not_loaded; const auto &d_docs(d.vdocuments.c_vector().v); auto custom = sets.find(Stickers::CustomSetId); @@ -1002,7 +1004,14 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) Local::writeUserSettings(); } - Local::writeStickers(); + if (it->flags & MTPDstickerSet::Flag::f_installed) { + if (!(it->flags & MTPDstickerSet::Flag::f_archived)) { + Local::writeInstalledStickers(); + } + } + if (it->flags & MTPDstickerSet_ClientFlag::f_featured) { + Local::writeFeaturedStickers(); + } if (App::main()) emit App::main()->stickersUpdated(); } diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index f3d177592..54cf58492 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -26,10 +26,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #endif #include "styles/style_overview.h" +#include "styles/style_mediaview.h" #include "lang.h" #include "data/data_abstract_structure.h" #include "history/history_service_layout.h" #include "media/media_audio.h" +#include "inline_bots/inline_bot_layout_item.h" #include "application.h" #include "fileuploader.h" #include "mainwidget.h" @@ -382,397 +384,413 @@ namespace { return (online > now); } - UserData *feedUsers(const MTPVector &users) { - UserData *result = nullptr; - for_const (auto &user, users.c_vector().v) { - UserData *data = nullptr; - bool wasContact = false, minimal = false; - const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty(); + UserData *feedUser(const MTPUser &user) { + UserData *data = nullptr; + bool wasContact = false, minimal = false; + const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty(); - Notify::PeerUpdate update; - using UpdateFlag = Notify::PeerUpdate::Flag; + Notify::PeerUpdate update; + using UpdateFlag = Notify::PeerUpdate::Flag; - switch (user.type()) { - case mtpc_userEmpty: { - const auto &d(user.c_userEmpty()); + switch (user.type()) { + case mtpc_userEmpty: { + auto &d(user.c_userEmpty()); - PeerId peer(peerFromUser(d.vid.v)); - data = App::user(peer); - auto canShareThisContact = data->canShareThisContactFast(); - wasContact = data->isContact(); + PeerId peer(peerFromUser(d.vid.v)); + data = App::user(peer); + auto canShareThisContact = data->canShareThisContactFast(); + wasContact = data->isContact(); - data->input = MTP_inputPeerUser(d.vid, MTP_long(0)); - data->inputUser = MTP_inputUser(d.vid, MTP_long(0)); + data->input = MTP_inputPeerUser(d.vid, MTP_long(0)); + data->inputUser = MTP_inputUser(d.vid, MTP_long(0)); + data->setName(lang(lng_deleted), QString(), QString(), QString()); + data->setPhoto(MTP_userProfilePhotoEmpty()); + data->access = UserNoAccess; + data->flags = 0; + data->setBotInfoVersion(-1); + status = &emptyStatus; + data->contact = -1; + + if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact; + if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact; + } break; + case mtpc_user: { + auto &d(user.c_user()); + minimal = d.is_min(); + + PeerId peer(peerFromUser(d.vid.v)); + data = App::user(peer); + auto canShareThisContact = data->canShareThisContactFast(); + wasContact = data->isContact(); + if (!minimal) { + data->flags = d.vflags.v; + if (d.is_self()) { + data->input = MTP_inputPeerSelf(); + data->inputUser = MTP_inputUserSelf(); + } else if (!d.has_access_hash()) { + data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access)); + data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access)); + } else { + data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash); + data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash); + } + if (d.is_restricted()) { + data->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason))); + } else { + data->setRestrictionReason(QString()); + } + } + if (d.is_deleted()) { + if (!data->phone().isEmpty()) { + data->setPhone(QString()); + update.flags |= UpdateFlag::UserPhoneChanged; + } data->setName(lang(lng_deleted), QString(), QString(), QString()); data->setPhoto(MTP_userProfilePhotoEmpty()); data->access = UserNoAccess; - data->flags = 0; - data->setBotInfoVersion(-1); status = &emptyStatus; - data->contact = -1; + } else { + // apply first_name and last_name from minimal user only if we don't have + // local values for first name and last name already, otherwise skip + bool noLocalName = data->firstName.isEmpty() && data->lastName.isEmpty(); + QString fname = (!minimal || noLocalName) ? (d.has_first_name() ? textOneLine(qs(d.vfirst_name)) : QString()) : data->firstName; + QString lname = (!minimal || noLocalName) ? (d.has_last_name() ? textOneLine(qs(d.vlast_name)) : QString()) : data->lastName; - if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact; - if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact; - } break; - case mtpc_user: { - const auto &d(user.c_user()); - minimal = d.is_min(); + QString phone = minimal ? data->phone() : (d.has_phone() ? qs(d.vphone) : QString()); + QString uname = minimal ? data->username : (d.has_username() ? textOneLine(qs(d.vusername)) : QString()); - PeerId peer(peerFromUser(d.vid.v)); - data = App::user(peer); - auto canShareThisContact = data->canShareThisContactFast(); - wasContact = data->isContact(); - if (!minimal) { - data->flags = d.vflags.v; - if (d.is_self()) { - data->input = MTP_inputPeerSelf(); - data->inputUser = MTP_inputUserSelf(); - } else if (!d.has_access_hash()) { - data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access)); - data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access)); - } else { - data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash); - data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash); - } - if (d.is_restricted()) { - data->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason))); - } else { - data->setRestrictionReason(QString()); - } + bool phoneChanged = (data->phone() != phone); + if (phoneChanged) { + data->setPhone(phone); + update.flags |= UpdateFlag::UserPhoneChanged; } - if (d.is_deleted()) { - if (!data->phone().isEmpty()) { - data->setPhone(QString()); - update.flags |= UpdateFlag::UserPhoneChanged; - } - data->setName(lang(lng_deleted), QString(), QString(), QString()); - data->setPhoto(MTP_userProfilePhotoEmpty()); - data->access = UserNoAccess; - status = &emptyStatus; + bool nameChanged = (data->firstName != fname) || (data->lastName != lname); + + bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact(); + bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact)); + if (minimal) { + showPhoneChanged = false; + showPhone = !isServiceUser(data->id) && (data->id != peerFromUser(MTP::authedId())) && !data->contact; + } + + // see also Local::readPeer + + QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone; + + if (!minimal && d.is_self() && uname != data->username) { + SignalHandlers::setCrashAnnotation("Username", uname); + } + data->setName(fname, lname, pname, uname); + if (d.has_photo()) { + data->setPhoto(d.vphoto); } else { - // apply first_name and last_name from minimal user only if we don't have - // local values for first name and last name already, otherwise skip - bool noLocalName = data->firstName.isEmpty() && data->lastName.isEmpty(); - QString fname = (!minimal || noLocalName) ? (d.has_first_name() ? textOneLine(qs(d.vfirst_name)) : QString()) : data->firstName; - QString lname = (!minimal || noLocalName) ? (d.has_last_name() ? textOneLine(qs(d.vlast_name)) : QString()) : data->lastName; - - QString phone = minimal ? data->phone() : (d.has_phone() ? qs(d.vphone) : QString()); - QString uname = minimal ? data->username : (d.has_username() ? textOneLine(qs(d.vusername)) : QString()); - - bool phoneChanged = (data->phone() != phone); - if (phoneChanged) { - data->setPhone(phone); - update.flags |= UpdateFlag::UserPhoneChanged; - } - bool nameChanged = (data->firstName != fname) || (data->lastName != lname); - - bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact(); - bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact)); - if (minimal) { - showPhoneChanged = false; - showPhone = !isServiceUser(data->id) && (data->id != peerFromUser(MTP::authedId())) && !data->contact; - } - - // see also Local::readPeer - - QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone; - - if (!minimal && d.is_self() && uname != data->username) { - SignalHandlers::setCrashAnnotation("Username", uname); - } - data->setName(fname, lname, pname, uname); - if (d.has_photo()) { - data->setPhoto(d.vphoto); - } else { - data->setPhoto(MTP_userProfilePhotoEmpty()); - } - if (d.has_access_hash()) data->access = d.vaccess_hash.v; - status = d.has_status() ? &d.vstatus : &emptyStatus; + data->setPhoto(MTP_userProfilePhotoEmpty()); } - if (!minimal) { - if (d.has_bot_info_version()) { - data->setBotInfoVersion(d.vbot_info_version.v); - data->botInfo->readsAllHistory = d.is_bot_chat_history(); - if (data->botInfo->cantJoinGroups != d.is_bot_nochats()) { - data->botInfo->cantJoinGroups = d.is_bot_nochats(); - update.flags |= UpdateFlag::BotCanAddToGroups; - } - data->botInfo->inlinePlaceholder = d.has_bot_inline_placeholder() ? '_' + qs(d.vbot_inline_placeholder) : QString(); - } else { - data->setBotInfoVersion(-1); - } - data->contact = (d.is_contact() || d.is_mutual_contact()) ? 1 : (data->phone().isEmpty() ? -1 : 0); - if (data->contact == 1 && cReportSpamStatuses().value(data->id, dbiprsHidden) != dbiprsHidden) { - cRefReportSpamStatuses().insert(data->id, dbiprsHidden); - Local::writeReportSpamStatuses(); - } - if (d.is_self() && ::self != data) { - ::self = data; - if (App::wnd()) App::wnd()->updateGlobalMenu(); + if (d.has_access_hash()) data->access = d.vaccess_hash.v; + status = d.has_status() ? &d.vstatus : &emptyStatus; + } + if (!minimal) { + if (d.has_bot_info_version()) { + data->setBotInfoVersion(d.vbot_info_version.v); + data->botInfo->readsAllHistory = d.is_bot_chat_history(); + if (data->botInfo->cantJoinGroups != d.is_bot_nochats()) { + data->botInfo->cantJoinGroups = d.is_bot_nochats(); + update.flags |= UpdateFlag::BotCanAddToGroups; } + data->botInfo->inlinePlaceholder = d.has_bot_inline_placeholder() ? '_' + qs(d.vbot_inline_placeholder) : QString(); + } else { + data->setBotInfoVersion(-1); } - - if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact; - if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact; - } break; - } - - if (!data) continue; - - if (minimal) { - if (data->loadedStatus == PeerData::NotLoaded) { - data->loadedStatus = PeerData::MinimalLoaded; + data->contact = (d.is_contact() || d.is_mutual_contact()) ? 1 : (data->phone().isEmpty() ? -1 : 0); + if (data->contact == 1 && cReportSpamStatuses().value(data->id, dbiprsHidden) != dbiprsHidden) { + cRefReportSpamStatuses().insert(data->id, dbiprsHidden); + Local::writeReportSpamStatuses(); } - } else if (data->loadedStatus != PeerData::FullLoaded) { - data->loadedStatus = PeerData::FullLoaded; - } - - auto oldOnlineTill = data->onlineTill; - if (status && !minimal) switch (status->type()) { - case mtpc_userStatusEmpty: data->onlineTill = 0; break; - case mtpc_userStatusRecently: - if (data->onlineTill > -10) { // don't modify pseudo-online - data->onlineTill = -2; - } - break; - case mtpc_userStatusLastWeek: data->onlineTill = -3; break; - case mtpc_userStatusLastMonth: data->onlineTill = -4; break; - case mtpc_userStatusOffline: data->onlineTill = status->c_userStatusOffline().vwas_online.v; break; - case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break; - } - if (oldOnlineTill != data->onlineTill) { - update.flags |= UpdateFlag::UserOnlineChanged; - } - - if (data->contact < 0 && !data->phone().isEmpty() && peerToUser(data->id) != MTP::authedId()) { - data->contact = 0; - } - if (App::main()) { - if ((data->contact > 0 && !wasContact) || (wasContact && data->contact < 1)) { - Notify::userIsContactChanged(data); - } - - markPeerUpdated(data); - if (update.flags) { - update.peer = data; - Notify::peerUpdatedDelayed(update); + if (d.is_self() && ::self != data) { + ::self = data; + if (App::wnd()) App::wnd()->updateGlobalMenu(); } } - result = data; + + if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact; + if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact; + } break; + } + + if (!data) { + return nullptr; + } + + if (minimal) { + if (data->loadedStatus == PeerData::NotLoaded) { + data->loadedStatus = PeerData::MinimalLoaded; + } + } else if (data->loadedStatus != PeerData::FullLoaded) { + data->loadedStatus = PeerData::FullLoaded; + } + + auto oldOnlineTill = data->onlineTill; + if (status && !minimal) switch (status->type()) { + case mtpc_userStatusEmpty: data->onlineTill = 0; break; + case mtpc_userStatusRecently: + if (data->onlineTill > -10) { // don't modify pseudo-online + data->onlineTill = -2; + } + break; + case mtpc_userStatusLastWeek: data->onlineTill = -3; break; + case mtpc_userStatusLastMonth: data->onlineTill = -4; break; + case mtpc_userStatusOffline: data->onlineTill = status->c_userStatusOffline().vwas_online.v; break; + case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break; + } + if (oldOnlineTill != data->onlineTill) { + update.flags |= UpdateFlag::UserOnlineChanged; + } + + if (data->contact < 0 && !data->phone().isEmpty() && peerToUser(data->id) != MTP::authedId()) { + data->contact = 0; + } + if (App::main()) { + if ((data->contact > 0 && !wasContact) || (wasContact && data->contact < 1)) { + Notify::userIsContactChanged(data); + } + + markPeerUpdated(data); + if (update.flags) { + update.peer = data; + Notify::peerUpdatedDelayed(update); + } + } + return data; + } + + UserData *feedUsers(const MTPVector &users) { + UserData *result = nullptr; + for_const (auto &user, users.c_vector().v) { + if (auto feededUser = feedUser(user)) { + result = feededUser; + } } return result; } + PeerData *feedChat(const MTPChat &chat) { + PeerData *data = nullptr; + bool minimal = false; + + Notify::PeerUpdate update; + using UpdateFlag = Notify::PeerUpdate::Flag; + + switch (chat.type()) { + case mtpc_chat: { + auto &d(chat.c_chat()); + + data = App::chat(peerFromChat(d.vid.v)); + auto cdata = data->asChat(); + auto canEdit = cdata->canEdit(); + + if (cdata->version < d.vversion.v) { + cdata->version = d.vversion.v; + cdata->invalidateParticipants(); + } + + data->input = MTP_inputPeerChat(d.vid); + cdata->setName(qs(d.vtitle)); + cdata->setPhoto(d.vphoto); + cdata->date = d.vdate.v; + + if (d.has_migrated_to() && d.vmigrated_to.type() == mtpc_inputChannel) { + const auto &c(d.vmigrated_to.c_inputChannel()); + ChannelData *channel = App::channel(peerFromChannel(c.vchannel_id)); + if (!channel->mgInfo) { + channel->flags |= MTPDchannel::Flag::f_megagroup; + channel->flagsUpdated(); + } + if (!channel->access) { + channel->input = MTP_inputPeerChannel(c.vchannel_id, c.vaccess_hash); + channel->inputChannel = d.vmigrated_to; + channel->access = d.vmigrated_to.c_inputChannel().vaccess_hash.v; + } + bool updatedTo = (cdata->migrateToPtr != channel), updatedFrom = (channel->mgInfo->migrateFromPtr != cdata); + if (updatedTo) { + cdata->migrateToPtr = channel; + } + if (updatedFrom) { + channel->mgInfo->migrateFromPtr = cdata; + if (History *h = App::historyLoaded(cdata->id)) { + if (History *hto = App::historyLoaded(channel->id)) { + if (!h->isEmpty()) { + h->clear(true); + } + if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) { + App::removeDialog(h); + } + } + } + Notify::migrateUpdated(channel); + update.flags |= UpdateFlag::MigrationChanged; + } + if (updatedTo) { + Notify::migrateUpdated(cdata); + update.flags |= UpdateFlag::MigrationChanged; + } + } + + if (!(cdata->flags & MTPDchat::Flag::f_admins_enabled) && (d.vflags.v & MTPDchat::Flag::f_admins_enabled)) { + cdata->invalidateParticipants(); + } + cdata->flags = d.vflags.v; + + cdata->count = d.vparticipants_count.v; + cdata->isForbidden = false; + if (canEdit != cdata->canEdit()) { + update.flags |= UpdateFlag::ChatCanEdit; + } + } break; + case mtpc_chatForbidden: { + auto &d(chat.c_chatForbidden()); + + data = App::chat(peerFromChat(d.vid.v)); + auto cdata = data->asChat(); + auto canEdit = cdata->canEdit(); + + data->input = MTP_inputPeerChat(d.vid); + cdata->setName(qs(d.vtitle)); + cdata->setPhoto(MTP_chatPhotoEmpty()); + cdata->date = 0; + cdata->count = -1; + cdata->invalidateParticipants(); + cdata->flags = 0; + cdata->isForbidden = true; + if (canEdit != cdata->canEdit()) { + update.flags |= UpdateFlag::ChatCanEdit; + } + } break; + case mtpc_channel: { + auto &d(chat.c_channel()); + + auto peerId = peerFromChannel(d.vid.v); + minimal = d.is_min(); + if (minimal) { + data = App::channelLoaded(peerId); + if (!data) { + return nullptr; // minimal is not loaded, need to make getDifference + } + } else { + data = App::channel(peerId); + data->input = MTP_inputPeerChannel(d.vid, d.has_access_hash() ? d.vaccess_hash : MTP_long(0)); + } + + auto cdata = data->asChannel(); + auto wasInChannel = cdata->amIn(); + auto canEditPhoto = cdata->canEditPhoto(); + auto canViewAdmins = cdata->canViewAdmins(); + auto canViewMembers = cdata->canViewMembers(); + auto canAddMembers = cdata->canAddMembers(); + auto wasEditor = cdata->amEditor(); + + if (minimal) { + auto mask = MTPDchannel::Flag::f_broadcast | MTPDchannel::Flag::f_verified | MTPDchannel::Flag::f_megagroup | MTPDchannel::Flag::f_democracy; + cdata->flags = (cdata->flags & ~mask) | (d.vflags.v & mask); + } else { + cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); + cdata->access = d.vaccess_hash.v; + cdata->date = d.vdate.v; + if (cdata->version < d.vversion.v) { + cdata->version = d.vversion.v; + } + if (d.is_restricted()) { + cdata->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason))); + } else { + cdata->setRestrictionReason(QString()); + } + cdata->flags = d.vflags.v; + } + cdata->flagsUpdated(); + + QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString(); + cdata->setName(qs(d.vtitle), uname); + + cdata->isForbidden = false; + cdata->setPhoto(d.vphoto); + + if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn; + if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto; + if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins; + if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers; + if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers; + if (wasEditor != cdata->amEditor()) { + cdata->selfAdminUpdated(); + update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged); + } + } break; + case mtpc_channelForbidden: { + auto &d(chat.c_channelForbidden()); + + auto peerId = peerFromChannel(d.vid.v); + data = App::channel(peerId); + data->input = MTP_inputPeerChannel(d.vid, d.vaccess_hash); + + auto cdata = data->asChannel(); + auto wasInChannel = cdata->amIn(); + auto canEditPhoto = cdata->canEditPhoto(); + auto canViewAdmins = cdata->canViewAdmins(); + auto canViewMembers = cdata->canViewMembers(); + auto canAddMembers = cdata->canAddMembers(); + auto wasEditor = cdata->amEditor(); + + cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); + + auto mask = mtpCastFlags(MTPDchannelForbidden::Flag::f_broadcast | MTPDchannelForbidden::Flag::f_megagroup); + cdata->flags = (cdata->flags & ~mask) | (mtpCastFlags(d.vflags) & mask); + cdata->flagsUpdated(); + + cdata->setName(qs(d.vtitle), QString()); + + cdata->access = d.vaccess_hash.v; + cdata->setPhoto(MTP_chatPhotoEmpty()); + cdata->date = 0; + cdata->setMembersCount(0); + cdata->isForbidden = true; + + if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn; + if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto; + if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins; + if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers; + if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers; + if (wasEditor != cdata->amEditor()) { + cdata->selfAdminUpdated(); + update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged); + } + } break; + } + if (!data) { + return nullptr; + } + + if (minimal) { + if (data->loadedStatus == PeerData::NotLoaded) { + data->loadedStatus = PeerData::MinimalLoaded; + } + } else if (data->loadedStatus != PeerData::FullLoaded) { + data->loadedStatus = PeerData::FullLoaded; + } + if (App::main()) { + markPeerUpdated(data); + if (update.flags) { + update.peer = data; + Notify::peerUpdatedDelayed(update); + } + } + return data; + } + PeerData *feedChats(const MTPVector &chats) { PeerData *result = nullptr; for_const (auto &chat, chats.c_vector().v) { - PeerData *data = nullptr; - bool minimal = false; - - Notify::PeerUpdate update; - using UpdateFlag = Notify::PeerUpdate::Flag; - - switch (chat.type()) { - case mtpc_chat: { - auto &d(chat.c_chat()); - - data = App::chat(peerFromChat(d.vid.v)); - auto cdata = data->asChat(); - auto canEdit = cdata->canEdit(); - - if (cdata->version < d.vversion.v) { - cdata->version = d.vversion.v; - cdata->invalidateParticipants(); - } - - data->input = MTP_inputPeerChat(d.vid); - cdata->setName(qs(d.vtitle)); - cdata->setPhoto(d.vphoto); - cdata->date = d.vdate.v; - - if (d.has_migrated_to() && d.vmigrated_to.type() == mtpc_inputChannel) { - const auto &c(d.vmigrated_to.c_inputChannel()); - ChannelData *channel = App::channel(peerFromChannel(c.vchannel_id)); - if (!channel->mgInfo) { - channel->flags |= MTPDchannel::Flag::f_megagroup; - channel->flagsUpdated(); - } - if (!channel->access) { - channel->input = MTP_inputPeerChannel(c.vchannel_id, c.vaccess_hash); - channel->inputChannel = d.vmigrated_to; - channel->access = d.vmigrated_to.c_inputChannel().vaccess_hash.v; - } - bool updatedTo = (cdata->migrateToPtr != channel), updatedFrom = (channel->mgInfo->migrateFromPtr != cdata); - if (updatedTo) { - cdata->migrateToPtr = channel; - } - if (updatedFrom) { - channel->mgInfo->migrateFromPtr = cdata; - if (History *h = App::historyLoaded(cdata->id)) { - if (History *hto = App::historyLoaded(channel->id)) { - if (!h->isEmpty()) { - h->clear(true); - } - if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) { - App::removeDialog(h); - } - } - } - Notify::migrateUpdated(channel); - update.flags |= UpdateFlag::MigrationChanged; - } - if (updatedTo) { - Notify::migrateUpdated(cdata); - update.flags |= UpdateFlag::MigrationChanged; - } - } - - if (!(cdata->flags & MTPDchat::Flag::f_admins_enabled) && (d.vflags.v & MTPDchat::Flag::f_admins_enabled)) { - cdata->invalidateParticipants(); - } - cdata->flags = d.vflags.v; - - cdata->count = d.vparticipants_count.v; - cdata->isForbidden = false; - if (canEdit != cdata->canEdit()) { - update.flags |= UpdateFlag::ChatCanEdit; - } - } break; - case mtpc_chatForbidden: { - auto &d(chat.c_chatForbidden()); - - data = App::chat(peerFromChat(d.vid.v)); - auto cdata = data->asChat(); - auto canEdit = cdata->canEdit(); - - data->input = MTP_inputPeerChat(d.vid); - cdata->setName(qs(d.vtitle)); - cdata->setPhoto(MTP_chatPhotoEmpty()); - cdata->date = 0; - cdata->count = -1; - cdata->invalidateParticipants(); - cdata->flags = 0; - cdata->isForbidden = true; - if (canEdit != cdata->canEdit()) { - update.flags |= UpdateFlag::ChatCanEdit; - } - } break; - case mtpc_channel: { - auto &d(chat.c_channel()); - - auto peerId = peerFromChannel(d.vid.v); - minimal = d.is_min(); - if (minimal) { - data = App::channelLoaded(peerId); - if (!data) { - continue; // minimal is not loaded, need to make getDifference - } - } else { - data = App::channel(peerId); - data->input = MTP_inputPeerChannel(d.vid, d.has_access_hash() ? d.vaccess_hash : MTP_long(0)); - } - - auto cdata = data->asChannel(); - auto wasInChannel = cdata->amIn(); - auto canEditPhoto = cdata->canEditPhoto(); - auto canViewAdmins = cdata->canViewAdmins(); - auto canViewMembers = cdata->canViewMembers(); - auto canAddMembers = cdata->canAddMembers(); - auto wasEditor = cdata->amEditor(); - - if (minimal) { - auto mask = MTPDchannel::Flag::f_broadcast | MTPDchannel::Flag::f_verified | MTPDchannel::Flag::f_megagroup | MTPDchannel::Flag::f_democracy; - cdata->flags = (cdata->flags & ~mask) | (d.vflags.v & mask); - } else { - cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); - cdata->access = d.vaccess_hash.v; - cdata->date = d.vdate.v; - if (cdata->version < d.vversion.v) { - cdata->version = d.vversion.v; - } - if (d.is_restricted()) { - cdata->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason))); - } else { - cdata->setRestrictionReason(QString()); - } - cdata->flags = d.vflags.v; - } - cdata->flagsUpdated(); - - QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString(); - cdata->setName(qs(d.vtitle), uname); - - cdata->isForbidden = false; - cdata->setPhoto(d.vphoto); - - if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn; - if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto; - if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins; - if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers; - if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers; - if (wasEditor != cdata->amEditor()) { - cdata->selfAdminUpdated(); - update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged); - } - } break; - case mtpc_channelForbidden: { - auto &d(chat.c_channelForbidden()); - - auto peerId = peerFromChannel(d.vid.v); - data = App::channel(peerId); - data->input = MTP_inputPeerChannel(d.vid, d.vaccess_hash); - - auto cdata = data->asChannel(); - auto wasInChannel = cdata->amIn(); - auto canEditPhoto = cdata->canEditPhoto(); - auto canViewAdmins = cdata->canViewAdmins(); - auto canViewMembers = cdata->canViewMembers(); - auto canAddMembers = cdata->canAddMembers(); - auto wasEditor = cdata->amEditor(); - - cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); - - auto mask = mtpCastFlags(MTPDchannelForbidden::Flag::f_broadcast | MTPDchannelForbidden::Flag::f_megagroup); - cdata->flags = (cdata->flags & ~mask) | (mtpCastFlags(d.vflags) & mask); - cdata->flagsUpdated(); - - cdata->setName(qs(d.vtitle), QString()); - - cdata->access = d.vaccess_hash.v; - cdata->setPhoto(MTP_chatPhotoEmpty()); - cdata->date = 0; - cdata->setMembersCount(0); - cdata->isForbidden = true; - - if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn; - if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto; - if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins; - if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers; - if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers; - if (wasEditor != cdata->amEditor()) { - cdata->selfAdminUpdated(); - update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged); - } - } break; + if (auto feededChat = feedChat(chat)) { + result = feededChat; } - if (!data) continue; - - if (minimal) { - if (data->loadedStatus == PeerData::NotLoaded) { - data->loadedStatus = PeerData::MinimalLoaded; - } - } else if (data->loadedStatus != PeerData::FullLoaded) { - data->loadedStatus = PeerData::FullLoaded; - } - if (App::main()) { - markPeerUpdated(data); - if (update.flags) { - update.peer = data; - Notify::peerUpdatedDelayed(update); - } - } - result = data; } return result; } @@ -1452,7 +1470,7 @@ namespace { switch (document.type()) { case mtpc_document: { const auto &d(document.c_document()); - return App::documentSet(d.vid.v, 0, d.vaccess_hash.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v, StorageImageLocation()); + return App::documentSet(d.vid.v, 0, d.vaccess_hash.v, d.vversion.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v, StorageImageLocation()); } break; case mtpc_documentEmpty: return App::document(document.c_documentEmpty().vid.v); } @@ -1465,14 +1483,14 @@ namespace { return feedDocument(document.c_document(), convert); } break; case mtpc_documentEmpty: { - return App::documentSet(document.c_documentEmpty().vid.v, convert, 0, 0, QVector(), QString(), ImagePtr(), 0, 0, StorageImageLocation()); + return App::documentSet(document.c_documentEmpty().vid.v, convert, 0, 0, 0, QVector(), QString(), ImagePtr(), 0, 0, StorageImageLocation()); } break; } return App::document(0); } DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert) { - return App::documentSet(document.vid.v, convert, document.vaccess_hash.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v, App::imageLocation(document.vthumb)); + return App::documentSet(document.vid.v, convert, document.vaccess_hash.v, document.vversion.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v, App::imageLocation(document.vthumb)); } WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) { @@ -1629,11 +1647,13 @@ namespace { return i.value(); } - DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) { + DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) { + bool versionChanged = false; bool sentSticker = false; if (convert) { MediaKey oldKey = convert->mediaKey(); - if (convert->id != document) { + bool idChanged = (convert->id != document); + if (idChanged) { DocumentsData::iterator i = ::documentsData.find(convert->id); if (i != ::documentsData.cend() && i.value() == convert) { ::documentsData.erase(i); @@ -1645,10 +1665,11 @@ namespace { } if (date) { convert->setattributes(attributes); + versionChanged = convert->setRemoteVersion(version); convert->setRemoteLocation(dc, access); convert->date = date; convert->mime = mime; - if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height())) { + if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height() || versionChanged)) { updateImage(convert->thumb, thumb); } convert->size = size; @@ -1658,7 +1679,7 @@ namespace { } MediaKey newKey = convert->mediaKey(); - if (newKey != oldKey) { + if (idChanged) { if (convert->voice()) { Local::copyAudio(oldKey, newKey); } else if (convert->sticker() || convert->isAnimation()) { @@ -1677,7 +1698,7 @@ namespace { if (convert) { result = convert; } else { - result = DocumentData::create(document, dc, access, attributes); + result = DocumentData::create(document, dc, access, version, attributes); result->date = date; result->mime = mime; result->thumb = thumb; @@ -1692,12 +1713,13 @@ namespace { result = i.value(); if (result != convert && date) { result->setattributes(attributes); + versionChanged = result->setRemoteVersion(version); if (!result->isValid()) { result->setRemoteLocation(dc, access); } result->date = date; result->mime = mime; - if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height())) { + if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height() || versionChanged)) { result->thumb = thumb; } result->size = size; @@ -1710,6 +1732,30 @@ namespace { if (sentSticker && App::main()) { App::main()->incrementSticker(result); } + if (versionChanged) { + if (result->sticker() && result->sticker()->set.type() == mtpc_inputStickerSetID) { + auto it = Global::StickerSets().constFind(result->sticker()->set.c_inputStickerSetID().vid.v); + if (it != Global::StickerSets().cend()) { + if (it->id == Stickers::CloudRecentSetId) { + Local::writeRecentStickers(); + } else if (it->flags & MTPDstickerSet::Flag::f_archived) { + Local::writeArchivedStickers(); + } else if (it->flags & MTPDstickerSet::Flag::f_installed) { + Local::writeInstalledStickers(); + } + if (it->flags & MTPDstickerSet_ClientFlag::f_featured) { + Local::writeFeaturedStickers(); + } + } + } + auto &items = App::documentItems(); + auto i = items.constFind(result); + if (i != items.cend()) { + for (auto j = i->cbegin(), e = i->cend(); j != e; ++j) { + j.key()->setPendingInitDimensions(); + } + } + } return result; } @@ -1977,6 +2023,11 @@ namespace { Global::SetStickerSets(Stickers::Sets()); Global::SetStickerSetsOrder(Stickers::Order()); Global::SetLastStickersUpdate(0); + Global::SetLastRecentStickersUpdate(0); + Global::SetFeaturedStickerSetsOrder(Stickers::Order()); + Global::SetFeaturedStickerSetsUnreadCount(0); + Global::SetLastFeaturedStickersUpdate(0); + Global::SetArchivedStickerSetsOrder(Stickers::Order()); cSetSavedGifs(SavedGifs()); cSetLastSavedGifsUpdate(0); cSetReportSpamStatuses(ReportSpamStatuses()); @@ -2119,7 +2170,7 @@ namespace { prepareCorners(InShadowCorners, st::msgRadius, st::msgInShadow); prepareCorners(InSelectedShadowCorners, st::msgRadius, st::msgInShadowSelected); prepareCorners(ForwardCorners, st::msgRadius, st::forwardBg); - prepareCorners(MediaviewSaveCorners, st::msgRadius, st::medviewSaveMsg); + prepareCorners(MediaviewSaveCorners, st::mediaviewControllerRadius, st::medviewSaveMsg); prepareCorners(EmojiHoverCorners, st::buttonRadius, st::emojiPanHover); prepareCorners(StickerHoverCorners, st::buttonRadius, st::emojiPanHover); prepareCorners(BotKeyboardCorners, st::buttonRadius, st::botKbBg); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 8468b9456..6dc19af13 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -65,7 +65,9 @@ namespace App { bool onlineColorUse(UserData *user, TimeId now); bool onlineColorUse(TimeId online, TimeId now); + UserData *feedUser(const MTPUser &user); UserData *feedUsers(const MTPVector &users); // returns last user + PeerData *feedChat(const MTPChat &chat); PeerData *feedChats(const MTPVector &chats); // returns last chat void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true); @@ -149,7 +151,7 @@ namespace App { PhotoData *photo(const PhotoId &photo); PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full); DocumentData *document(const DocumentId &document); - DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation); + DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation); WebPageData *webPage(const WebPageId &webPage); WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill); LocationData *location(const LocationCoords &coords); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index d690d196f..c2eeae415 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -264,7 +264,7 @@ void Application::readClients() { } } else if (cmd.startsWith(qsl("OPEN:"))) { if (cStartUrl().isEmpty()) { - startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)); + startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)).mid(0, 8192); } } else { LOG(("Application Error: unknown command %1 passed in local socket").arg(QString(cmd.constData(), cmd.length()))); @@ -1053,7 +1053,7 @@ void AppClass::checkMapVersion() { QString versionFeatures; if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 9058) { versionFeatures = QString::fromUtf8("\xe2\x80\x94 Alpha version of an embedded video player"); - } else if (Local::oldMapVersion() < 9056) { + } else if (Local::oldMapVersion() < 10000) { versionFeatures = langNewVersionText(); } else { versionFeatures = lang(lng_new_version_minor).trimmed(); diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style new file mode 100644 index 000000000..ba77c0abe --- /dev/null +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -0,0 +1,75 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +using "basic.style"; + +confirmInviteTitle: flatLabel(labelDefFlat) { + font: font(16px semibold); + align: align(center); + width: 320px; + maxHeight: 24px; + textFg: #333333; +} +confirmInviteStatus: flatLabel(labelDefFlat) { + font: font(boxFontSize); + align: align(center); + width: 320px; + maxHeight: 20px; + textFg: windowSubTextFg; +} +confirmInviteTitleTop: 106px; +confirmInvitePhotoSize: 76px; +confirmInvitePhotoTop: 20px; +confirmInviteStatusTop: 136px; +confirmInviteUserHeight: 80px; +confirmInviteUserPhotoSize: 56px; +confirmInviteUserPhotoTop: 166px; +confirmInviteUserName: flatLabel(labelDefFlat) { + font: normalFont; + align: align(center); + width: 66px; + maxHeight: 20px; +} +confirmInviteUserNameTop: 227px; + +stickersAddIcon: icon { + { "stickers_add", #ffffff }, +}; +stickersAddSize: size(30px, 24px); + +stickersFeaturedHeight: 32px; +stickersFeaturedFont: contactsNameFont; +stickersFeaturedPosition: point(16px, 6px); +stickersFeaturedBadgeFont: semiboldFont; +stickersFeaturedBadgeSize: 21px; +stickersFeaturedPen: contactsNewItemFg; +stickersFeaturedUnreadBg: msgFileInBg; +stickersFeaturedUnreadSize: 5px; +stickersFeaturedUnreadSkip: 5px; +stickersFeaturedUnreadTop: 7px; +stickersFeaturedInstalled: icon { + { "mediaview_save_check", #40ace3 } +}; + +confirmPhoneAboutLabel: flatLabel(labelDefFlat) { + width: 282px; +} +confirmPhoneCodeField: InputField(defaultInputField) { +} diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index 83ce30643..39c978ed3 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "apiwrap.h" #include "application.h" #include "core/click_handler_types.h" +#include "styles/style_boxes.h" TextParseOptions _confirmBoxTextOptions = { TextParseLinks | TextParseMultiline | TextParseRichText, // flags @@ -520,3 +521,86 @@ void KickMemberBox::onConfirm() { App::api()->kickParticipant(channel, _member); } } + +ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector &participants) : AbstractBox() +, _title(this, st::confirmInviteTitle) +, _status(this, st::confirmInviteStatus) +, _photo(chatDefPhoto(0)) +, _participants(participants) +, _join(this, lang(lng_group_invite_join), st::defaultBoxButton) +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { + if (_participants.size() > 4) { + _participants.resize(4); + } + + _title->setText(title); + QString status; + if (_participants.isEmpty() || _participants.size() >= count) { + status = lng_chat_status_members(lt_count, count); + } else { + status = lng_group_invite_members(lt_count, count); + } + _status->setText(status); + if (photo.type() == mtpc_chatPhoto) { + auto &d = photo.c_chatPhoto(); + auto location = App::imageLocation(160, 160, d.vphoto_small); + if (!location.isNull()) { + _photo = ImagePtr(location); + if (!_photo->loaded()) { + connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); + _photo->load(); + } + } + } + + int h = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _join->height() + st::boxButtonPadding.bottom(); + if (!_participants.isEmpty()) { + int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5; + int padding = skip / 2; + _userWidth = (st::confirmInviteUserPhotoSize + 2 * padding); + int sumWidth = _participants.size() * _userWidth; + int left = (width() - sumWidth) / 2; + for_const (auto user, _participants) { + auto name = new FlatLabel(this, st::confirmInviteUserName); + name->resizeToWidth(st::confirmInviteUserPhotoSize + padding); + name->setText(user->firstName.isEmpty() ? App::peerName(user) : user->firstName); + name->moveToLeft(left + (padding / 2), st::confirmInviteUserNameTop); + left += _userWidth; + } + + h += st::confirmInviteUserHeight; + } + setMaxHeight(h); + + connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + connect(_join, SIGNAL(clicked()), App::main(), SLOT(onInviteImport())); +} + +void ConfirmInviteBox::resizeEvent(QResizeEvent *e) { + _title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop); + _status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop); + _join->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _join->height()); + _cancel->moveToRight(st::boxButtonPadding.right() + _join->width() + st::boxButtonPadding.left(), _join->y()); +} + +void ConfirmInviteBox::paintEvent(QPaintEvent *e) { + Painter p(this); + if (paint(p)) return; + + p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize)); + + int sumWidth = _participants.size() * _userWidth; + int left = (width() - sumWidth) / 2; + for_const (auto user, _participants) { + user->paintUserpicLeft(p, st::confirmInviteUserPhotoSize, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width()); + left += _userWidth; + } +} + +void ConfirmInviteBox::showAll() { + showChildren(); +} + +void ConfirmInviteBox::hideAll() { + hideChildren(); +} diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index 59f27336d..11dabfaef 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -266,3 +266,26 @@ private: UserData *_member; }; + +class ConfirmInviteBox : public AbstractBox, public RPCSender { + Q_OBJECT + +public: + ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector &participants); + +protected: + void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; + + void showAll() override; + void hideAll() override; + +private: + ChildWidget _title, _status; + ImagePtr _photo; + QVector _participants; + + ChildWidget _join, _cancel; + int _userWidth = 0; + +}; diff --git a/Telegram/SourceFiles/boxes/confirmphonebox.cpp b/Telegram/SourceFiles/boxes/confirmphonebox.cpp new file mode 100644 index 000000000..af9c48d85 --- /dev/null +++ b/Telegram/SourceFiles/boxes/confirmphonebox.cpp @@ -0,0 +1,306 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "boxes/confirmphonebox.h" + +#include "styles/style_boxes.h" +#include "boxes/confirmbox.h" +#include "mainwidget.h" +#include "lang.h" + +namespace { + +QPointer CurrentConfirmPhoneBox = nullptr; + +} // namespace + +void ConfirmPhoneBox::start(const QString &phone, const QString &hash) { + if (CurrentConfirmPhoneBox) { + if (CurrentConfirmPhoneBox->getPhone() == phone) return; + delete CurrentConfirmPhoneBox; + } + if (auto main = App::main()) { + CurrentConfirmPhoneBox = new ConfirmPhoneBox(main, phone, hash); + } +} + +ConfirmPhoneBox::ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash) : AbstractBox(st::boxWidth) +, _phone(phone) +, _hash(hash) { + setParent(parent); + + MTPaccount_SendConfirmPhoneCode::Flags flags = 0; + _sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(flags), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail)); +} + +void ConfirmPhoneBox::sendCodeDone(const MTPauth_SentCode &result) { + _sendCodeRequestId = 0; + + auto &resultInner = result.c_auth_sentCode(); + switch (resultInner.vtype.type()) { + case mtpc_auth_sentCodeTypeApp: LOG(("Error: should not be in-app code!")); break; + case mtpc_auth_sentCodeTypeSms: _sentCodeLength = resultInner.vtype.c_auth_sentCodeTypeSms().vlength.v; break; + case mtpc_auth_sentCodeTypeCall: _sentCodeLength = resultInner.vtype.c_auth_sentCodeTypeCall().vlength.v; break; + case mtpc_auth_sentCodeTypeFlashCall: LOG(("Error: should not be flashcall!")); break; + } + _phoneHash = qs(resultInner.vphone_code_hash); + if (resultInner.has_next_type() && resultInner.vnext_type.type() == mtpc_auth_codeTypeCall) { + setCallStatus({ CallState::Waiting, resultInner.has_timeout() ? resultInner.vtimeout.v : 60 }); + } else { + setCallStatus({ CallState::Disabled, 0 }); + } + launch(); +} + +bool ConfirmPhoneBox::sendCodeFail(const RPCError &error) { + auto errorText = lang(lng_server_error); + if (MTP::isFloodError(error)) { + errorText = lang(lng_flood_error); + } else if (MTP::isDefaultHandledError(error)) { + return false; + } else if (error.code() == 400) { + errorText = lang(lng_confirm_phone_link_invalid); + } + _sendCodeRequestId = 0; + Ui::showLayer(new InformBox(errorText)); + deleteLater(); + return true; +} + +void ConfirmPhoneBox::setCallStatus(const CallStatus &status) { + _callStatus = status; + if (_callStatus.state == CallState::Waiting) { + _callTimer.start(1000); + } +} + +void ConfirmPhoneBox::launch() { + setBlueTitle(true); + + _about = new FlatLabel(this, st::confirmPhoneAboutLabel); + TextWithEntities aboutText; + auto formattedPhone = App::formatPhone(_phone); + aboutText.text = lng_confirm_phone_about(lt_phone, formattedPhone); + auto phonePosition = aboutText.text.indexOf(formattedPhone); + if (phonePosition >= 0) { + aboutText.entities.push_back(EntityInText(EntityInTextBold, phonePosition, formattedPhone.size())); + } + _about->setMarkedText(aboutText); + + _code = new InputField(this, st::confirmPhoneCodeField, lang(lng_code_ph)); + + _send = new BoxButton(this, lang(lng_confirm_phone_send), st::defaultBoxButton); + _cancel = new BoxButton(this, lang(lng_cancel), st::cancelBoxButton); + + setMaxHeight(st::boxTitleHeight + st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip + _send->height() + st::boxButtonPadding.bottom()); + + connect(_send, SIGNAL(clicked()), this, SLOT(onSendCode())); + connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + + connect(_code, SIGNAL(changed()), this, SLOT(onCodeChanged())); + connect(_code, SIGNAL(submitted(bool)), this, SLOT(onSendCode())); + + connect(&_callTimer, SIGNAL(timeout()), this, SLOT(onCallStatusTimer())); + + prepare(); + + Ui::showLayer(this); +} + +void ConfirmPhoneBox::onCallStatusTimer() { + if (_callStatus.state == CallState::Waiting) { + if (--_callStatus.timeout <= 0) { + _callStatus.state = CallState::Calling; + _callTimer.stop(); + MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_phoneHash)), rpcDone(&ConfirmPhoneBox::callDone)); + } + } + update(); +} + +void ConfirmPhoneBox::callDone(const MTPauth_SentCode &result) { + if (_callStatus.state == CallState::Calling) { + _callStatus.state = CallState::Called; + update(); + } +} + +void ConfirmPhoneBox::onSendCode() { + if (_sendCodeRequestId) { + return; + } + auto code = _code->getLastText(); + if (code.isEmpty()) { + _code->showError(); + return; + } + + _code->setDisabled(true); + setFocus(); + + showError(QString()); + + _sendCodeRequestId = MTP::send(MTPaccount_ConfirmPhone(MTP_string(_phoneHash), MTP_string(_code->getLastText())), rpcDone(&ConfirmPhoneBox::confirmDone), rpcFail(&ConfirmPhoneBox::confirmFail)); +} + +void ConfirmPhoneBox::confirmDone(const MTPBool &result) { + _sendCodeRequestId = 0; + Ui::showLayer(new InformBox(lng_confirm_phone_success(lt_phone, App::formatPhone(_phone)))); +} + +bool ConfirmPhoneBox::confirmFail(const RPCError &error) { + auto errorText = lang(lng_server_error); + if (MTP::isFloodError(error)) { + errorText = lang(lng_flood_error); + } else if (MTP::isDefaultHandledError(error)) { + return false; + } else { + auto &errorType = error.type(); + if (errorType == qstr("PHONE_CODE_EMPTY") || errorType == qstr("PHONE_CODE_INVALID")) { + errorText = lang(lng_bad_code); + } + } + _sendCodeRequestId = 0; + _code->setDisabled(false); + _code->setFocus(); + showError(errorText); + return true; +} + +void ConfirmPhoneBox::onCodeChanged() { + if (_fixing) return; + + _fixing = true; + QString newText, now = _code->getLastText(); + int oldPos = _code->textCursor().position(), newPos = -1; + int oldLen = now.size(), digitCount = 0; + for_const (auto ch, now) { + if (ch.isDigit()) { + ++digitCount; + } + } + + if (_sentCodeLength > 0 && digitCount > _sentCodeLength) { + digitCount = _sentCodeLength; + } + bool strict = (_sentCodeLength > 0 && digitCount == _sentCodeLength); + + newText.reserve(oldLen); + int i = 0; + for_const (auto ch, now) { + if (i++ == oldPos) { + newPos = newText.length(); + } + if (ch.isDigit()) { + if (!digitCount--) { + break; + } + newText += ch; + if (strict && !digitCount) { + break; + } + } + } + if (newPos < 0) { + newPos = newText.length(); + } + if (newText != now) { + now = newText; + _code->setText(now); + _code->setCursorPosition(newPos); + } + _fixing = false; + + showError(QString()); + if (strict) { + onSendCode(); + } +} + +void ConfirmPhoneBox::showError(const QString &error) { + _error = error; + if (!_error.isEmpty()) { + _code->showError(); + } + update(); +} + +void ConfirmPhoneBox::paintEvent(QPaintEvent *e) { + Painter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_confirm_phone_title)); + + p.setFont(st::boxTextFont); + auto callText = getCallText(); + if (!callText.isEmpty()) { + p.setPen(st::usernameDefaultFg); + auto callTextRectLeft = st::usernamePadding.left(); + auto callTextRectTop = _about->y() + _about->height(); + auto callTextRectWidth = width() - 2 * st::usernamePadding.left(); + auto callTextRect = QRect(callTextRectLeft, callTextRectTop, callTextRectWidth, st::usernameSkip); + p.drawText(callTextRect, callText, style::al_left); + } + auto errorText = _error; + if (errorText.isEmpty()) { + p.setPen(st::usernameDefaultFg); + errorText = lang(lng_confirm_phone_enter_code); + } else { + p.setPen(st::setErrColor); + } + auto errorTextRectLeft = st::usernamePadding.left(); + auto errorTextRectTop = _code->y() + _code->height(); + auto errorTextRectWidth = width() - 2 * st::usernamePadding.left(); + auto errorTextRect = QRect(errorTextRectLeft, errorTextRectTop, errorTextRectWidth, st::usernameSkip); + p.drawText(errorTextRect, errorText, style::al_left); +} + +QString ConfirmPhoneBox::getCallText() const { + switch (_callStatus.state) { + case CallState::Waiting: { + if (_callStatus.timeout >= 3600) { + return lng_code_call(lt_minutes, qsl("%1:%2").arg(_callStatus.timeout / 3600).arg((_callStatus.timeout / 60) % 60, 2, 10, QChar('0')), lt_seconds, qsl("%1").arg(_callStatus.timeout % 60, 2, 10, QChar('0'))); + } + return lng_code_call(lt_minutes, QString::number(_callStatus.timeout / 60), lt_seconds, qsl("%1").arg(_callStatus.timeout % 60, 2, 10, QChar('0'))); + } break; + case CallState::Calling: return lang(lng_code_calling); + case CallState::Called: return lang(lng_code_called); + } + return QString(); +} + +void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) { + _code->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _code->height()); + _code->moveToLeft(st::usernamePadding.left(), st::boxTitleHeight + st::usernamePadding.top()); + + _about->moveToLeft(st::usernamePadding.left(), _code->y() + _code->height() + st::usernameSkip); + + _send->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _send->height()); + _cancel->moveToRight(st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y()); + + AbstractBox::resizeEvent(e); +} + +ConfirmPhoneBox::~ConfirmPhoneBox() { + if (_sendCodeRequestId) { + MTP::cancel(_sendCodeRequestId); + } +} diff --git a/Telegram/SourceFiles/boxes/confirmphonebox.h b/Telegram/SourceFiles/boxes/confirmphonebox.h new file mode 100644 index 000000000..a19b8a371 --- /dev/null +++ b/Telegram/SourceFiles/boxes/confirmphonebox.h @@ -0,0 +1,107 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "boxes/abstractbox.h" + +class FlatLabel; + +class ConfirmPhoneBox : public AbstractBox, public RPCSender { + Q_OBJECT + +public: + static void start(const QString &phone, const QString &hash); + + ~ConfirmPhoneBox(); + +private slots: + void onCallStatusTimer(); + void onSendCode(); + void onCodeChanged(); + +protected: + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + void hideAll() override { + hideChildren(); + } + void showAll() override { + showChildren(); + } + void showDone() override { + _code->setFocus(); + } + +private: + ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash); + void sendCodeDone(const MTPauth_SentCode &result); + bool sendCodeFail(const RPCError &error); + + void callDone(const MTPauth_SentCode &result); + + void confirmDone(const MTPBool &result); + bool confirmFail(const RPCError &error); + + QString getPhone() const { + return _phone; + } + void launch(); + + enum CallState { + Waiting, + Calling, + Called, + Disabled, + }; + struct CallStatus { + CallState state; + int timeout; + }; + void setCallStatus(const CallStatus &status); + QString getCallText() const; + + void showError(const QString &error); + + mtpRequestId _sendCodeRequestId = 0; + + // _hash from the link for account.sendConfirmPhoneCode call. + // _phoneHash from auth.sentCode for account.confirmPhone call. + QString _phone, _hash; + QString _phoneHash; + + // If we receive the code length, we autosubmit _code field when enough symbols is typed. + int _sentCodeLength = 0; + + mtpRequestId _checkCodeRequestId = 0; + + ChildWidget _about = { nullptr }; + ChildWidget _send = { nullptr }; + ChildWidget _cancel = { nullptr }; + ChildWidget _code = { nullptr }; + + // Flag for not calling onTextChanged() recursively. + bool _fixing = false; + QString _error; + + CallStatus _callStatus; + QTimer _callTimer; + +}; diff --git a/Telegram/SourceFiles/boxes/passcodebox.h b/Telegram/SourceFiles/boxes/passcodebox.h index be908ae1a..eecdf664f 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.h +++ b/Telegram/SourceFiles/boxes/passcodebox.h @@ -26,15 +26,10 @@ class PasscodeBox : public AbstractBox, public RPCSender { Q_OBJECT public: - PasscodeBox(bool turningOff = false); PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false); - void init(); - void paintEvent(QPaintEvent *e); - void resizeEvent(QResizeEvent *e); - -public slots: +private slots: void onSave(bool force = false); void onBadOldPasscode(); void onOldChanged(); @@ -47,16 +42,17 @@ public slots: void onSubmit(); signals: - void reloadPassword(); protected: - - void hideAll(); - void showAll(); - void showDone(); + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + void hideAll() override; + void showAll() override; + void showDone() override; private: + void init(); void setPasswordDone(const MTPBool &result); bool setPasswordFail(const RPCError &error); diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp index b71a9634e..5176838ac 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.cpp +++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp @@ -28,18 +28,51 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/confirmbox.h" #include "apiwrap.h" #include "localstorage.h" +#include "dialogs/dialogs_layout.h" +#include "styles/style_boxes.h" + +namespace { + +constexpr int kArchivedLimitFirstRequest = 10; +constexpr int kArchivedLimitPerPage = 30; + +} // namespace + +namespace Stickers { + +void applyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) { + auto &v = d.vsets.c_vector().v; + auto &order = Global::RefStickerSetsOrder(); + Stickers::Order archived; + archived.reserve(v.size()); + QMap setsToRequest; + for_const (auto &stickerSet, v) { + if (stickerSet.type() == mtpc_stickerSetCovered && stickerSet.c_stickerSetCovered().vset.type() == mtpc_stickerSet) { + auto set = Stickers::feedSet(stickerSet.c_stickerSetCovered().vset.c_stickerSet()); + if (set->stickers.isEmpty()) { + setsToRequest.insert(set->id, set->access); + } + auto index = order.indexOf(set->id); + if (index >= 0) { + order.removeAt(index); + } + archived.push_back(set->id); + } + } + if (!setsToRequest.isEmpty()) { + for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) { + App::api()->scheduleStickerSetRequest(i.key(), i.value()); + } + App::api()->requestStickerSets(); + } + Local::writeArchivedStickers(); + Ui::showLayer(new StickersBox(archived), KeepOtherLayers); +} + +} // namespace Stickers StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : TWidget() -, _loaded(false) -, _setId(0) -, _setAccess(0) -, _setCount(0) -, _setHash(0) -, _setFlags(0) -, _bottom(0) -, _input(set) -, _installRequest(0) -, _previewShown(-1) { +, _input(set) { connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); switch (set.type()) { case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break; @@ -56,21 +89,21 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) { _pack.clear(); _emoji.clear(); if (set.type() == mtpc_messages_stickerSet) { - const auto &d(set.c_messages_stickerSet()); - const auto &v(d.vdocuments.c_vector().v); + auto &d(set.c_messages_stickerSet()); + auto &v(d.vdocuments.c_vector().v); _pack.reserve(v.size()); - for (int32 i = 0, l = v.size(); i < l; ++i) { - DocumentData *doc = App::feedDocument(v.at(i)); + for (int i = 0, l = v.size(); i < l; ++i) { + auto doc = App::feedDocument(v.at(i)); if (!doc || !doc->sticker()) continue; _pack.push_back(doc); } - const auto &packs(d.vpacks.c_vector().v); - for (int32 i = 0, l = packs.size(); i < l; ++i) { + auto &packs(d.vpacks.c_vector().v); + for (int i = 0, l = packs.size(); i < l; ++i) { if (packs.at(i).type() != mtpc_stickerPack) continue; - const auto &pack(packs.at(i).c_stickerPack()); - if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) { - const auto &stickers(pack.vdocuments.c_vector().v); + auto &pack(packs.at(i).c_stickerPack()); + if (auto e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) { + auto &stickers(pack.vdocuments.c_vector().v); StickerPack p; p.reserve(stickers.size()); for (int32 j = 0, c = stickers.size(); j < c; ++j) { @@ -83,7 +116,7 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) { } } if (d.vset.type() == mtpc_stickerSet) { - const auto &s(d.vset.c_stickerSet()); + auto &s(d.vset.c_stickerSet()); _setTitle = stickerSetTitle(s); _title = st::boxTitleFont->elided(_setTitle, width() - st::boxTitlePosition.x() - st::boxTitleHeight); _setShortName = qs(s.vshort_name); @@ -92,6 +125,15 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) { _setCount = s.vcount.v; _setHash = s.vhash.v; _setFlags = s.vflags.v; + auto &sets = Global::RefStickerSets(); + auto it = sets.find(_setId); + if (it != sets.cend()) { + auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_special); + _setFlags |= clientFlags; + it->flags = _setFlags; + it->stickers = _pack; + it->emoji = _emoji; + } } } @@ -116,19 +158,29 @@ bool StickerSetInner::failedSet(const RPCError &error) { return true; } -void StickerSetInner::installDone(const MTPBool &result) { - Stickers::Sets &sets(Global::RefStickerSets()); +void StickerSetInner::installDone(const MTPmessages_StickerSetInstallResult &result) { + auto &sets = Global::RefStickerSets(); - _setFlags &= ~MTPDstickerSet::Flag::f_disabled; + bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived); + if (wasArchived) { + auto index = Global::RefArchivedStickerSetsOrder().indexOf(_setId); + if (index >= 0) { + Global::RefArchivedStickerSetsOrder().removeAt(index); + } + } + _setFlags &= ~MTPDstickerSet::Flag::f_archived; + _setFlags |= MTPDstickerSet::Flag::f_installed; auto it = sets.find(_setId); if (it == sets.cend()) { it = sets.insert(_setId, Stickers::Set(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags)); + } else { + it->flags = _setFlags; } - it.value().stickers = _pack; - it.value().emoji = _emoji; + it->stickers = _pack; + it->emoji = _emoji; - Stickers::Order &order(Global::RefStickerSetsOrder()); - int32 insertAtIndex = 0, currentIndex = order.indexOf(_setId); + auto &order = Global::RefStickerSetsOrder(); + int insertAtIndex = 0, currentIndex = order.indexOf(_setId); if (currentIndex != insertAtIndex) { if (currentIndex > 0) { order.removeAt(currentIndex); @@ -138,27 +190,30 @@ void StickerSetInner::installDone(const MTPBool &result) { auto custom = sets.find(Stickers::CustomSetId); if (custom != sets.cend()) { - for (int32 i = 0, l = _pack.size(); i < l; ++i) { - int32 removeIndex = custom->stickers.indexOf(_pack.at(i)); + for_const (auto sticker, _pack) { + int removeIndex = custom->stickers.indexOf(sticker); if (removeIndex >= 0) custom->stickers.removeAt(removeIndex); } if (custom->stickers.isEmpty()) { sets.erase(custom); } } - Local::writeStickers(); + + if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { + Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); + } else if (wasArchived) { + Local::writeArchivedStickers(); + } + + Local::writeInstalledStickers(); + emit App::main()->stickersUpdated(); emit installed(_setId); - Ui::hideLayer(); } -bool StickerSetInner::installFailed(const RPCError &error) { +bool StickerSetInner::installFail(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; - if (error.type() == qstr("STICKERSETS_TOO_MUCH")) { - Ui::showLayer(new InformBox(lang(lng_stickers_too_many_packs))); - } else { - Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); - } + Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); return true; } @@ -261,7 +316,7 @@ bool StickerSetInner::loaded() const { int32 StickerSetInner::notInstalled() const { if (!_loaded) return 0; auto it = Global::StickerSets().constFind(_setId); - if (it == Global::StickerSets().cend() || (it->flags & MTPDstickerSet::Flag::f_disabled)) return _pack.size(); + if (it == Global::StickerSets().cend() || !(it->flags & MTPDstickerSet::Flag::f_installed) || (it->flags & MTPDstickerSet::Flag::f_archived)) return _pack.size(); return 0; } @@ -279,7 +334,7 @@ QString StickerSetInner::shortName() const { void StickerSetInner::install() { if (_installRequest) return; - _installRequest = MTP::send(MTPmessages_InstallStickerSet(_input, MTP_bool(false)), rpcDone(&StickerSetInner::installDone), rpcFail(&StickerSetInner::installFailed)); + _installRequest = MTP::send(MTPmessages_InstallStickerSet(_input, MTP_bool(false)), rpcDone(&StickerSetInner::installDone), rpcFail(&StickerSetInner::installFail)); } StickerSetInner::~StickerSetInner() { @@ -305,7 +360,7 @@ StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st:: connect(&_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons())); connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); - connect(&_inner, SIGNAL(installed(uint64)), this, SIGNAL(installed(uint64))); + connect(&_inner, SIGNAL(installed(uint64)), this, SLOT(onInstalled(uint64))); onStickersUpdated(); @@ -314,6 +369,11 @@ StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st:: prepare(); } +void StickerSetBox::onInstalled(uint64 setId) { + emit installed(setId); + onClose(); +} + void StickerSetBox::onStickersUpdated() { showAll(); } @@ -402,28 +462,59 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) { } } -StickersInner::StickersInner() : TWidget() +namespace internal { + +StickersInner::StickersInner(StickersBox::Section section) : TWidget() +, _section(section) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) -, _aboveShadowFadeStart(0) -, _aboveShadowFadeOpacity(0, 0) , _a_shifting(animation(this, &StickersInner::step_shifting)) , _itemsTop(st::membersPadding.top()) -, _saving(false) -, _removeSel(-1) -, _removeDown(-1) +, _clearWidth(st::normalFont->width(lang(lng_stickers_clear_recent))) , _removeWidth(st::normalFont->width(lang(lng_stickers_remove))) , _returnWidth(st::normalFont->width(lang(lng_stickers_return))) , _restoreWidth(st::normalFont->width(lang(lng_stickers_restore))) -, _selected(-1) -, _started(-1) -, _dragging(-1) -, _above(-1) -, _aboveShadow(st::boxShadow) -, _scrollbar(0) { +, _aboveShadow(st::boxShadow) { + setup(); +} + +StickersInner::StickersInner(const Stickers::Order &archivedIds) : TWidget() +, _section(StickersBox::Section::ArchivedPart) +, _archivedIds(archivedIds) +, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) +, _a_shifting(animation(this, &StickersInner::step_shifting)) +, _itemsTop(st::membersPadding.top()) +, _clearWidth(st::normalFont->width(lang(lng_stickers_clear_recent))) +, _removeWidth(st::normalFont->width(lang(lng_stickers_remove))) +, _returnWidth(st::normalFont->width(lang(lng_stickers_return))) +, _restoreWidth(st::normalFont->width(lang(lng_stickers_restore))) +, _aboveShadow(st::boxShadow) { + setup(); +} + +void StickersInner::setup() { connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); setMouseTracking(true); } +void StickersInner::paintButton(Painter &p, int y, bool selected, const QString &text, int badgeCounter) const { + if (selected) { + p.fillRect(0, y, width(), _buttonHeight, st::contactsBgOver); + } + p.setFont(st::stickersFeaturedFont); + p.setPen(st::stickersFeaturedPen); + p.drawTextLeft(st::stickersFeaturedPosition.x(), y + st::stickersFeaturedPosition.y(), width(), text); + + if (badgeCounter) { + Dialogs::Layout::UnreadBadgeStyle unreadSt; + unreadSt.sizeId = Dialogs::Layout::UnreadBadgeInStickersBox; + unreadSt.size = st::stickersFeaturedBadgeSize; + int unreadRight = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x()); + if (rtl()) unreadRight = width() - unreadRight; + int unreadTop = y + (_buttonHeight - st::stickersFeaturedBadgeSize) / 2; + Dialogs::Layout::paintUnreadCount(p, QString::number(badgeCounter), unreadRight, unreadTop, unreadSt); + } +} + void StickersInner::paintEvent(QPaintEvent *e) { QRect r(e->rect()); Painter p(this); @@ -432,10 +523,23 @@ void StickersInner::paintEvent(QPaintEvent *e) { p.fillRect(r, st::white); p.setClipRect(r); + + int y = st::membersPadding.top(); + if (_hasFeaturedButton) { + auto selected = (_selected == -2); + paintButton(p, y, selected, lang(lng_stickers_featured), Global::FeaturedStickerSetsUnreadCount()); + y += _buttonHeight; + } + if (_hasArchivedButton) { + auto selected = (_selected == -1); + paintButton(p, y, selected, lang(lng_stickers_archived), 0); + y += _buttonHeight; + } + if (_rows.isEmpty()) { - p.setFont(st::noContactsFont->f); - p.setPen(st::noContactsColor->p); - p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center); + p.setFont(st::noContactsFont); + p.setPen(st::noContactsColor); + p.drawText(QRect(0, y, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center); } else { p.translate(0, _itemsTop); @@ -462,50 +566,84 @@ void StickersInner::paintRow(Painter &p, int32 index) { int32 xadd = 0, yadd = s->yadd.current(); if (xadd || yadd) p.translate(xadd, yadd); - bool removeSel = (index == _removeSel && (_removeDown < 0 || index == _removeDown)); - bool removeDown = removeSel && (index == _removeDown); + if (_section == Section::Installed) { + bool removeSel = (index == _actionSel && (_actionDown < 0 || index == _actionDown)); + bool removeDown = removeSel && (index == _actionDown); - p.setFont((removeSel ? st::linkOverFont : st::linkFont)->f); - if (removeDown) { - p.setPen(st::btnDefLink.downColor->p); - } else { - p.setPen(st::btnDefLink.color->p); - } - int32 remWidth = s->disabled ? (s->official ? _restoreWidth : _returnWidth) : _removeWidth; - QString remText = lang(s->disabled ? (s->official ? lng_stickers_restore : lng_stickers_return) : lng_stickers_remove); - p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), remText, remWidth); - - if (index == _above) { - float64 current = _aboveShadowFadeOpacity.current(); - if (_started >= 0) { - float64 o = aboveShadowOpacity(); - if (o > current) { - _aboveShadowFadeOpacity = anim::fvalue(o, o); - current = o; - } + p.setFont(removeSel ? st::linkOverFont : st::linkFont); + if (removeDown) { + p.setPen(st::btnDefLink.downColor); + } else { + p.setPen(st::btnDefLink.color); } - p.setOpacity(current); - QRect row(myrtlrect(_aboveShadow.getDimensions(st::boxShadowShift).left(), st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - _aboveShadow.getDimensions(st::boxShadowShift).right(), _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2))); - _aboveShadow.paint(p, row, st::boxShadowShift); - p.fillRect(row, st::white); - p.setOpacity(1); + int32 remWidth = s->recent ? _clearWidth : (s->disabled ? (s->official ? _restoreWidth : _returnWidth) : _removeWidth); + QString remText = lang(s->recent ? lng_stickers_clear_recent : (s->disabled ? (s->official ? lng_stickers_restore : lng_stickers_return) : lng_stickers_remove)); + p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), remText, remWidth); + + if (index == _above) { + float64 current = _aboveShadowFadeOpacity.current(); + if (_started >= 0) { + float64 o = aboveShadowOpacity(); + if (o > current) { + _aboveShadowFadeOpacity = anim::fvalue(o, o); + current = o; + } + } + p.setOpacity(current); + QRect row(myrtlrect(_aboveShadow.getDimensions(st::boxShadowShift).left(), st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - _aboveShadow.getDimensions(st::boxShadowShift).right(), _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2))); + _aboveShadow.paint(p, row, st::boxShadowShift); + p.fillRect(row, st::white); + p.setOpacity(1); + } + } else if (s->installed && !s->disabled) { + int addw = st::stickersAddSize.width(); + int checkx = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x() + (addw + st::stickersFeaturedInstalled.width()) / 2); + int checky = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersFeaturedInstalled.height()) / 2; + st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width()); + } else { + int addw = st::stickersAddSize.width(); + int addx = width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - addw; + int addy = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersAddSize.height()) / 2; + QRect add(myrtlrect(addx, addy, addw, st::stickersAddSize.height())); + + auto textBg = (_actionSel == index) ? st::defaultActiveButton.textBgOver : st::defaultActiveButton.textBg; + App::roundRect(p, add, textBg, ImageRoundRadius::Small); + int iconx = addx + (st::stickersAddSize.width() - st::stickersAddIcon.width()) / 2; + int icony = addy + (st::stickersAddSize.height() - st::stickersAddIcon.height()) / 2; + icony += (_actionSel == index && _actionDown == index) ? (st::defaultActiveButton.downTextTop - st::defaultActiveButton.textTop) : 0; + st::stickersAddIcon.paint(p, QPoint(iconx, icony), width()); } - if (s->disabled) p.setOpacity(st::stickersRowDisabledOpacity); + if (s->disabled && _section == Section::Installed) { + p.setOpacity(st::stickersRowDisabledOpacity); + } if (s->sticker) { s->sticker->thumb->load(); QPixmap pix(s->sticker->thumb->pix(s->pixw, s->pixh)); p.drawPixmapLeft(st::contactsPadding.left() + (st::contactsPhotoSize - s->pixw) / 2, st::contactsPadding.top() + (st::contactsPhotoSize - s->pixh) / 2, width(), pix); } + + int namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(); + int namey = st::contactsPadding.top() + st::contactsNameTop; + int statusx = namex; + int statusy = st::contactsPadding.top() + st::contactsStatusTop; + + if (s->unread) { + p.setPen(Qt::NoPen); + p.setBrush(st::stickersFeaturedUnreadBg); + + p.setRenderHint(QPainter::HighQualityAntialiasing, true); + p.drawEllipse(rtlrect(namex, namey + st::stickersFeaturedUnreadTop, st::stickersFeaturedUnreadSize, st::stickersFeaturedUnreadSize, width())); + p.setRenderHint(QPainter::HighQualityAntialiasing, false); + namex += st::stickersFeaturedUnreadSize + st::stickersFeaturedUnreadSkip; + } p.setFont(st::contactsNameFont); p.setPen(st::black); - - int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(); - p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsNameTop, width(), s->title); + p.drawTextLeft(namex, namey, width(), s->title); p.setFont(st::contactsStatusFont); p.setPen(st::contactsStatusFg); - p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), lng_stickers_count(lt_count, s->count)); + p.drawTextLeft(statusx, statusy, width(), lng_stickers_count(lt_count, s->count)); p.setOpacity(1); if (xadd || yadd) p.translate(-xadd, -yadd); @@ -516,10 +654,12 @@ void StickersInner::mousePressEvent(QMouseEvent *e) { if (_dragging >= 0) mouseReleaseEvent(e); _mouse = e->globalPos(); onUpdateSelected(); - if (_removeSel >= 0) { - _removeDown = _removeSel; - update(0, _itemsTop + _removeSel * _rowHeight, width(), _rowHeight); - } else if (_selected >= 0) { + + _pressed = _selected; + if (_actionSel >= 0) { + _actionDown = _actionSel; + update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight); + } else if (_selected >= 0 && _section == Section::Installed && !_rows.at(_selected)->recent) { _above = _dragging = _started = _selected; _dragStart = mapFromGlobal(_mouse); } @@ -537,8 +677,12 @@ void StickersInner::onUpdateSelected() { if (_dragging >= 0) { int32 shift = 0; uint64 ms = getms(); + int firstSetIndex = 0; + if (_rows.at(firstSetIndex)->recent) { + ++firstSetIndex; + } if (_dragStart.y() > local.y() && _dragging > 0) { - shift = -floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging); + shift = -floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging - firstSetIndex); for (int32 from = _dragging, to = _dragging + shift; from > to; --from) { qSwap(_rows[from], _rows[from - 1]); _rows.at(from)->yadd = anim::ivalue(_rows.at(from)->yadd.current() - _rowHeight, 0); @@ -567,19 +711,74 @@ void StickersInner::onUpdateSelected() { emit checkDraggingScroll(local.y()); } else { bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersPadding.bottom())).contains(local); - _selected = in ? floorclamp(local.y() - _itemsTop, _rowHeight, 0, _rows.size() - 1) : -1; - int32 removeSel = -1; + int selected = -2; + int actionSel = -1; + if (in) { + selected = floorclamp(local.y() - _itemsTop, _rowHeight, 0, _rows.size() - 1); - if (_selected >= 0) { - int32 remw = _rows.at(_selected)->disabled ? (_rows.at(_selected)->official ? _restoreWidth : _returnWidth) : _removeWidth; - QRect rem(myrtlrect(width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - remw, st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, remw, st::normalFont->height)); - removeSel = rem.contains(local.x(), local.y() - _itemsTop - _selected * _rowHeight) ? _selected : -1; + if (_section == Section::Installed) { + int remw = _rows.at(selected)->recent ? _clearWidth : (_rows.at(selected)->disabled ? (_rows.at(selected)->official ? _restoreWidth : _returnWidth) : _removeWidth); + QRect rem(myrtlrect(width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - remw, st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, remw, st::normalFont->height)); + actionSel = rem.contains(local.x(), local.y() - _itemsTop - selected * _rowHeight) ? selected : -1; + } else if (_rows.at(selected)->installed && !_rows.at(selected)->disabled) { + actionSel = -1; + } else { + int addw = st::stickersAddSize.width(); + int addx = width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - addw; + int addy = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersAddSize.height()) / 2; + QRect add(myrtlrect(addx, addy, addw, st::stickersAddSize.height())); + actionSel = add.contains(local.x(), local.y() - _itemsTop - selected * _rowHeight) ? selected : -1; + } + } else if (_hasFeaturedButton && QRect(0, st::membersPadding.top(), width(), _buttonHeight).contains(local)) { + selected = -2; + } else if (_hasArchivedButton && QRect(0, st::membersPadding.top() + (_hasFeaturedButton ? _buttonHeight : 0), width(), _buttonHeight).contains(local)) { + selected = -1; + } else { + selected = -3; } - setRemoveSel(removeSel); + if (_selected != selected) { + if (((_selected == -1) != (selected == -1)) || ((_selected == -2) != (selected == -2))) { + update(); + } + if (_section != Section::Installed && ((_selected >= 0 || _pressed >= 0) != (selected >= 0 || _pressed >= 0))) { + setCursor((selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default); + } + _selected = selected; + } + setActionSel(actionSel); emit noDraggingScroll(); } } +void StickersInner::onClearRecent() { + if (_clearBox) { + _clearBox->onClose(); + } + + auto &sets = Global::RefStickerSets(); + bool removedCloud = (sets.remove(Stickers::CloudRecentSetId) != 0); + bool removedCustom = (sets.remove(Stickers::CustomSetId) != 0); + + auto &recent = cGetRecentStickers(); + if (!recent.isEmpty()) { + recent.clear(); + Local::writeUserSettings(); + } + + if (removedCustom) Local::writeInstalledStickers(); + if (removedCloud) Local::writeRecentStickers(); + emit App::main()->updateStickers(); + rebuild(); + + MTP::send(MTPmessages_ClearRecentStickers()); +} + +void StickersInner::onClearBoxDestroyed(QObject *box) { + if (box == _clearBox) { + _clearBox = nullptr; + } +} + float64 StickersInner::aboveShadowOpacity() const { if (_above < 0) return 0; @@ -589,11 +788,30 @@ float64 StickersInner::aboveShadowOpacity() const { } void StickersInner::mouseReleaseEvent(QMouseEvent *e) { + auto pressed = _pressed; + _pressed = -2; + + if (_section != Section::Installed && _selected < 0 && pressed >= 0) { + setCursor(style::cur_default); + } + if (_saving) return; + _mouse = e->globalPos(); onUpdateSelected(); - if (_removeDown == _removeSel && _removeSel >= 0) { - _rows[_removeDown]->disabled = !_rows[_removeDown]->disabled; + if (_actionDown == _actionSel && _actionSel >= 0) { + if (_section == Section::Installed) { + if (_rows[_actionDown]->recent) { + _clearBox = new ConfirmBox(lang(lng_stickers_clear_recent_sure), lang(lng_stickers_clear_recent)); + connect(_clearBox, SIGNAL(confirmed()), this, SLOT(onClearRecent())); + connect(_clearBox, SIGNAL(destroyed(QObject*)), this, SLOT(onClearBoxDestroyed(QObject*))); + Ui::showLayer(_clearBox, KeepOtherLayers); + } else { + _rows[_actionDown]->disabled = !_rows[_actionDown]->disabled; + } + } else { + installSet(_rows[_actionDown]->id); + } } else if (_dragging >= 0) { QPoint local(mapFromGlobal(_mouse)); _rows[_dragging]->yadd.start(0); @@ -604,13 +822,124 @@ void StickersInner::mouseReleaseEvent(QMouseEvent *e) { } _dragging = _started = -1; + } else if (pressed == _selected && _actionSel < 0 && _actionDown < 0) { + if (_selected == -2) { + _selected = -3; + Ui::showLayer(new StickersBox(Section::Featured), KeepOtherLayers); + } else if (_selected == -1) { + _selected = -3; + Ui::showLayer(new StickersBox(Section::Archived), KeepOtherLayers); + } else if (_selected >= 0 && _section != Section::Installed) { + auto &sets = Global::RefStickerSets(); + auto it = sets.find(_rows.at(pressed)->id); + if (it != sets.cend()) { + _selected = -3; + Ui::showLayer(new StickerSetBox(Stickers::inputSetId(*it)), KeepOtherLayers); + } + } } - if (_removeDown >= 0) { - update(0, _itemsTop + _removeDown * _rowHeight, width(), _rowHeight); - _removeDown = -1; + if (_actionDown >= 0) { + update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight); + _actionDown = -1; } } +void StickersInner::leaveEvent(QEvent *e) { + _mouse = QPoint(-1, -1); + onUpdateSelected(); +} + +void StickersInner::installSet(uint64 setId) { + auto &sets = Global::RefStickerSets(); + auto it = sets.find(setId); + if (it == sets.cend()) { + rebuild(); + return; + } + + MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_boolFalse()), rpcDone(&StickersInner::installDone), rpcFail(&StickersInner::installFail, setId)); + + auto flags = it->flags; + it->flags &= ~(MTPDstickerSet::Flag::f_archived | MTPDstickerSet_ClientFlag::f_unread); + it->flags |= MTPDstickerSet::Flag::f_installed; + auto changedFlags = flags ^ it->flags; + + auto &order = Global::RefStickerSetsOrder(); + int insertAtIndex = 0, currentIndex = order.indexOf(setId); + if (currentIndex != insertAtIndex) { + if (currentIndex > 0) { + order.removeAt(currentIndex); + } + order.insert(insertAtIndex, setId); + } + + auto custom = sets.find(Stickers::CustomSetId); + if (custom != sets.cend()) { + for_const (auto sticker, it->stickers) { + int removeIndex = custom->stickers.indexOf(sticker); + if (removeIndex >= 0) custom->stickers.removeAt(removeIndex); + } + if (custom->stickers.isEmpty()) { + sets.erase(custom); + } + } + Local::writeInstalledStickers(); + if (changedFlags & MTPDstickerSet_ClientFlag::f_unread) Local::writeFeaturedStickers(); + if (changedFlags & MTPDstickerSet::Flag::f_archived) { + auto index = Global::RefArchivedStickerSetsOrder().indexOf(setId); + if (index >= 0) { + Global::RefArchivedStickerSetsOrder().removeAt(index); + Local::writeArchivedStickers(); + } + } + emit App::main()->stickersUpdated(); +} + +void StickersInner::installDone(const MTPmessages_StickerSetInstallResult &result) { + if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { + Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); + Local::writeInstalledStickers(); + Local::writeArchivedStickers(); + emit App::main()->stickersUpdated(); + } + + // TEST DATA ONLY + //MTPVector v = MTP_vector(0); + //for (auto &set : Global::RefStickerSets()) { + // if (rand() < RAND_MAX / 2) { + // set.flags |= MTPDstickerSet::Flag::f_archived; + // v._vector().v.push_back(MTP_stickerSet(MTP_flags(set.flags), MTP_long(set.id), MTP_long(set.access), MTP_string(set.title), MTP_string(set.shortName), MTP_int(set.count), MTP_int(set.hash))); + // } + //} + //Stickers::applyArchivedResult(MTP_messages_stickerSetInstallResultArchive(v).c_messages_stickerSetInstallResultArchive()); +} + +bool StickersInner::installFail(uint64 setId, const RPCError &error) { + if (MTP::isDefaultHandledError(error)) return false; + + auto &sets = Global::RefStickerSets(); + auto it = sets.find(setId); + if (it == sets.cend()) { + rebuild(); + return true; + } + + it->flags &= ~MTPDstickerSet::Flag::f_installed; + + auto &order = Global::RefStickerSetsOrder(); + int currentIndex = order.indexOf(setId); + if (currentIndex >= 0) { + order.removeAt(currentIndex); + } + + Local::writeInstalledStickers(); + emit App::main()->stickersUpdated(); + + Ui::showLayer(new InformBox(lang(lng_stickers_not_found)), KeepOtherLayers); + + return true; +} + void StickersInner::step_shifting(uint64 ms, bool timer) { bool animating = false; int32 updateMin = -1, updateMax = 0; @@ -664,90 +993,267 @@ void StickersInner::clear() { _aboveShadowFadeOpacity = anim::fvalue(0, 0); _a_shifting.stop(); _above = _dragging = _started = -1; - _selected = -1; - _removeDown = -1; - setRemoveSel(-1); + _selected = -3; + _pressed = -3; + _actionDown = -1; + setActionSel(-1); update(); } -void StickersInner::setRemoveSel(int32 removeSel) { - if (removeSel != _removeSel) { - if (_removeSel >= 0) update(0, _itemsTop + _removeSel * _rowHeight, width(), _rowHeight); - _removeSel = removeSel; - if (_removeSel >= 0) update(0, _itemsTop + _removeSel * _rowHeight, width(), _rowHeight); - setCursor((_removeSel >= 0 && (_removeDown < 0 || _removeDown == _removeSel)) ? style::cur_pointer : style::cur_default); +void StickersInner::setActionSel(int32 actionSel) { + if (actionSel != _actionSel) { + if (_actionSel >= 0) update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight); + _actionSel = actionSel; + if (_actionSel >= 0) update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight); + if (_section == Section::Installed) { + setCursor((_actionSel >= 0 && (_actionDown < 0 || _actionDown == _actionSel)) ? style::cur_pointer : style::cur_default); + } } } void StickersInner::rebuild() { - QList rows, rowsDisabled; + _hasFeaturedButton = _hasArchivedButton = false; + _itemsTop = st::membersPadding.top(); + _buttonHeight = st::stickersFeaturedHeight; + if (_section == Section::Installed) { + if (!Global::FeaturedStickerSetsOrder().isEmpty()) { + _itemsTop += _buttonHeight; + _hasFeaturedButton = true; + } + if (!Global::ArchivedStickerSetsOrder().isEmpty()) { + _itemsTop += _buttonHeight; + _hasArchivedButton = true; + } + if (_itemsTop > st::membersPadding.top()) { + _itemsTop += st::membersPadding.top(); + } + } - int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(); - int32 namew = st::boxWideWidth - namex - st::contactsPadding.right() - st::contactsCheckPosition.x() - qMax(qMax(_returnWidth, _removeWidth), _restoreWidth); + int maxNameWidth = countMaxNameWidth(); clear(); - const Stickers::Order &order(Global::StickerSetsOrder()); - _animStartTimes.reserve(order.size()); + auto &order = ([this]() -> const Stickers::Order & { + if (_section == Section::Installed) { + return Global::StickerSetsOrder(); + } else if (_section == Section::Featured) { + return Global::FeaturedStickerSetsOrder(); + } else if (_section == Section::Archived) { + return Global::ArchivedStickerSetsOrder(); + } + return _archivedIds; + })(); + _rows.reserve(order.size() + 1); + _animStartTimes.reserve(order.size() + 1); - const Stickers::Sets &sets(Global::StickerSets()); - for (int i = 0, l = order.size(); i < l; ++i) { - auto it = sets.constFind(order.at(i)); - if (it != sets.cend()) { - bool disabled = (it->flags & MTPDstickerSet::Flag::f_disabled); + auto &sets = Global::StickerSets(); + if (_section == Section::Installed) { + auto cloudIt = sets.constFind(Stickers::CloudRecentSetId); + if (cloudIt != sets.cend() && !cloudIt->stickers.isEmpty()) { + rebuildAppendSet(cloudIt.value(), maxNameWidth); + } + } + for_const (auto setId, order) { + auto it = sets.constFind(setId); + if (it == sets.cend()) { + continue; + } - DocumentData *sticker = it->stickers.isEmpty() ? 0 : it->stickers.at(0); - int32 pixw = 0, pixh = 0; - if (sticker) { - pixw = sticker->thumb->width(); - pixh = sticker->thumb->height(); - if (pixw > st::contactsPhotoSize) { - if (pixw > pixh) { - pixh = (pixh * st::contactsPhotoSize) / pixw; - pixw = st::contactsPhotoSize; - } else { - pixw = (pixw * st::contactsPhotoSize) / pixh; - pixh = st::contactsPhotoSize; - } - } else if (pixh > st::contactsPhotoSize) { - pixw = (pixw * st::contactsPhotoSize) / pixh; - pixh = st::contactsPhotoSize; - } - } - QString title = it->title; - int32 titleWidth = st::contactsNameFont->width(title); - if (titleWidth > namew) { - title = st::contactsNameFont->elided(title, namew); - } - bool official = (it->flags & MTPDstickerSet::Flag::f_official); - (disabled ? rowsDisabled : rows).push_back(new StickerSetRow(it->id, sticker, it->stickers.size(), title, official, disabled, pixw, pixh)); - _animStartTimes.push_back(0); - if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { - App::api()->scheduleStickerSetRequest(it->id, it->access); - } + rebuildAppendSet(it.value(), maxNameWidth); + + if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { + App::api()->scheduleStickerSetRequest(it->id, it->access); } } App::api()->requestStickerSets(); - _rows = rows + rowsDisabled; + updateSize(); + + if (_section == Section::Featured && Global::FeaturedStickerSetsUnreadCount()) { + Global::SetFeaturedStickerSetsUnreadCount(0); + for (auto &set : Global::RefStickerSets()) { + set.flags &= ~MTPDstickerSet_ClientFlag::f_unread; + } + MTP::send(MTPmessages_ReadFeaturedStickers(), rpcDone(&StickersInner::readFeaturedDone), rpcFail(&StickersInner::readFeaturedFail)); + } +} + +void StickersInner::updateSize() { resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersPadding.bottom()); } -QVector StickersInner::getOrder() const { - QVector result; +void StickersInner::updateRows() { + int maxNameWidth = countMaxNameWidth(); + auto &sets = Global::StickerSets(); + for_const (auto row, _rows) { + auto it = sets.constFind(row->id); + if (it != sets.cend()) { + auto &set = it.value(); + if (!row->sticker) { + DocumentData *sticker = nullptr; + int pixw = 0, pixh = 0; + fillSetCover(set, &sticker, &pixw, &pixh); + if (sticker) { + row->sticker = sticker; + row->pixw = pixw; + row->pixh = pixh; + } + } + fillSetFlags(set, &row->recent, &row->installed, &row->official, &row->unread, &row->disabled); + if (_section == Section::Installed) { + row->disabled = false; + } + row->title = fillSetTitle(set, maxNameWidth); + row->count = fillSetCount(set); + } + } + update(); +} + +bool StickersInner::appendSet(const Stickers::Set &set) { + for_const (auto row, _rows) { + if (row->id == set.id) { + return false; + } + } + rebuildAppendSet(set, countMaxNameWidth()); + return true; +} + +int StickersInner::countMaxNameWidth() const { + int namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(); + int namew = st::boxWideWidth - namex - st::contactsPadding.right() - st::contactsCheckPosition.x(); + if (_section == Section::Installed) { + namew -= qMax(qMax(qMax(_returnWidth, _removeWidth), _restoreWidth), _clearWidth); + } else { + namew -= st::stickersAddIcon.width() - st::defaultActiveButton.width; + } + return namew; +} + +void StickersInner::rebuildAppendSet(const Stickers::Set &set, int maxNameWidth) { + bool recent = false, installed = false, official = false, unread = false, disabled = false; + fillSetFlags(set, &recent, &installed, &official, &unread, &disabled); + if (_section == Section::Installed && disabled) { + return; + } + + DocumentData *sticker = nullptr; + int pixw = 0, pixh = 0; + fillSetCover(set, &sticker, &pixw, &pixh); + + QString title = fillSetTitle(set, maxNameWidth); + int count = fillSetCount(set); + + _rows.push_back(new StickerSetRow(set.id, sticker, count, title, installed, official, unread, disabled, recent, pixw, pixh)); + _animStartTimes.push_back(0); +} + +void StickersInner::fillSetCover(const Stickers::Set &set, DocumentData **outSticker, int *outWidth, int *outHeight) const { + if (set.stickers.isEmpty()) { + *outSticker = nullptr; + *outWidth = *outHeight = 0; + return; + } + auto sticker = *outSticker = set.stickers.front(); + + auto pixw = sticker->thumb->width(); + auto pixh = sticker->thumb->height(); + if (pixw > st::contactsPhotoSize) { + if (pixw > pixh) { + pixh = (pixh * st::contactsPhotoSize) / pixw; + pixw = st::contactsPhotoSize; + } else { + pixw = (pixw * st::contactsPhotoSize) / pixh; + pixh = st::contactsPhotoSize; + } + } else if (pixh > st::contactsPhotoSize) { + pixw = (pixw * st::contactsPhotoSize) / pixh; + pixh = st::contactsPhotoSize; + } + *outWidth = pixw; + *outHeight = pixh; +} + +int StickersInner::fillSetCount(const Stickers::Set &set) const { + int result = set.stickers.isEmpty() ? set.count : set.stickers.size(), added = 0; + if (set.id == Stickers::CloudRecentSetId) { + auto customIt = Global::StickerSets().constFind(Stickers::CustomSetId); + if (customIt != Global::StickerSets().cend()) { + added = customIt->stickers.size(); + for_const (auto &sticker, cGetRecentStickers()) { + if (customIt->stickers.indexOf(sticker.first) < 0) { + ++added; + } + } + } else { + added = cGetRecentStickers().size(); + } + } + return result + added; +} + +QString StickersInner::fillSetTitle(const Stickers::Set &set, int maxNameWidth) const { + auto result = set.title; + int32 titleWidth = st::contactsNameFont->width(result); + if (titleWidth > maxNameWidth) { + result = st::contactsNameFont->elided(result, maxNameWidth); + } + return result; +} + +void StickersInner::fillSetFlags(const Stickers::Set &set, bool *outRecent, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outDisabled) { + *outRecent = (set.id == Stickers::CloudRecentSetId); + *outInstalled = true; + *outOfficial = true; + *outUnread = false; + *outDisabled = false; + if (!*outRecent) { + *outInstalled = (set.flags & MTPDstickerSet::Flag::f_installed); + *outOfficial = (set.flags & MTPDstickerSet::Flag::f_official); + *outDisabled = (set.flags & MTPDstickerSet::Flag::f_archived); + if (_section == Section::Featured) { + *outUnread = _unreadSets.contains(set.id); + if (!*outUnread && (set.flags & MTPDstickerSet_ClientFlag::f_unread)) { + *outUnread = true; + _unreadSets.insert(set.id); + } + } + } +} + +void StickersInner::readFeaturedDone(const MTPBool &result) { + Local::writeFeaturedStickers(); + emit App::main()->stickersUpdated(); +} + +bool StickersInner::readFeaturedFail(const RPCError &error) { + if (MTP::isDefaultHandledError(error)) return false; + + int unreadCount = 0; + for_const (auto &set, Global::StickerSets()) { + if (!(set.flags & MTPDstickerSet::Flag::f_installed)) { + if (set.flags & MTPDstickerSet_ClientFlag::f_unread) { + ++unreadCount; + } + } + } + Global::SetFeaturedStickerSetsUnreadCount(unreadCount); + return true; +} + +Stickers::Order StickersInner::getOrder() const { + Stickers::Order result; result.reserve(_rows.size()); for (int32 i = 0, l = _rows.size(); i < l; ++i) { - if (_rows.at(i)->disabled) { - auto it = Global::StickerSets().constFind(_rows.at(i)->id); - if (it == Global::StickerSets().cend() || !(it->flags & MTPDstickerSet::Flag::f_official)) { - continue; - } + if (_rows.at(i)->disabled || _rows.at(i)->recent) { + continue; } result.push_back(_rows.at(i)->id); } return result; } -QVector StickersInner::getDisabledSets() const { - QVector result; +Stickers::Order StickersInner::getDisabledSets() const { + Stickers::Order result; result.reserve(_rows.size()); for (int32 i = 0, l = _rows.size(); i < l; ++i) { if (_rows.at(i)->disabled) { @@ -765,40 +1271,177 @@ StickersInner::~StickersInner() { clear(); } -StickersBox::StickersBox() : ItemListBox(st::boxScroll) -, _save(this, lang(lng_settings_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _reorderRequest(0) -, _topShadow(this, st::contactsAboutShadow) -, _bottomShadow(this) -, _scrollDelta(0) -, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.left()) -, _about(st::boxTextFont, lang(lng_stickers_reorder), _defaultOptions, _aboutWidth) -, _aboutHeight(st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom()) { - ItemListBox::init(&_inner, st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom(), st::boxTitleHeight + _aboutHeight); +} // namespace internal + +StickersBox::StickersBox(Section section) : ItemListBox(st::boxScroll) +, _section(section) +, _inner(section) +, _aboutWidth(st::boxWideWidth - 2 * st::stickersReorderPadding.top()) +, _about(st::boxTextFont, lang((section == Section::Archived) ? lng_stickers_packs_archived : lng_stickers_reorder), _defaultOptions, _aboutWidth) { + setup(); +} + +StickersBox::StickersBox(const Stickers::Order &archivedIds) : ItemListBox(st::boxScroll) +, _section(Section::ArchivedPart) +, _inner(archivedIds) +, _aboutWidth(st::boxWideWidth - 2 * st::stickersReorderPadding.top()) +, _about(st::boxTextFont, lang(lng_stickers_packs_archived), _defaultOptions, _aboutWidth) { + setup(); +} + +void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) { + _archivedRequestId = 0; + if (result.type() != mtpc_messages_archivedStickers) { + return; + } + + auto &stickers = result.c_messages_archivedStickers(); + auto &archived = Global::RefArchivedStickerSetsOrder(); + if (offsetId) { + auto index = archived.indexOf(offsetId); + if (index >= 0) { + archived = archived.mid(0, index + 1); + } + } else { + archived.clear(); + } + + bool addedSet = false; + auto &v = stickers.vsets.c_vector().v; + for_const (auto &stickerSet, v) { + if (stickerSet.type() != mtpc_stickerSetCovered || stickerSet.c_stickerSetCovered().vset.type() != mtpc_stickerSet) continue; + + if (auto set = Stickers::feedSet(stickerSet.c_stickerSetCovered().vset.c_stickerSet())) { + auto index = archived.indexOf(set->id); + if (archived.isEmpty() || index != archived.size() - 1) { + if (index < archived.size() - 1) { + archived.removeAt(index); + } + archived.push_back(set->id); + } + if (_section == Section::Archived) { + if (_inner->appendSet(*set)) { + addedSet = true; + if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { + App::api()->scheduleStickerSetRequest(set->id, set->access); + } + } + } + } + } + if (_section == Section::Installed && !archived.isEmpty()) { + Local::writeArchivedStickers(); + rebuildList(); + } else if (_section == Section::Archived) { + if (addedSet) { + _inner->updateSize(); + setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight))); + _inner->setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); + App::api()->requestStickerSets(); + } else { + _allArchivedLoaded = v.isEmpty() || (offsetId != 0); + } + } + checkLoadMoreArchived(); +} + +void StickersBox::setup() { + if (_section == Section::Installed) { + Local::readArchivedStickers(); + if (Global::ArchivedStickerSetsOrder().isEmpty()) { + _archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_long(0), MTP_int(kArchivedLimitFirstRequest)), rpcDone(&StickersBox::getArchivedDone, 0ULL)); + } + } else if (_section == Section::Archived) { + // Reload the archived list. + _archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_long(0), MTP_int(kArchivedLimitFirstRequest)), rpcDone(&StickersBox::getArchivedDone, 0ULL)); + + auto &sets = Global::StickerSets(); + for_const (auto setId, Global::ArchivedStickerSetsOrder()) { + auto it = sets.constFind(setId); + if (it != sets.cend()) { + if (it->stickers.isEmpty() && (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { + App::api()->scheduleStickerSetRequest(setId, it->access); + } + } + } + App::api()->requestStickerSets(); + } + + int bottomSkip = st::boxPadding.bottom(); + if (_section == Section::Installed) { + _aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom(); + _topShadow = new PlainShadow(this, st::contactsAboutShadow); + + _save = new BoxButton(this, lang(lng_settings_save), st::defaultBoxButton); + connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); + + _cancel = new BoxButton(this, lang(lng_cancel), st::cancelBoxButton); + connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + + _bottomShadow = new ScrollableBoxShadow(this); + bottomSkip = st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); + } else if (_section == Section::ArchivedPart) { + _aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom(); + _topShadow = new PlainShadow(this, st::contactsAboutShadow); + + _save = new BoxButton(this, lang(lng_box_ok), st::defaultBoxButton); + connect(_save, SIGNAL(clicked()), this, SLOT(onClose())); + } else if (_section == Section::Archived) { + _aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom(); + _topShadow = new PlainShadow(this, st::contactsAboutShadow); + } + ItemListBox::init(_inner, bottomSkip, st::boxTitleHeight + _aboutHeight); setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight))); connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated())); App::main()->updateStickers(); - connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(&_save, SIGNAL(clicked()), this, SLOT(onSave())); - - connect(&_inner, SIGNAL(checkDraggingScroll(int)), this, SLOT(onCheckDraggingScroll(int))); - connect(&_inner, SIGNAL(noDraggingScroll()), this, SLOT(onNoDraggingScroll())); + connect(_inner, SIGNAL(checkDraggingScroll(int)), this, SLOT(onCheckDraggingScroll(int))); + connect(_inner, SIGNAL(noDraggingScroll()), this, SLOT(onNoDraggingScroll())); connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer())); + connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); _scrollTimer.setSingleShot(false); - onStickersUpdated(); + rebuildList(); prepare(); } -int32 StickersBox::countHeight() const { - return st::boxTitleHeight + _aboutHeight + _inner.height() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom(); +void StickersBox::onScroll() { + checkLoadMoreArchived(); } -void StickersBox::disenableDone(const MTPBool & result, mtpRequestId req) { +void StickersBox::checkLoadMoreArchived() { + if (_section != Section::Archived) return; + + int scrollTop = _scroll.scrollTop(), scrollTopMax = _scroll.scrollTopMax(); + if (scrollTop + PreloadHeightsCount * _scroll.height() >= scrollTopMax) { + if (!_archivedRequestId && !_allArchivedLoaded) { + uint64 lastId = 0; + for (auto setId = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setId != e;) { + --setId; + auto it = Global::StickerSets().constFind(*setId); + if (it != Global::StickerSets().cend()) { + if (it->flags & MTPDstickerSet::Flag::f_archived) { + lastId = it->id; + break; + } + } + } + _archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId)); + } + } +} + +int32 StickersBox::countHeight() const { + int bottomSkip = st::boxPadding.bottom(); + if (_section == Section::Installed) { + bottomSkip = st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); + } + return st::boxTitleHeight + _aboutHeight + _inner->height() + bottomSkip; +} + +void StickersBox::disenableDone(const MTPmessages_StickerSetInstallResult &result, mtpRequestId req) { _disenableRequests.remove(req); if (_disenableRequests.isEmpty()) { saveOrder(); @@ -815,7 +1458,7 @@ bool StickersBox::disenableFail(const RPCError &error, mtpRequestId req) { } void StickersBox::saveOrder() { - QVector order = _inner.getOrder(); + auto order = _inner->getOrder(); if (order.size() > 1) { QVector mtpOrder; mtpOrder.reserve(order.size()); @@ -846,12 +1489,22 @@ void StickersBox::paintEvent(QPaintEvent *e) { Painter p(this); if (paint(p)) return; - paintTitle(p, lang(lng_stickers_packs)); + auto title = ([this]() { + if (_section == Section::Installed) { + return lang(lng_stickers_packs); + } else if (_section == Section::Featured) { + return lang(lng_stickers_featured); + } + return lang(lng_stickers_archived); + })(); + paintTitle(p, title); p.translate(0, st::boxTitleHeight); - p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg); - p.setPen(st::stickersReorderFg); - _about.draw(p, st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center); + if (_aboutHeight > 0) { + p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg); + p.setPen(st::stickersReorderFg); + _about.draw(p, st::stickersReorderPadding.top(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center); + } } void StickersBox::closePressed() { @@ -870,20 +1523,40 @@ void StickersBox::closePressed() { } } +StickersBox::~StickersBox() { + if (_section == Section::Archived) { + Local::writeArchivedStickers(); + } +} + void StickersBox::resizeEvent(QResizeEvent *e) { ItemListBox::resizeEvent(e); - _save.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save.height()); - _cancel.moveToRight(st::boxButtonPadding.right() + _save.width() + st::boxButtonPadding.left(), _save.y()); - _inner.resize(width(), _inner.height()); - _topShadow.setGeometry(0, st::boxTitleHeight + _aboutHeight, width(), st::lineWidth); - _bottomShadow.setGeometry(0, height() - st::boxButtonPadding.bottom() - _save.height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); - _inner.setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); + _inner->resize(width(), _inner->height()); + _inner->setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); + if (_topShadow) { + _topShadow->setGeometry(0, st::boxTitleHeight + _aboutHeight, width(), st::lineWidth); + } + if (_save) { + _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); + } + if (_cancel) { + _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); + _bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _save->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); + } } void StickersBox::onStickersUpdated() { - _inner.rebuild(); + if (_section == Section::Installed || _section == Section::Featured) { + rebuildList(); + } else { + _inner->updateRows(); + } +} + +void StickersBox::rebuildList() { + _inner->rebuild(); setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight))); - _inner.setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); + _inner->setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); } void StickersBox::onCheckDraggingScroll(int localY) { @@ -911,15 +1584,15 @@ void StickersBox::onScrollTimer() { } void StickersBox::onSave() { - if (!_inner.savingStart()) { + if (!_inner->savingStart()) { return; } - bool writeRecent = false; - RecentStickerPack &recent(cGetRecentStickers()); - Stickers::Sets &sets(Global::RefStickerSets()); + bool writeRecent = false, writeArchived = false; + auto &recent = cGetRecentStickers(); + auto &sets = Global::RefStickerSets(); - QVector reorder = _inner.getOrder(), disabled = _inner.getDisabledSets(); + auto reorder = _inner->getOrder(), disabled = _inner->getDisabledSets(); for (int32 i = 0, l = disabled.size(); i < l; ++i) { auto it = sets.find(disabled.at(i)); if (it != sets.cend()) { @@ -931,43 +1604,69 @@ void StickersBox::onSave() { ++i; } } - if (!(it->flags & MTPDstickerSet::Flag::f_disabled)) { + if (!(it->flags & MTPDstickerSet::Flag::f_archived)) { MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName)); if (it->flags & MTPDstickerSet::Flag::f_official) { _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolTrue()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); - it->flags |= MTPDstickerSet::Flag::f_disabled; + it->flags |= MTPDstickerSet::Flag::f_archived; + auto index = Global::RefArchivedStickerSetsOrder().indexOf(it->id); + if (index < 0) { + Global::RefArchivedStickerSetsOrder().push_front(it->id); + writeArchived = true; + } } else { _disenableRequests.insert(MTP::send(MTPmessages_UninstallStickerSet(setId), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); int removeIndex = Global::StickerSetsOrder().indexOf(it->id); if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex); - sets.erase(it); + if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured) && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) { + sets.erase(it); + } else { + if (it->flags & MTPDstickerSet::Flag::f_archived) { + writeArchived = true; + } + it->flags &= ~(MTPDstickerSet::Flag::f_installed | MTPDstickerSet::Flag::f_archived); + } } } } } - Stickers::Order &order(Global::RefStickerSetsOrder()); + + // Clear all installed flags, set only for sets from order. + for (auto &set : sets) { + if (!(set.flags & MTPDstickerSet::Flag::f_archived)) { + set.flags &= ~MTPDstickerSet::Flag::f_installed; + } + } + + auto &order(Global::RefStickerSetsOrder()); order.clear(); for (int i = 0, l = reorder.size(); i < l; ++i) { auto it = sets.find(reorder.at(i)); if (it != sets.cend()) { - if ((it->flags & MTPDstickerSet::Flag::f_disabled) && !disabled.contains(it->id)) { + if ((it->flags & MTPDstickerSet::Flag::f_archived) && !disabled.contains(it->id)) { MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName)); _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolFalse()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); - it->flags &= ~MTPDstickerSet::Flag::f_disabled; + it->flags &= ~MTPDstickerSet::Flag::f_archived; + writeArchived = true; } order.push_back(reorder.at(i)); + it->flags |= MTPDstickerSet::Flag::f_installed; } } for (auto it = sets.begin(); it != sets.cend();) { - if (it->id == Stickers::CustomSetId || it->id == Stickers::RecentSetId || order.contains(it->id)) { + if ((it->flags & MTPDstickerSet_ClientFlag::f_featured) + || (it->flags & MTPDstickerSet::Flag::f_installed) + || (it->flags & MTPDstickerSet::Flag::f_archived) + || (it->flags & MTPDstickerSet_ClientFlag::f_special)) { ++it; } else { it = sets.erase(it); } } - Local::writeStickers(); + Local::writeInstalledStickers(); if (writeRecent) Local::writeUserSettings(); + if (writeArchived) Local::writeArchivedStickers(); emit App::main()->stickersUpdated(); if (_disenableRequests.isEmpty()) { @@ -978,29 +1677,41 @@ void StickersBox::onSave() { } void StickersBox::hideAll() { - _save.hide(); - _cancel.hide(); - _topShadow.hide(); - _bottomShadow.hide(); + if (_topShadow) { + _topShadow->hide(); + } + if (_save) { + _save->hide(); + } + if (_cancel) { + _cancel->hide(); + _bottomShadow->hide(); + } ItemListBox::hideAll(); } void StickersBox::showAll() { - _save.show(); - _cancel.show(); - _topShadow.show(); - _bottomShadow.show(); + if (_topShadow) { + _topShadow->show(); + } + if (_save) { + _save->show(); + } + if (_cancel) { + _cancel->show(); + _bottomShadow->show(); + } ItemListBox::showAll(); } int32 stickerPacksCount(bool includeDisabledOfficial) { int32 result = 0; - const Stickers::Order &order(Global::StickerSetsOrder()); - const Stickers::Sets &sets(Global::StickerSets()); + auto &order = Global::StickerSetsOrder(); + auto &sets = Global::StickerSets(); for (int i = 0, l = order.size(); i < l; ++i) { auto it = sets.constFind(order.at(i)); if (it != sets.cend()) { - if (!(it->flags & MTPDstickerSet::Flag::f_disabled) || ((it->flags & MTPDstickerSet::Flag::f_official) && includeDisabledOfficial)) { + if (!(it->flags & MTPDstickerSet::Flag::f_archived) || ((it->flags & MTPDstickerSet::Flag::f_official) && includeDisabledOfficial)) { ++result; } } diff --git a/Telegram/SourceFiles/boxes/stickersetbox.h b/Telegram/SourceFiles/boxes/stickersetbox.h index fc2c9a513..cde1293f1 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.h +++ b/Telegram/SourceFiles/boxes/stickersetbox.h @@ -22,6 +22,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "abstractbox.h" +class ConfirmBox; + class StickerSetInner : public TWidget, public RPCSender { Q_OBJECT @@ -62,24 +64,26 @@ private: void gotSet(const MTPmessages_StickerSet &set); bool failedSet(const RPCError &error); - void installDone(const MTPBool &result); - bool installFailed(const RPCError &error); + void installDone(const MTPmessages_StickerSetInstallResult &result); + bool installFail(const RPCError &error); StickerPack _pack; StickersByEmojiMap _emoji; - bool _loaded; - uint64 _setId, _setAccess; + bool _loaded = false; + uint64 _setId = 0; + uint64 _setAccess = 0; QString _title, _setTitle, _setShortName; - int32 _setCount, _setHash; - MTPDstickerSet::Flags _setFlags; + int32 _setCount = 0; + int32 _setHash = 0; + MTPDstickerSet::Flags _setFlags = 0; - int32 _bottom; + int32 _bottom = 0; MTPInputStickerSet _input; - mtpRequestId _installRequest; + mtpRequestId _installRequest = 0; QTimer _previewTimer; - int32 _previewShown; + int32 _previewShown = -1; }; class StickerSetBox : public ScrollableBox, public RPCSender { @@ -93,7 +97,6 @@ public: void resizeEvent(QResizeEvent *e); public slots: - void onStickersUpdated(); void onAddStickers(); void onShareStickers(); @@ -101,122 +104,49 @@ public slots: void onScroll(); -signals: +private slots: + void onInstalled(uint64 id); +signals: void installed(uint64 id); protected: - void hideAll(); void showAll(); private: - StickerSetInner _inner; ScrollableBoxShadow _shadow; BoxButton _add, _share, _cancel, _done; QString _title; + }; -class StickersInner : public TWidget { - Q_OBJECT - -public: - - StickersInner(); - - void paintEvent(QPaintEvent *e); - void mousePressEvent(QMouseEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void mouseReleaseEvent(QMouseEvent *e); - - void rebuild(); - bool savingStart() { - if (_saving) return false; - _saving = true; - return true; - } - - QVector getOrder() const; - QVector getDisabledSets() const; - - void setVisibleScrollbar(int32 width); - - ~StickersInner(); - -signals: - - void checkDraggingScroll(int localY); - void noDraggingScroll(); - -public slots: - - void onUpdateSelected(); - -private: - - void step_shifting(uint64 ms, bool timer); - void paintRow(Painter &p, int32 index); - void clear(); - void setRemoveSel(int32 removeSel); - float64 aboveShadowOpacity() const; - - int32 _rowHeight; - struct StickerSetRow { - StickerSetRow(uint64 id, DocumentData *sticker, int32 count, const QString &title, bool official, bool disabled, int32 pixw, int32 pixh) : id(id) - , sticker(sticker) - , count(count) - , title(title) - , official(official) - , disabled(disabled) - , pixw(pixw) - , pixh(pixh) - , yadd(0, 0) { - } - uint64 id; - DocumentData *sticker; - int32 count; - QString title; - bool official, disabled; - int32 pixw, pixh; - anim::ivalue yadd; - }; - typedef QList StickerSetRows; - StickerSetRows _rows; - QList _animStartTimes; - uint64 _aboveShadowFadeStart; - anim::fvalue _aboveShadowFadeOpacity; - Animation _a_shifting; - - int32 _itemsTop; - - bool _saving; - - int32 _removeSel, _removeDown, _removeWidth, _returnWidth, _restoreWidth; - - QPoint _mouse; - int32 _selected; - QPoint _dragStart; - int32 _started, _dragging, _above; - - BoxShadow _aboveShadow; - - int32 _scrollbar; -}; +namespace internal { +class StickersInner; +} // namespace internal class StickersBox : public ItemListBox, public RPCSender { Q_OBJECT public: + enum class Section { + Installed, + Featured, + Archived, + ArchivedPart, + }; + StickersBox(Section section = Section::Installed); + StickersBox(const Stickers::Order &archivedIds); - StickersBox(); void resizeEvent(QResizeEvent *e); void paintEvent(QPaintEvent *e); void closePressed(); -public slots: + ~StickersBox(); +public slots: void onStickersUpdated(); void onCheckDraggingScroll(int localY); @@ -225,35 +155,181 @@ public slots: void onSave(); -protected: +private slots: + void onScroll(); +protected: void hideAll(); void showAll(); private: - + void setup(); int32 countHeight() const; + void rebuildList(); - void disenableDone(const MTPBool &result, mtpRequestId req); + void disenableDone(const MTPmessages_StickerSetInstallResult &result, mtpRequestId req); bool disenableFail(const RPCError &error, mtpRequestId req); void reorderDone(const MTPBool &result); bool reorderFail(const RPCError &result); void saveOrder(); - StickersInner _inner; - BoxButton _save, _cancel; + void checkLoadMoreArchived(); + void getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result); + + Section _section; + + ChildWidget _inner; + ChildWidget _save = { nullptr }; + ChildWidget _cancel = { nullptr }; QMap _disenableRequests; - mtpRequestId _reorderRequest; - PlainShadow _topShadow; - ScrollableBoxShadow _bottomShadow; + mtpRequestId _reorderRequest = 0; + ChildWidget _topShadow = { nullptr }; + ChildWidget _bottomShadow = { nullptr }; QTimer _scrollTimer; - int32 _scrollDelta; + int32 _scrollDelta = 0; - int32 _aboutWidth; + int _aboutWidth = 0; Text _about; - int32 _aboutHeight; + int _aboutHeight = 0; + + mtpRequestId _archivedRequestId = 0; + bool _allArchivedLoaded = false; }; int32 stickerPacksCount(bool includeDisabledOfficial = false); + +namespace internal { + +class StickersInner : public TWidget, public RPCSender { + Q_OBJECT + +public: + using Section = StickersBox::Section; + StickersInner(Section section); + StickersInner(const Stickers::Order &archivedIds); + + void rebuild(); + void updateSize(); + void updateRows(); // refresh only pack cover stickers + bool appendSet(const Stickers::Set &set); + bool savingStart() { + if (_saving) return false; + _saving = true; + return true; + } + + Stickers::Order getOrder() const; + Stickers::Order getDisabledSets() const; + + void setVisibleScrollbar(int32 width); + + ~StickersInner(); + +protected: + void paintEvent(QPaintEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void leaveEvent(QEvent *e) override; + +signals: + void checkDraggingScroll(int localY); + void noDraggingScroll(); + +public slots: + void onUpdateSelected(); + void onClearRecent(); + void onClearBoxDestroyed(QObject *box); + +private: + void setup(); + void paintButton(Painter &p, int y, bool selected, const QString &text, int badgeCounter) const; + + void step_shifting(uint64 ms, bool timer); + void paintRow(Painter &p, int32 index); + void clear(); + void setActionSel(int32 actionSel); + float64 aboveShadowOpacity() const; + + void installSet(uint64 setId); + void installDone(const MTPmessages_StickerSetInstallResult &result); + bool installFail(uint64 setId, const RPCError &error); + void readFeaturedDone(const MTPBool &result); + bool readFeaturedFail(const RPCError &error); + + Section _section; + Stickers::Order _archivedIds; + + int32 _rowHeight; + struct StickerSetRow { + StickerSetRow(uint64 id, DocumentData *sticker, int32 count, const QString &title, bool installed, bool official, bool unread, bool disabled, bool recent, int32 pixw, int32 pixh) : id(id) + , sticker(sticker) + , count(count) + , title(title) + , installed(installed) + , official(official) + , unread(unread) + , disabled(disabled) + , recent(recent) + , pixw(pixw) + , pixh(pixh) + , yadd(0, 0) { + } + uint64 id; + DocumentData *sticker; + int32 count; + QString title; + bool installed, official, unread, disabled, recent; + int32 pixw, pixh; + anim::ivalue yadd; + }; + using StickerSetRows = QList; + + void rebuildAppendSet(const Stickers::Set &set, int maxNameWidth); + void fillSetCover(const Stickers::Set &set, DocumentData **outSticker, int *outWidth, int *outHeight) const; + int fillSetCount(const Stickers::Set &set) const; + QString fillSetTitle(const Stickers::Set &set, int maxNameWidth) const; + void fillSetFlags(const Stickers::Set &set, bool *outRecent, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outDisabled); + + int countMaxNameWidth() const; + + StickerSetRows _rows; + QList _animStartTimes; + uint64 _aboveShadowFadeStart = 0; + anim::fvalue _aboveShadowFadeOpacity = { 0., 0. }; + Animation _a_shifting; + + int32 _itemsTop; + + bool _saving = false; + + int _actionSel = -1; + int _actionDown = -1; + + int _clearWidth, _removeWidth, _returnWidth, _restoreWidth; + + ConfirmBox *_clearBox = nullptr; + + int _buttonHeight = 0; + bool _hasFeaturedButton = false; + bool _hasArchivedButton = false; + + // Remember all the unread set ids to display unread dots. + OrderedSet _unreadSets; + + QPoint _mouse; + int _selected = -3; // -2 - featured stickers button, -1 - archived stickers button + int _pressed = -2; + QPoint _dragStart; + int _started = -1; + int _dragging = -1; + int _above = -1; + + BoxShadow _aboveShadow; + + int32 _scrollbar = 0; +}; + +} // namespace internal diff --git a/Telegram/SourceFiles/boxes/usernamebox.cpp b/Telegram/SourceFiles/boxes/usernamebox.cpp index 7d7bb157f..3070baf2e 100644 --- a/Telegram/SourceFiles/boxes/usernamebox.cpp +++ b/Telegram/SourceFiles/boxes/usernamebox.cpp @@ -83,21 +83,18 @@ void UsernameBox::paintEvent(QPaintEvent *e) { paintTitle(p, lang(lng_username_title)); + p.setFont(st::boxTextFont); if (!_copiedTextLink.isEmpty()) { p.setPen(st::usernameDefaultFg); - p.setFont(st::boxTextFont); p.drawTextLeft(st::usernamePadding.left(), _username.y() + _username.height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _copiedTextLink); } else if (!_errorText.isEmpty()) { p.setPen(st::setErrColor); - p.setFont(st::boxTextFont); p.drawTextLeft(st::usernamePadding.left(), _username.y() + _username.height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _errorText); } else if (!_goodText.isEmpty()) { p.setPen(st::setGoodColor); - p.setFont(st::boxTextFont); p.drawTextLeft(st::usernamePadding.left(), _username.y() + _username.height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _goodText); } else { p.setPen(st::usernameDefaultFg); - p.setFont(st::boxTextFont); p.drawTextLeft(st::usernamePadding.left(), _username.y() + _username.height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), lang(lng_username_choose)); } p.setPen(st::black); diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index 23b34fb76..3726fa358 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -24,6 +24,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "lang.h" #include "pspecific.h" #include "boxes/confirmbox.h" +#include "core/qthelp_regex.h" +#include "core/qthelp_url.h" QString UrlClickHandler::copyToClipboardContextItemText() const { return lang(isEmail() ? lng_context_copy_email : lng_context_copy_link); @@ -31,23 +33,28 @@ QString UrlClickHandler::copyToClipboardContextItemText() const { namespace { -QString tryConvertUrlToLocal(const QString &url) { - QRegularExpressionMatch telegramMeUser = QRegularExpression(qsl("^https?://telegram\\.me/([a-zA-Z0-9\\.\\_]+)(/?\\?|/?$|/(\\d+)/?(?:\\?|$))"), QRegularExpression::CaseInsensitiveOption).match(url); - QRegularExpressionMatch telegramMeGroup = QRegularExpression(qsl("^https?://telegram\\.me/joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url); - QRegularExpressionMatch telegramMeStickers = QRegularExpression(qsl("^https?://telegram\\.me/addstickers/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url); - QRegularExpressionMatch telegramMeShareUrl = QRegularExpression(qsl("^https?://telegram\\.me/share/url\\?(.+)$"), QRegularExpression::CaseInsensitiveOption).match(url); - if (telegramMeGroup.hasMatch()) { - return qsl("tg://join?invite=") + myUrlEncode(telegramMeGroup.captured(1)); - } else if (telegramMeStickers.hasMatch()) { - return qsl("tg://addstickers?set=") + myUrlEncode(telegramMeStickers.captured(1)); - } else if (telegramMeShareUrl.hasMatch()) { - return qsl("tg://msg_url?") + telegramMeShareUrl.captured(1); - } else if (telegramMeUser.hasMatch()) { - QString params = url.mid(telegramMeUser.captured(0).size()), postParam; - if (QRegularExpression(qsl("^/\\d+/?(?:\\?|$)")).match(telegramMeUser.captured(2)).hasMatch()) { - postParam = qsl("&post=") + telegramMeUser.captured(3); +QString tryConvertUrlToLocal(QString url) { + if (url.size() > 8192) url = url.mid(0, 8192); + + using namespace qthelp; + auto matchOptions = RegExOption::CaseInsensitive; + if (auto telegramMeMatch = regex_match(qsl("https?://telegram\\.me/(.+)$"), url, matchOptions)) { + auto query = telegramMeMatch->capturedRef(1); + if (auto joinChatMatch = regex_match(qsl("^joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), query, matchOptions)) { + return qsl("tg://join?invite=") + url_encode(joinChatMatch->captured(1)); + } else if (auto stickerSetMatch = regex_match(qsl("^addstickers/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), query, matchOptions)) { + return qsl("tg://addstickers?set=") + url_encode(stickerSetMatch->captured(1)); + } else if (auto shareUrlMatch = regex_match(qsl("^share/url/?\\?(.+)$"), query, matchOptions)) { + return qsl("tg://msg_url?") + shareUrlMatch->captured(1); + } else if (auto confirmPhoneMatch = regex_match(qsl("^confirmphone/?\\?(.+)"), query, matchOptions)) { + return qsl("tg://confirmphone?") + confirmPhoneMatch->captured(1); + } else if (auto usernameMatch = regex_match(qsl("^([a-zA-Z0-9\\.\\_]+)(/?\\?|/?$|/(\\d+)/?(?:\\?|$))"), query, matchOptions)) { + QString params = url.mid(usernameMatch->captured(0).size()), postParam; + if (auto postMatch = regex_match(qsl("^/\\d+/?(?:\\?|$)"), usernameMatch->captured(2))) { + postParam = qsl("&post=") + usernameMatch->captured(3); + } + return qsl("tg://resolve/?domain=") + url_encode(usernameMatch->captured(1)) + postParam + (params.isEmpty() ? QString() : '&' + params); } - return qsl("tg://resolve/?domain=") + myUrlEncode(telegramMeUser.captured(1)) + postParam + (params.isEmpty() ? QString() : '&' + params); } return url; } diff --git a/Telegram/SourceFiles/core/qthelp_regex.h b/Telegram/SourceFiles/core/qthelp_regex.h new file mode 100644 index 000000000..6ecd20a4f --- /dev/null +++ b/Telegram/SourceFiles/core/qthelp_regex.h @@ -0,0 +1,71 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +namespace qthelp { + +class RegularExpressionMatch { +public: + RegularExpressionMatch(QRegularExpressionMatch &&match) : data_(std_::move(match)) { + } + RegularExpressionMatch(RegularExpressionMatch &&other) : data_(std_::move(other.data_)) { + } + QRegularExpressionMatch *operator->() { + return &data_; + } + const QRegularExpressionMatch *operator->() const { + return &data_; + } + explicit operator bool() const { + return data_.hasMatch(); + } + +private: + QRegularExpressionMatch data_; + +}; + +enum class RegExOption { + None = QRegularExpression::NoPatternOption, + CaseInsensitive = QRegularExpression::CaseInsensitiveOption, + DotMatchesEverything = QRegularExpression::DotMatchesEverythingOption, + Multiline = QRegularExpression::MultilineOption, + ExtendedSyntax = QRegularExpression::ExtendedPatternSyntaxOption, + InvertedGreediness = QRegularExpression::InvertedGreedinessOption, + DontCapture = QRegularExpression::DontCaptureOption, + UseUnicodeProperties = QRegularExpression::UseUnicodePropertiesOption, + OptimizeOnFirstUsage = QRegularExpression::OptimizeOnFirstUsageOption, + DontAutomaticallyOptimize = QRegularExpression::DontAutomaticallyOptimizeOption, +}; +Q_DECLARE_FLAGS(RegExOptions, RegExOption); +Q_DECLARE_OPERATORS_FOR_FLAGS(RegExOptions); + +inline RegularExpressionMatch regex_match(const QString &string, const QString &subject, RegExOptions options = 0) { + auto qtOptions = QRegularExpression::PatternOptions(static_cast(options)); + return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subject)); +} + +inline RegularExpressionMatch regex_match(const QString &string, const QStringRef &subjectRef, RegExOptions options = 0) { + auto qtOptions = QRegularExpression::PatternOptions(static_cast(options)); + return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subjectRef)); +} + +} // namespace qthelp diff --git a/Telegram/SourceFiles/core/qthelp_url.cpp b/Telegram/SourceFiles/core/qthelp_url.cpp new file mode 100644 index 000000000..8acd3791d --- /dev/null +++ b/Telegram/SourceFiles/core/qthelp_url.cpp @@ -0,0 +1,52 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "core/qthelp_url.h" + +namespace qthelp { + +QMap url_parse_params(const QString ¶ms, UrlParamNameTransform transform) { + QMap result; + + auto transformParamName = [transform](const QString &name) { + if (transform == UrlParamNameTransform::ToLower) { + return name.toLower(); + } + return name; + }; + + auto paramsList = params.split('&'); + for_const (auto ¶m, paramsList) { + // Skip params without a name (starting with '='). + if (auto separatorPosition = param.indexOf('=')) { + auto paramName = param; + auto paramValue = QString(); + if (separatorPosition > 0) { + paramName = param.mid(0, separatorPosition); + paramValue = url_decode(param.mid(separatorPosition + 1)); + } + result.insert(transformParamName(paramName), paramValue); + } + } + return result; +} + +} // namespace qthelp diff --git a/Telegram/SourceFiles/core/qthelp_url.h b/Telegram/SourceFiles/core/qthelp_url.h new file mode 100644 index 000000000..c6a904494 --- /dev/null +++ b/Telegram/SourceFiles/core/qthelp_url.h @@ -0,0 +1,40 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +namespace qthelp { + +inline QString url_encode(const QString &part) { + return QString::fromLatin1(QUrl::toPercentEncoding(part)); +} + +inline QString url_decode(const QString &encoded) { + return QUrl::fromPercentEncoding(encoded.toUtf8()); +} + +enum class UrlParamNameTransform { + NoTransform, + ToLower, +}; +// Parses a string like "p1=v1&p2=v2&..&pn=vn" to a map. +QMap url_parse_params(const QString ¶ms, UrlParamNameTransform transform = UrlParamNameTransform::NoTransform); + +} // namespace qthelp diff --git a/Telegram/SourceFiles/core/vector_of_moveable.h b/Telegram/SourceFiles/core/vector_of_moveable.h index 412d87b35..608bb0796 100644 --- a/Telegram/SourceFiles/core/vector_of_moveable.h +++ b/Telegram/SourceFiles/core/vector_of_moveable.h @@ -141,7 +141,10 @@ private: void reallocate(int newCapacity) { auto newPlainData = operator new[](newCapacity * sizeof(T)); for (int i = 0; i < _size; ++i) { - *(reinterpret_cast(newPlainData) + i) = std_::move(*(data() + i)); + auto oldLocation = data() + i; + auto newLocation = reinterpret_cast(newPlainData) + i; + new (newLocation) T(std_::move(*oldLocation)); + oldLocation->~T(); } std::swap(_plaindata, newPlainData); _capacity = newCapacity; diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index ad8fb384b..d0cb462d6 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #define BETA_VERSION_MACRO (0ULL) -constexpr int AppVersion = 9060; -constexpr str_const AppVersionStr = "0.9.60"; -constexpr bool AppAlphaVersion = true; +constexpr int AppVersion = 10000; +constexpr str_const AppVersionStr = "0.10"; +constexpr bool AppAlphaVersion = false; constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO; diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index daae49132..ce4681df0 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -29,7 +29,6 @@ dialogsUnreadBgActive: #ffffff; dialogsUnreadBgMutedActive: #d3e2ee; dialogsUnreadFont: font(12px bold); dialogsUnreadHeight: 19px; -dialogsUnreadTop: 1px; dialogsUnreadPadding: 5px; dialogsBg: windowBg; @@ -86,8 +85,8 @@ dialogsTextStyleActive: textStyle(dialogsTextStyle) { linkFgDown: dialogsTextFgActive; } dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) { - linkFg: #ffd6d6; - linkFgDown: #ffd6d6; + linkFg: #c6e1f7; + linkFgDown: #c6e1f7; } dialogsNewChatIcon: icon { diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index 8e8843ac6..cb19698b9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -33,11 +33,16 @@ namespace Layout { namespace { +// Show all dates that are in the last 20 hours in time format. +constexpr int kRecentlyInSeconds = 20 * 3600; + void paintRowDate(Painter &p, const QDateTime &date, QRect &rectForName, bool active) { QDateTime now(QDateTime::currentDateTime()), lastTime(date); QDate nowDate(now.date()), lastDate(lastTime.date()); QString dt; - if (lastDate == nowDate) { + bool wasSameDay = (lastDate == nowDate); + bool wasRecently = qAbs(lastTime.secsTo(now)) < kRecentlyInSeconds; + if (wasSameDay || wasRecently) { dt = lastTime.toString(cTimeFormat()); } else if (lastDate.year() == nowDate.year() && lastDate.weekNumber() == nowDate.weekNumber()) { dt = langDayOfWeek(lastDate); @@ -222,7 +227,7 @@ void paintUnreadCount(Painter &p, const QString &text, int x, int y, const Unrea p.setFont(st.font); p.setPen(st.active ? st::dialogsUnreadFgActive : st::dialogsUnreadFg); - p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dialogsUnreadTop + st.font->ascent, text); + p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + (unreadRectHeight - st.font->height) / 2 + st.font->ascent, text); } void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) { @@ -258,7 +263,7 @@ void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool sele auto counter = QString::number(unreadCount); auto mutedCounter = history->mute(); int unreadRight = w - st::dialogsPadding.x(); - int unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - st::dialogsUnreadTop; + int unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2; int unreadWidth = 0; UnreadBadgeStyle st; @@ -297,7 +302,7 @@ void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool o int unreadTop = (st::dialogsImportantBarHeight - st::dialogsUnreadHeight) / 2; bool mutedHidden = (current == Dialogs::Mode::Important); QString text = mutedHidden ? qsl("Show all chats") : qsl("Hide muted chats"); - int textBaseline = unreadTop + st::dialogsUnreadTop + st::dialogsUnreadFont->ascent; + int textBaseline = unreadTop + (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2 + st::dialogsUnreadFont->ascent; p.drawText(st::dialogsPadding.x(), textBaseline, text); if (mutedHidden) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.h b/Telegram/SourceFiles/dialogs/dialogs_layout.h index b0e5bd8b1..f083f062f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.h +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.h @@ -38,6 +38,8 @@ void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool o enum UnreadBadgeSize { UnreadBadgeInDialogs = 0, UnreadBadgeInHistoryToDown, + UnreadBadgeInStickersPanel, + UnreadBadgeInStickersBox, UnreadBadgeSizesCount }; diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index b96b1a1d3..72c1cf737 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/stickersetbox.h" #include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_layout_item.h" +#include "dialogs/dialogs_layout.h" #include "historywidget.h" #include "localstorage.h" #include "lang.h" @@ -713,7 +714,7 @@ void EmojiColorPicker::drawVariant(Painter &p, int variant) { } EmojiPanInner::EmojiPanInner() : TWidget() -, _maxHeight(int(st::emojiPanMaxHeight)) +, _maxHeight(int(st::emojiPanMaxHeight) - st::rbEmoji.height) , _a_selected(animation(this, &EmojiPanInner::step_selected)) , _top(0) , _selected(-1) @@ -1229,7 +1230,7 @@ StickerPanInner::StickerPanInner() : TWidget() , _pressedSel(-1) , _settings(this, lang(lng_stickers_you_have)) , _previewShown(false) { - setMaxHeight(st::emojiPanMaxHeight); + setMaxHeight(st::emojiPanMaxHeight - st::rbEmoji.height); setMouseTracking(true); setFocusPolicy(Qt::NoFocus); @@ -1508,7 +1509,7 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) { break; } } - Stickers::Sets &sets(Global::RefStickerSets()); + auto &sets = Global::RefStickerSets(); auto it = sets.find(Stickers::CustomSetId); if (it != sets.cend()) { for (int32 i = 0, l = it->stickers.size(); i < l; ++i) { @@ -1517,7 +1518,7 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) { if (it->stickers.isEmpty()) { sets.erase(it); } - Local::writeStickers(); + Local::writeInstalledStickers(); refresh = true; break; } @@ -1628,8 +1629,8 @@ void StickerPanInner::hideFinish(bool completely) { void StickerPanInner::refreshStickers() { clearSelection(true); - const Stickers::Sets &sets(Global::StickerSets()); - _sets.clear(); _sets.reserve(sets.size() + 1); + _sets.clear(); + _sets.reserve(Global::StickerSetsOrder().size() + 1); refreshRecentStickers(false); for (auto i = Global::StickerSetsOrder().cbegin(), e = Global::StickerSetsOrder().cend(); i != e; ++i) { @@ -2085,9 +2086,9 @@ bool StickerPanInner::ui_isInlineItemBeingChosen() { } void StickerPanInner::appendSet(uint64 setId) { - const Stickers::Sets &sets(Global::StickerSets()); + auto &sets = Global::StickerSets(); auto it = sets.constFind(setId); - if (it == sets.cend() || (it->flags & MTPDstickerSet::Flag::f_disabled) || it->stickers.isEmpty()) return; + if (it == sets.cend() || (it->flags & MTPDstickerSet::Flag::f_archived) || it->stickers.isEmpty()) return; StickerPack pack; pack.reserve(it->stickers.size()); @@ -2110,37 +2111,49 @@ void StickerPanInner::refreshRecent() { void StickerPanInner::refreshRecentStickers(bool performResize) { _custom.clear(); clearSelection(true); - auto customIt = Global::StickerSets().constFind(Stickers::CustomSetId); - if (cGetRecentStickers().isEmpty() && (customIt == Global::StickerSets().cend() || customIt->stickers.isEmpty())) { + auto &sets = Global::StickerSets(); + auto &recent = cGetRecentStickers(); + auto customIt = sets.constFind(Stickers::CustomSetId); + auto cloudIt = sets.constFind(Stickers::CloudRecentSetId); + if (recent.isEmpty() + && (customIt == sets.cend() || customIt->stickers.isEmpty()) + && (cloudIt == sets.cend() || cloudIt->stickers.isEmpty())) { if (!_sets.isEmpty() && _sets.at(0).id == Stickers::RecentSetId) { _sets.pop_front(); } } else { - StickerPack recent; - int32 customCnt = (customIt == Global::StickerSets().cend() ? 0 : customIt->stickers.size()); - QMap recentOnly; - recent.reserve(cGetRecentStickers().size() + customCnt); - _custom.reserve(cGetRecentStickers().size() + customCnt); - for (int32 i = 0, l = cGetRecentStickers().size(); i < l; ++i) { - DocumentData *s = cGetRecentStickers().at(i).first; - recent.push_back(s); - recentOnly.insert(s, true); + StickerPack recentPack; + int customCnt = (customIt == sets.cend()) ? 0 : customIt->stickers.size(); + int cloudCnt = (cloudIt == sets.cend()) ? 0 : cloudIt->stickers.size(); + recentPack.reserve(cloudCnt + recent.size() + customCnt); + _custom.reserve(cloudCnt + recent.size() + customCnt); + if (cloudCnt > 0) { + for_const (auto sticker, cloudIt->stickers) { + recentPack.push_back(sticker); + _custom.push_back(false); + } + } + for_const (auto &recentSticker, recent) { + auto sticker = recentSticker.first; + recentPack.push_back(sticker); _custom.push_back(false); } - for (int32 i = 0; i < customCnt; ++i) { - DocumentData *s = customIt->stickers.at(i); - if (recentOnly.contains(s)) { - _custom[recent.indexOf(s)] = true; - } else { - recent.push_back(s); - _custom.push_back(true); + if (customCnt > 0) { + for_const (auto &sticker, customIt->stickers) { + auto index = recentPack.indexOf(sticker); + if (index >= cloudCnt) { + _custom[index] = true; // mark stickers from recent as custom + } else { + recentPack.push_back(sticker); + _custom.push_back(true); + } } } if (_sets.isEmpty() || _sets.at(0).id != Stickers::RecentSetId) { - _sets.push_back(DisplayedSet(Stickers::RecentSetId, MTPDstickerSet::Flag::f_official, lang(lng_emoji_category0), recent.size() * 2, recent)); + _sets.push_back(DisplayedSet(Stickers::RecentSetId, MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special, lang(lng_recent_stickers), recentPack.size() * 2, recentPack)); } else { - _sets[0].pack = recent; - _sets[0].hovers.resize(recent.size() * 2); + _sets[0].pack = recentPack; + _sets[0].hovers.resize(recentPack.size() * 2); } } @@ -2829,6 +2842,20 @@ void EmojiPan::onSaveConfigDelayed(int32 delay) { _saveConfigTimer.start(delay); } +void EmojiPan::paintStickerSettingsIcon(Painter &p) const { + int settingsLeft = _iconsLeft + 7 * st::rbEmoji.width; + p.drawSpriteLeft(settingsLeft + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::stickersSettings); + if (auto unread = Global::FeaturedStickerSetsUnreadCount()) { + Dialogs::Layout::UnreadBadgeStyle unreadSt; + unreadSt.sizeId = Dialogs::Layout::UnreadBadgeInStickersPanel; + unreadSt.size = st::stickersSettingsUnreadSize; + int unreadRight = settingsLeft + st::rbEmoji.width - st::stickersSettingsUnreadPosition.x(); + if (rtl()) unreadRight = width() - unreadRight; + int unreadTop = _iconsTop + st::stickersSettingsUnreadPosition.y(); + Dialogs::Layout::paintUnreadCount(p, QString::number(unread), unreadRight, unreadTop, unreadSt); + } +} + void EmojiPan::paintEvent(QPaintEvent *e) { Painter p(this); @@ -2846,7 +2873,7 @@ void EmojiPan::paintEvent(QPaintEvent *e) { p.fillRect(myrtlrect(r.x() + r.width() - st::emojiScroll.width, r.y(), st::emojiScroll.width, e_scroll.height()), st::white->b); if (_stickersShown && s_inner.showSectionIcons()) { p.fillRect(r.left(), _iconsTop, r.width(), st::rbEmoji.height, st::emojiPanCategories); - p.drawSpriteLeft(_iconsLeft + 7 * st::rbEmoji.width + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::stickersSettings); + paintStickerSettingsIcon(p); if (!_icons.isEmpty()) { int32 x = _iconsLeft, i = 0, selxrel = _iconsLeft + _iconSelX.current(), selx = selxrel - _iconsX.current(); @@ -3093,6 +3120,7 @@ void EmojiPan::refreshStickers() { if (!_stickersShown) { s_inner.preloadImages(); } + update(); } void EmojiPan::refreshSavedGifs() { @@ -3228,7 +3256,7 @@ void EmojiPan::step_icons(uint64 ms, bool timer) { } if (_iconsStartAnim) { - float64 dt = (ms - _iconsStartAnim) / st::stickerIconMove; + float64 dt = (ms - _iconsStartAnim) / float64(st::stickerIconMove); if (dt >= 1) { _iconsStartAnim = 0; _iconsX.finish(); @@ -3584,7 +3612,7 @@ void EmojiPan::onSwitch() { } else { if (cShowingSavedGifs() && cSavedGifs().isEmpty()) { s_inner.showStickerSet(Stickers::DefaultSetId); - } else if (!cShowingSavedGifs() && !cSavedGifs().isEmpty() && Global::StickerSets().isEmpty()) { + } else if (!cShowingSavedGifs() && !cSavedGifs().isEmpty() && Global::StickerSetsOrder().isEmpty()) { s_inner.showStickerSet(Stickers::NoneSetId); } else { s_inner.updateShowingSavedGifs(); @@ -3623,8 +3651,9 @@ void EmojiPan::onSwitch() { } void EmojiPan::onRemoveSet(quint64 setId) { - auto it = Global::StickerSets().constFind(setId); - if (it != Global::StickerSets().cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { + auto &sets = Global::StickerSets(); + auto it = sets.constFind(setId); + if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { _removingSetId = it->id; ConfirmBox *box = new ConfirmBox(lng_stickers_remove_pack(lt_sticker_pack, it->title), lang(lng_box_remove)); connect(box, SIGNAL(confirmed()), this, SLOT(onRemoveSetSure())); @@ -3635,8 +3664,9 @@ void EmojiPan::onRemoveSet(quint64 setId) { void EmojiPan::onRemoveSetSure() { Ui::hideLayer(); - auto it = Global::RefStickerSets().find(_removingSetId); - if (it != Global::RefStickerSets().cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { + auto &sets = Global::RefStickerSets(); + auto it = sets.find(_removingSetId); + if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { if (it->id && it->access) { MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))); } else if (!it->shortName.isEmpty()) { @@ -3652,11 +3682,14 @@ void EmojiPan::onRemoveSetSure() { ++i; } } - Global::RefStickerSets().erase(it); + it->flags &= ~MTPDstickerSet::Flag::f_installed; + if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured) && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) { + sets.erase(it); + } int removeIndex = Global::StickerSetsOrder().indexOf(_removingSetId); if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex); refreshStickers(); - Local::writeStickers(); + Local::writeInstalledStickers(); if (writeRecent) Local::writeUserSettings(); } _removingSetId = 0; diff --git a/Telegram/SourceFiles/dropdown.h b/Telegram/SourceFiles/dropdown.h index 32faf3568..dfd81a7cf 100644 --- a/Telegram/SourceFiles/dropdown.h +++ b/Telegram/SourceFiles/dropdown.h @@ -656,6 +656,7 @@ signals: void updateStickers(); private: + void paintStickerSettingsIcon(Painter &p) const; void validateSelectedIcon(bool animated = false); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index b0f0a17b2..3f82c3d85 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org Q_DECLARE_METATYPE(ClickHandlerPtr); Q_DECLARE_METATYPE(Qt::MouseButton); +Q_DECLARE_METATYPE(Ui::ShowWay); namespace App { @@ -253,13 +254,14 @@ void showPeerOverview(const PeerId &peer, MediaOverviewType type) { } } -void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) { - if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, back); +void showPeerHistory(const PeerId &peer, MsgId msgId, ShowWay way) { + if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, way); } -void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) { +void showPeerHistoryAsync(const PeerId &peer, MsgId msgId, ShowWay way) { if (MainWidget *m = App::main()) { - QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId)); + qRegisterMetaType(); + QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId), Q_ARG(Ui::ShowWay, way)); } } @@ -518,6 +520,45 @@ DefineVar(Sandbox, ConnectionProxy, PreLaunchProxy); } // namespace Sandbox +namespace Stickers { + +Set *feedSet(const MTPDstickerSet &set) { + MTPDstickerSet::Flags flags = 0; + + auto &sets = Global::RefStickerSets(); + auto it = sets.find(set.vid.v); + auto title = stickerSetTitle(set); + if (it == sets.cend()) { + it = sets.insert(set.vid.v, Stickers::Set(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | MTPDstickerSet_ClientFlag::f_not_loaded)); + } else { + it->access = set.vaccess_hash.v; + it->title = title; + it->shortName = qs(set.vshort_name); + flags = it->flags; + auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special); + it->flags = set.vflags.v | clientFlags; + if (it->count != set.vcount.v || it->hash != set.vhash.v || it->emoji.isEmpty()) { + it->count = set.vcount.v; + it->hash = set.vhash.v; + it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; // need to request this set + } + } + auto changedFlags = (flags ^ it->flags); + if (changedFlags & MTPDstickerSet::Flag::f_archived) { + auto index = Global::ArchivedStickerSetsOrder().indexOf(it->id); + if (it->flags & MTPDstickerSet::Flag::f_archived) { + if (index < 0) { + Global::RefArchivedStickerSetsOrder().push_front(it->id); + } + } else if (index >= 0) { + Global::RefArchivedStickerSetsOrder().removeAt(index); + } + } + return &it.value(); +} + +} // namespace Stickers + namespace Global { namespace internal { @@ -557,6 +598,7 @@ struct Data { int32 PushChatLimit = 2; int32 SavedGifsLimit = 200; int32 EditTimeLimit = 172800; + int32 StickersRecentLimit = 30; HiddenPinnedMessagesMap HiddenPinnedMessages; @@ -565,6 +607,11 @@ struct Data { Stickers::Sets StickerSets; Stickers::Order StickerSetsOrder; uint64 LastStickersUpdate = 0; + uint64 LastRecentStickersUpdate = 0; + Stickers::Order FeaturedStickerSetsOrder; + int FeaturedStickerSetsUnreadCount = 0; + uint64 LastFeaturedStickersUpdate = 0; + Stickers::Order ArchivedStickerSetsOrder; MTP::DcOptions DcOptions; @@ -628,6 +675,7 @@ DefineVar(Global, int32, PushChatPeriod); DefineVar(Global, int32, PushChatLimit); DefineVar(Global, int32, SavedGifsLimit); DefineVar(Global, int32, EditTimeLimit); +DefineVar(Global, int32, StickersRecentLimit); DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages); @@ -636,6 +684,11 @@ DefineRefVar(Global, PendingItemsMap, PendingRepaintItems); DefineVar(Global, Stickers::Sets, StickerSets); DefineVar(Global, Stickers::Order, StickerSetsOrder); DefineVar(Global, uint64, LastStickersUpdate); +DefineVar(Global, uint64, LastRecentStickersUpdate); +DefineVar(Global, Stickers::Order, FeaturedStickerSetsOrder); +DefineVar(Global, int, FeaturedStickerSetsUnreadCount); +DefineVar(Global, uint64, LastFeaturedStickersUpdate); +DefineVar(Global, Stickers::Order, ArchivedStickerSetsOrder); DefineVar(Global, MTP::DcOptions, DcOptions); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 4a14f5694..364dc28da 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -83,22 +83,27 @@ inline void showPeerOverview(const History *history, MediaOverviewType type) { showPeerOverview(history->peer->id, type); } -void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false); -inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) { - showPeerHistory(peer->id, msgId, back); +enum class ShowWay { + ClearStack, + Forward, + Backward, +}; +void showPeerHistory(const PeerId &peer, MsgId msgId, ShowWay way = ShowWay::ClearStack); +inline void showPeerHistory(const PeerData *peer, MsgId msgId, ShowWay way = ShowWay::ClearStack) { + showPeerHistory(peer->id, msgId, way); } -inline void showPeerHistory(const History *history, MsgId msgId, bool back = false) { - showPeerHistory(history->peer->id, msgId, back); +inline void showPeerHistory(const History *history, MsgId msgId, ShowWay way = ShowWay::ClearStack) { + showPeerHistory(history->peer->id, msgId, way); } -inline void showPeerHistoryAtItem(const HistoryItem *item) { - showPeerHistory(item->history()->peer->id, item->id); +inline void showPeerHistoryAtItem(const HistoryItem *item, ShowWay way = ShowWay::ClearStack) { + showPeerHistory(item->history()->peer->id, item->id, way); } -void showPeerHistoryAsync(const PeerId &peer, MsgId msgId); +void showPeerHistoryAsync(const PeerId &peer, MsgId msgId, ShowWay way = ShowWay::ClearStack); inline void showChatsList() { - showPeerHistory(PeerId(0), 0); + showPeerHistory(PeerId(0), 0, ShowWay::ClearStack); } inline void showChatsListAsync() { - showPeerHistoryAsync(PeerId(0), 0); + showPeerHistoryAsync(PeerId(0), 0, ShowWay::ClearStack); } PeerData *getPeerForMouseAction(); @@ -178,10 +183,19 @@ enum Flags { namespace Stickers { static const uint64 DefaultSetId = 0; // for backward compatibility -static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL; -static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel +static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL; +static const uint64 RecentSetId = 0xFFFFFFFFFFFFFFFEULL; // for emoji/stickers panel, should not appear in Sets +static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel, should not appear in Sets +static const uint64 CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; // for cloud-stored recent stickers struct Set { - Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) : id(id), access(access), title(title), shortName(shortName), count(count), hash(hash), flags(flags) { + Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) + : id(id) + , access(access) + , title(title) + , shortName(shortName) + , count(count) + , hash(hash) + , flags(flags) { } uint64 id, access; QString title, shortName; @@ -193,6 +207,15 @@ struct Set { using Sets = QMap; using Order = QList; +inline MTPInputStickerSet inputSetId(const Set &set) { + if (set.id && set.access) { + return MTP_inputStickerSetID(MTP_long(set.id), MTP_long(set.access)); + } + return MTP_inputStickerSetShortName(MTP_string(set.shortName)); +} + +Set *feedSet(const MTPDstickerSet &set); + } // namespace Stickers namespace Global { @@ -236,6 +259,7 @@ DeclareVar(int32, PushChatPeriod); DeclareVar(int32, PushChatLimit); DeclareVar(int32, SavedGifsLimit); DeclareVar(int32, EditTimeLimit); +DeclareVar(int32, StickersRecentLimit); typedef QMap HiddenPinnedMessagesMap; DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages); @@ -246,6 +270,11 @@ DeclareRefVar(PendingItemsMap, PendingRepaintItems); DeclareVar(Stickers::Sets, StickerSets); DeclareVar(Stickers::Order, StickerSetsOrder); DeclareVar(uint64, LastStickersUpdate); +DeclareVar(uint64, LastRecentStickersUpdate); +DeclareVar(Stickers::Order, FeaturedStickerSetsOrder); +DeclareVar(int, FeaturedStickerSetsUnreadCount); +DeclareVar(uint64, LastFeaturedStickersUpdate); +DeclareVar(Stickers::Order, ArchivedStickerSetsOrder); DeclareVar(MTP::DcOptions, DcOptions); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 8bf762fea..f9f3cbe34 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -2871,7 +2871,9 @@ bool HistoryItem::unread() const { if (id > 0) { if (id < history()->outboxReadBefore) return false; - if (auto channel = history()->peer->asChannel()) { + if (auto user = history()->peer->asUser()) { + if (user->botInfo) return false; + } else if (auto channel = history()->peer->asChannel()) { if (!channel->isMegagroup()) return false; } } @@ -4081,10 +4083,10 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection, bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width)); - QPixmap thumb = loaded ? _data->thumb->pixSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize); + QPixmap thumb = loaded ? _data->thumb->pixSingle(ImageRoundRadius::Large, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize); p.drawPixmap(rthumb.topLeft(), thumb); if (selected) { - App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners); + App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayLargeCorners); } if (radial || (!loaded && !_data->loading())) { @@ -5172,7 +5174,7 @@ int HistorySticker::additionalWidth(const HistoryMessageVia *via, const HistoryM } void SendMessageClickHandler::onClickImpl() const { - Ui::showPeerHistory(peer()->id, ShowAtUnreadMsgId); + Ui::showPeerHistory(peer()->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); } void AddContactClickHandler::onClickImpl() const { diff --git a/Telegram/SourceFiles/history/field_autocomplete.cpp b/Telegram/SourceFiles/history/field_autocomplete.cpp index cfeffcdf0..a814fa9bd 100644 --- a/Telegram/SourceFiles/history/field_autocomplete.cpp +++ b/Telegram/SourceFiles/history/field_autocomplete.cpp @@ -153,15 +153,15 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) { StickerPack srows; if (_emoji) { QMap setsToRequest; - Stickers::Sets &sets(Global::RefStickerSets()); - const Stickers::Order &order(Global::StickerSetsOrder()); + auto &sets = Global::RefStickerSets(); + auto &order = Global::StickerSetsOrder(); for (int i = 0, l = order.size(); i < l; ++i) { auto it = sets.find(order.at(i)); if (it != sets.cend()) { if (it->emoji.isEmpty()) { setsToRequest.insert(it->id, it->access); it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; - } else if (!(it->flags & MTPDstickerSet::Flag::f_disabled)) { + } else if (!(it->flags & MTPDstickerSet::Flag::f_archived)) { StickersByEmojiMap::const_iterator i = it->emoji.constFind(emojiGetNoColor(_emoji)); if (i != it->emoji.cend()) { srows += *i; @@ -196,14 +196,14 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) { } return true; }; - auto filterNotPassedByName = [this](UserData *user) -> bool { + auto filterNotPassedByName = [this, &filterNotPassedByUsername](UserData *user) -> bool { for_const (auto &namePart, user->names) { if (namePart.startsWith(_filter, Qt::CaseInsensitive)) { bool exactUsername = (user->username.compare(_filter, Qt::CaseInsensitive) == 0); return exactUsername; } } - return true; + return filterNotPassedByUsername(user); }; bool listAllSuggestions = _filter.isEmpty(); diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index ecf537a67..efcc20934 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -29,6 +29,8 @@ historyToDownArrow: icon { { "history_down_arrow", #b9b9b9, point(14px, 19px) }, }; historyToDownPaddingTop: 10px; +historyToDownBadgeFont: semiboldFont; +historyToDownBadgeSize: 22px; membersInnerScroll: flatScroll(solidScroll) { deltat: 3px; @@ -43,8 +45,6 @@ membersInnerDropdown: InnerDropdown(defaultInnerDropdown) { scrollMargin: margins(0px, 5px, 0px, 5px); scrollPadding: margins(0px, 3px, 8px, 3px); } -historyToDownBadgeFont: semiboldFont; -historyToDownBadgeSize: 22px; historyServiceMsgRadius: 12px; historyServiceMsgInvertedRadius: 6px; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index a46a42433..b587be32c 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "data/data_drafts.h" #include "history/history_service_layout.h" #include "profile/profile_members_widget.h" +#include "core/click_handler_types.h" #include "lang.h" #include "application.h" #include "mainwidget.h" @@ -3519,12 +3520,23 @@ void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) { } void HistoryWidget::updateStickers() { - if (!Global::LastStickersUpdate() || getms(true) >= Global::LastStickersUpdate() + StickersUpdateTimeout) { + auto now = getms(true); + if (!Global::LastStickersUpdate() || now >= Global::LastStickersUpdate() + StickersUpdateTimeout) { if (!_stickersUpdateRequest) { _stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(Local::countStickersHash(true))), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed)); } } - if (!cLastSavedGifsUpdate() || getms(true) >= cLastSavedGifsUpdate() + StickersUpdateTimeout) { + if (!Global::LastRecentStickersUpdate() || now >= Global::LastRecentStickersUpdate() + StickersUpdateTimeout) { + if (!_recentStickersUpdateRequest) { + _recentStickersUpdateRequest = MTP::send(MTPmessages_GetRecentStickers(MTP_int(Local::countRecentStickersHash())), rpcDone(&HistoryWidget::recentStickersGot), rpcFail(&HistoryWidget::recentStickersFailed)); + } + } + if (!Global::LastFeaturedStickersUpdate() || now >= Global::LastFeaturedStickersUpdate() + StickersUpdateTimeout) { + if (!_featuredStickersUpdateRequest) { + _featuredStickersUpdateRequest = MTP::send(MTPmessages_GetFeaturedStickers(MTP_int(Local::countFeaturedStickersHash())), rpcDone(&HistoryWidget::featuredStickersGot), rpcFail(&HistoryWidget::featuredStickersFailed)); + } + } + if (!cLastSavedGifsUpdate() || now >= cLastSavedGifsUpdate() + StickersUpdateTimeout) { if (!_savedGifsUpdateRequest) { _savedGifsUpdateRequest = MTP::send(MTPmessages_GetSavedGifs(MTP_int(Local::countSavedGifsHash())), rpcDone(&HistoryWidget::savedGifsGot), rpcFail(&HistoryWidget::savedGifsFailed)); } @@ -3650,36 +3662,23 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { const auto &d_sets(d.vsets.c_vector().v); - Stickers::Order &setsOrder(Global::RefStickerSetsOrder()); + auto &setsOrder = Global::RefStickerSetsOrder(); setsOrder.clear(); - Stickers::Sets &sets(Global::RefStickerSets()); + auto &sets = Global::RefStickerSets(); QMap setsToRequest; - for (auto i = sets.begin(), e = sets.end(); i != e; ++i) { - i->access = 0; // mark for removing + for (auto &set : sets) { + if (!(set.flags & MTPDstickerSet::Flag::f_archived)) { + set.flags &= ~MTPDstickerSet::Flag::f_installed; // mark for removing + } } - for (int i = 0, l = d_sets.size(); i != l; ++i) { - if (d_sets.at(i).type() == mtpc_stickerSet) { - const auto &set(d_sets.at(i).c_stickerSet()); - auto it = sets.find(set.vid.v); - QString title = stickerSetTitle(set); - if (it == sets.cend()) { - it = sets.insert(set.vid.v, Stickers::Set(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | MTPDstickerSet_ClientFlag::f_not_loaded)); - } else { - it->access = set.vaccess_hash.v; - it->title = title; - it->shortName = qs(set.vshort_name); - it->flags = set.vflags.v; - if (it->count != set.vcount.v || it->hash != set.vhash.v || it->emoji.isEmpty()) { - it->count = set.vcount.v; - it->hash = set.vhash.v; - it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; // need to request this set - } - } - if (!(it->flags & MTPDstickerSet::Flag::f_disabled) || (it->flags & MTPDstickerSet::Flag::f_official)) { - setsOrder.push_back(set.vid.v); - if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { - setsToRequest.insert(set.vid.v, set.vaccess_hash.v); + for_const (auto &setData, d_sets) { + if (setData.type() == mtpc_stickerSet) { + auto set = Stickers::feedSet(setData.c_stickerSet()); + if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) { + setsOrder.push_back(set->id); + if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { + setsToRequest.insert(set->id, set->access); } } } @@ -3687,9 +3686,11 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { bool writeRecent = false; RecentStickerPack &recent(cGetRecentStickers()); for (Stickers::Sets::iterator it = sets.begin(), e = sets.end(); it != e;) { - if (it->id == Stickers::CustomSetId || it->access != 0) { - ++it; - } else { + bool installed = (it->flags & MTPDstickerSet::Flag::f_installed); + bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured); + bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special); + bool archived = (it->flags & MTPDstickerSet::Flag::f_archived); + if (!installed) { // remove not mine sets from recent stickers for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { if (it->stickers.indexOf(i->first) >= 0) { i = recent.erase(i); @@ -3698,6 +3699,10 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { ++i; } } + } + if (installed || featured || special || archived) { + ++it; + } else { it = sets.erase(it); } } @@ -3713,7 +3718,7 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { App::api()->requestStickerSets(); } - Local::writeStickers(); + Local::writeInstalledStickers(); if (writeRecent) Local::writeUserSettings(); if (App::main()) emit App::main()->stickersUpdated(); @@ -3729,6 +3734,193 @@ bool HistoryWidget::stickersFailed(const RPCError &error) { return true; } +void HistoryWidget::recentStickersGot(const MTPmessages_RecentStickers &stickers) { + Global::SetLastRecentStickersUpdate(getms(true)); + _recentStickersUpdateRequest = 0; + + if (stickers.type() != mtpc_messages_recentStickers) return; + auto &d = stickers.c_messages_recentStickers(); + + auto &sets = Global::RefStickerSets(); + auto it = sets.find(Stickers::CloudRecentSetId); + + auto &d_docs = d.vstickers.c_vector().v; + if (d_docs.isEmpty()) { + if (it != sets.cend()) { + sets.erase(it); + } + } else { + if (it == sets.cend()) { + it = sets.insert(Stickers::CloudRecentSetId, Stickers::Set(Stickers::CloudRecentSetId, 0, lang(lng_recent_stickers), QString(), 0, 0, qFlags(MTPDstickerSet_ClientFlag::f_special))); + } else { + it->title = lang(lng_recent_stickers); + } + it->hash = d.vhash.v; + + auto custom = sets.find(Stickers::CustomSetId); + + StickerPack pack; + pack.reserve(d_docs.size()); + for (int32 i = 0, l = d_docs.size(); i != l; ++i) { + DocumentData *doc = App::feedDocument(d_docs.at(i)); + if (!doc || !doc->sticker()) continue; + + pack.push_back(doc); + if (custom != sets.cend()) { + int32 index = custom->stickers.indexOf(doc); + if (index >= 0) { + custom->stickers.removeAt(index); + } + } + } + if (custom != sets.cend() && custom->stickers.isEmpty()) { + sets.erase(custom); + custom = sets.end(); + } + + bool writeRecent = false; + RecentStickerPack &recent(cGetRecentStickers()); + for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { + if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) { + i = recent.erase(i); + writeRecent = true; + } else { + ++i; + } + } + + if (pack.isEmpty()) { + sets.erase(it); + } else { + it->stickers = pack; + it->emoji.clear(); + } + + if (writeRecent) { + Local::writeUserSettings(); + } + } + + if (Local::countRecentStickersHash() != d.vhash.v) { + LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countRecentStickersHash())); + } + + Local::writeRecentStickers(); + + if (App::main()) emit App::main()->stickersUpdated(); +} + +bool HistoryWidget::recentStickersFailed(const RPCError &error) { + if (MTP::isDefaultHandledError(error)) return false; + + LOG(("App Fail: Failed to get recent stickers!")); + + Global::SetLastRecentStickersUpdate(getms(true)); + _recentStickersUpdateRequest = 0; + return true; +} + +void HistoryWidget::featuredStickersGot(const MTPmessages_FeaturedStickers &stickers) { + Global::SetLastFeaturedStickersUpdate(getms(true)); + _featuredStickersUpdateRequest = 0; + + if (stickers.type() != mtpc_messages_featuredStickers) return; + auto &d(stickers.c_messages_featuredStickers()); + + OrderedSet unread; + for_const (auto &unreadSetId, d.vunread.c_vector().v) { + unread.insert(unreadSetId.v); + } + + auto &d_sets(d.vsets.c_vector().v); + + auto &setsOrder = Global::RefFeaturedStickerSetsOrder(); + setsOrder.clear(); + + auto &sets = Global::RefStickerSets(); + QMap setsToRequest; + for (auto &set : sets) { + set.flags &= ~MTPDstickerSet_ClientFlag::f_featured; // mark for removing + } + for (int i = 0, l = d_sets.size(); i != l; ++i) { + if (d_sets.at(i).type() == mtpc_stickerSetCovered && d_sets.at(i).c_stickerSetCovered().vset.type() == mtpc_stickerSet) { + const auto &set(d_sets.at(i).c_stickerSetCovered().vset.c_stickerSet()); + auto it = sets.find(set.vid.v); + QString title = stickerSetTitle(set); + if (it == sets.cend()) { + auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_not_loaded; + if (unread.contains(set.vid.v)) { + setClientFlags |= MTPDstickerSet_ClientFlag::f_unread; + } + it = sets.insert(set.vid.v, Stickers::Set(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | setClientFlags)); + } else { + it->access = set.vaccess_hash.v; + it->title = title; + it->shortName = qs(set.vshort_name); + auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special); + it->flags = set.vflags.v | clientFlags; + it->flags |= MTPDstickerSet_ClientFlag::f_featured; + if (unread.contains(it->id)) { + it->flags |= MTPDstickerSet_ClientFlag::f_unread; + } else { + it->flags &= ~MTPDstickerSet_ClientFlag::f_unread; + } + if (it->count != set.vcount.v || it->hash != set.vhash.v || it->emoji.isEmpty()) { + it->count = set.vcount.v; + it->hash = set.vhash.v; + it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; // need to request this set + } + } + setsOrder.push_back(set.vid.v); + if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { + setsToRequest.insert(set.vid.v, set.vaccess_hash.v); + } + } + } + + int unreadCount = 0; + for (auto it = sets.begin(), e = sets.end(); it != e;) { + bool installed = (it->flags & MTPDstickerSet::Flag::f_installed); + bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured); + bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special); + bool archived = (it->flags & MTPDstickerSet::Flag::f_archived); + if (installed || featured || special || archived) { + if (featured && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) { + ++unreadCount; + } + ++it; + } else { + it = sets.erase(it); + } + } + Global::SetFeaturedStickerSetsUnreadCount(unreadCount); + + if (Local::countFeaturedStickersHash() != d.vhash.v) { + LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countFeaturedStickersHash())); + } + + if (!setsToRequest.isEmpty() && App::api()) { + for (QMap::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) { + App::api()->scheduleStickerSetRequest(i.key(), i.value()); + } + App::api()->requestStickerSets(); + } + + Local::writeFeaturedStickers(); + + if (App::main()) emit App::main()->stickersUpdated(); +} + +bool HistoryWidget::featuredStickersFailed(const RPCError &error) { + if (MTP::isDefaultHandledError(error)) return false; + + LOG(("App Fail: Failed to get featured stickers!")); + + Global::SetLastFeaturedStickersUpdate(getms(true)); + _featuredStickersUpdateRequest = 0; + return true; +} + void HistoryWidget::savedGifsGot(const MTPmessages_SavedGifs &gifs) { cSetLastSavedGifsUpdate(getms(true)); _savedGifsUpdateRequest = 0; @@ -4571,7 +4763,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { PeerData *was = _peer; - Ui::showChatsList(); + App::main()->showBackFromStack(); Ui::showLayer(new InformBox(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); return true; } @@ -4583,7 +4775,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId _preloadDownRequest = 0; } else if (_firstLoadRequest == requestId) { _firstLoadRequest = 0; - Ui::showChatsList(); + App::main()->showBackFromStack(); } else if (_delayedShowAtRequest == requestId) { _delayedShowAtRequest = 0; } @@ -5601,6 +5793,8 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC toast.text = qs(answerData.vmessage); Ui::Toast::Show(App::wnd(), toast); } + } else if (answerData.has_url()) { + HiddenUrlClickHandler(qs(answerData.vurl)).onClick(Qt::LeftButton); } } } @@ -6036,7 +6230,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) { if (!_history) return; - int32 increaseLeft = Adaptive::OneColumn() ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0; + int32 increaseLeft = (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0; decreaseWidth += increaseLeft; QRect rectForName(st::topBarForwardPadding.left() + increaseLeft, st::topBarForwardPadding.top(), width() - decreaseWidth - st::topBarForwardPadding.left() - st::topBarForwardPadding.right(), st::msgNameFont->height); p.setFont(st::dialogsTextFont); @@ -6051,7 +6245,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) { p.setPen(st::dialogsNameFg); _peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); - if (Adaptive::OneColumn()) { + if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) { p.setOpacity(st::topBarForwardAlpha + (1 - st::topBarForwardAlpha) * over); p.drawSprite(QPoint((st::topBarForwardPadding.right() - st::topBarBackwardImg.pxWidth()) / 2, (st::topBarHeight - st::topBarBackwardImg.pxHeight()) / 2), st::topBarBackwardImg); } else { @@ -6061,7 +6255,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) { } QRect HistoryWidget::getMembersShowAreaGeometry() const { - int increaseLeft = Adaptive::OneColumn() ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0; + int increaseLeft = (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0; int membersTextLeft = st::topBarForwardPadding.left() + increaseLeft; int membersTextTop = st::topBarHeight - st::topBarForwardPadding.bottom() - st::dialogsTextFont->height; int membersTextWidth = _titlePeerTextWidth; @@ -6107,8 +6301,8 @@ void HistoryWidget::onMembersDropdownHidden() { } void HistoryWidget::topBarClick() { - if (Adaptive::OneColumn()) { - Ui::showChatsList(); + if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) { + App::main()->showBackFromStack(); } else { if (_history) Ui::showPeerProfile(_peer); } @@ -6660,10 +6854,10 @@ void HistoryWidget::onReportSpamClear() { if (_clearPeer->isUser()) { App::main()->deleteConversation(_clearPeer); } else if (_clearPeer->isChat()) { - Ui::showChatsList(); + App::main()->showBackFromStack(); MTP::send(MTPmessages_DeleteChatUser(_clearPeer->asChat()->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _clearPeer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _clearPeer)); } else if (_clearPeer->isChannel()) { - Ui::showChatsList(); + App::main()->showBackFromStack(); if (_clearPeer->migrateFrom()) { App::main()->deleteConversation(_clearPeer->migrateFrom()); } @@ -7191,7 +7385,7 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { e->ignore(); } else if (e->key() == Qt::Key_Back) { - Ui::showChatsList(); + App::main()->showBackFromStack(); emit cancelled(); } else if (e->key() == Qt::Key_PageDown) { _scroll.keyPressEvent(e); @@ -7971,7 +8165,7 @@ void HistoryWidget::onCancel() { } else if (!_fieldAutocomplete->isHidden()) { _fieldAutocomplete->hideStart(); } else { - Ui::showChatsList(); + App::main()->showBackFromStack(); emit cancelled(); } } @@ -8009,7 +8203,7 @@ void HistoryWidget::peerUpdated(PeerData *data) { } QString restriction = _peer->restrictionReason(); if (!restriction.isEmpty()) { - Ui::showChatsList(); + App::main()->showBackFromStack(); Ui::showLayer(new InformBox(restriction)); return; } diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index fdcdad95d..ee97d4115 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -1005,6 +1005,14 @@ private: void stickersGot(const MTPmessages_AllStickers &stickers); bool stickersFailed(const RPCError &error); + mtpRequestId _recentStickersUpdateRequest = 0; + void recentStickersGot(const MTPmessages_RecentStickers &stickers); + bool recentStickersFailed(const RPCError &error); + + mtpRequestId _featuredStickersUpdateRequest = 0; + void featuredStickersGot(const MTPmessages_FeaturedStickers &stickers); + bool featuredStickersFailed(const RPCError &error); + mtpRequestId _savedGifsUpdateRequest = 0; void savedGifsGot(const MTPmessages_SavedGifs &gifs); bool savedGifsFailed(const RPCError &error); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index 29a4909c7..d3afc27b4 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -352,7 +352,7 @@ void Result::createDocument() { attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes())); } - MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(0), MTP_photoSizeEmpty(MTP_string("")), MTP_int(MTP::maindc()), MTP_vector(attributes)); + MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(0), MTP_photoSizeEmpty(MTP_string("")), MTP_int(MTP::maindc()), MTP_int(0), MTP_vector(attributes)); _document = App::feedDocument(document); _document->setContentUrl(_content_url); diff --git a/Telegram/SourceFiles/intro/introcode.h b/Telegram/SourceFiles/intro/introcode.h index 7e6bfad3d..ab62224ca 100644 --- a/Telegram/SourceFiles/intro/introcode.h +++ b/Telegram/SourceFiles/intro/introcode.h @@ -29,15 +29,12 @@ class CodeInput final : public FlatInput { Q_OBJECT public: - CodeInput(QWidget *parent, const style::flatInput &st, const QString &ph); signals: - void codeEntered(); protected: - void correctValue(const QString &was, QString &now); }; diff --git a/Telegram/SourceFiles/intro/intropwdcheck.cpp b/Telegram/SourceFiles/intro/intropwdcheck.cpp index ae6d34348..c7da076c9 100644 --- a/Telegram/SourceFiles/intro/intropwdcheck.cpp +++ b/Telegram/SourceFiles/intro/intropwdcheck.cpp @@ -340,7 +340,28 @@ bool IntroPwdCheck::deleteFail(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; sentRequest = 0; - showError(lang(lng_server_error)); + + auto type = error.type(); + if (type.startsWith(qstr("2FA_CONFIRM_WAIT_"))) { + int seconds = type.mid(qstr("2FA_CONFIRM_WAIT_").size()).toInt(); + int days = (seconds + 59) / 86400; + int hours = ((seconds + 59) % 86400) / 3600; + int minutes = ((seconds + 59) % 3600) / 60; + QString when; + if (days > 0) { + when = lng_signin_reset_in_days(lt_count_days, days, lt_count_hours, hours, lt_count_minutes, minutes); + } else if (hours > 0) { + when = lng_signin_reset_in_hours(lt_count_hours, hours, lt_count_minutes, minutes); + } else { + when = lng_signin_reset_in_minutes(lt_count_minutes, minutes); + } + Ui::showLayer(new InformBox(lng_signin_reset_wait(lt_phone_number, App::formatPhone(intro()->getPhone()), lt_when, when))); + } else if (type == qstr("2FA_RECENT_CONFIRM")) { + Ui::showLayer(new InformBox(lang(lng_signin_reset_cancelled))); + } else { + Ui::hideLayer(); + showError(lang(lng_server_error)); + } return true; } diff --git a/Telegram/SourceFiles/localimageloader.cpp b/Telegram/SourceFiles/localimageloader.cpp index 8419f665e..1da43d5c1 100644 --- a/Telegram/SourceFiles/localimageloader.cpp +++ b/Telegram/SourceFiles/localimageloader.cpp @@ -414,9 +414,9 @@ void FileLoadTask::process() { if (voice) { attributes[0] = MTP_documentAttributeAudio(MTP_flags(MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform))); attributes.resize(1); - document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector(attributes)); + document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector(attributes)); } else { - document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector(attributes)); + document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector(attributes)); if (photo.type() == mtpc_photoEmpty) { _type = PrepareDocument; } diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 11e617c13..f8d4a1786 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -479,11 +479,12 @@ namespace { lskBackground = 0x08, // no data lskUserSettings = 0x09, // no data lskRecentHashtagsAndBots = 0x0a, // no data - lskStickers = 0x0b, // no data + lskStickersOld = 0x0b, // no data lskSavedPeers = 0x0c, // no data lskReportSpamStatuses = 0x0d, // no data lskSavedGifsOld = 0x0e, // no data lskSavedGifs = 0x0f, // no data + lskStickersKeys = 0x10, // no data }; enum { @@ -542,6 +543,7 @@ namespace { dbiDialogsMode = 0x40, dbiModerateMode = 0x41, dbiVideoVolume = 0x42, + dbiStickersRecentLimit = 0x43, dbiEncryptedWithSalt = 333, dbiEncrypted = 444, @@ -571,7 +573,9 @@ namespace { uint64 _storageWebFilesSize = 0; FileKey _locationsKey = 0, _reportSpamStatusesKey = 0; - FileKey _recentStickersKeyOld = 0, _stickersKey = 0, _savedGifsKey = 0; + FileKey _recentStickersKeyOld = 0; + FileKey _installedStickersKey = 0, _featuredStickersKey = 0, _recentStickersKey = 0, _archivedStickersKey = 0; + FileKey _savedGifsKey = 0; FileKey _backgroundKey = 0; bool _backgroundWasRead = false; @@ -835,6 +839,14 @@ namespace { Global::SetSavedGifsLimit(limit); } break; + case dbiStickersRecentLimit: { + qint32 limit; + stream >> limit; + if (!_checkStreamStatus(stream)) return false; + + Global::SetStickersRecentLimit(limit); + } break; + case dbiMegagroupSizeMax: { qint32 maxSize; stream >> maxSize; @@ -1725,7 +1737,9 @@ namespace { StorageMap imagesMap, stickerImagesMap, audiosMap; qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0; quint64 locationsKey = 0, reportSpamStatusesKey = 0; - quint64 recentStickersKeyOld = 0, stickersKey = 0, savedGifsKey = 0; + quint64 recentStickersKeyOld = 0; + quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, archivedStickersKey = 0; + quint64 savedGifsKey = 0; quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0; while (!map.stream.atEnd()) { quint32 keyType; @@ -1806,8 +1820,11 @@ namespace { case lskRecentHashtagsAndBots: { map.stream >> recentHashtagsAndBotsKey; } break; - case lskStickers: { - map.stream >> stickersKey; + case lskStickersOld: { + map.stream >> installedStickersKey; + } break; + case lskStickersKeys: { + map.stream >> installedStickersKey >> featuredStickersKey >> recentStickersKey >> archivedStickersKey; } break; case lskSavedGifsOld: { quint64 key; @@ -1842,7 +1859,10 @@ namespace { _locationsKey = locationsKey; _reportSpamStatusesKey = reportSpamStatusesKey; _recentStickersKeyOld = recentStickersKeyOld; - _stickersKey = stickersKey; + _installedStickersKey = installedStickersKey; + _featuredStickersKey = featuredStickersKey; + _recentStickersKey = recentStickersKey; + _archivedStickersKey = archivedStickersKey; _savedGifsKey = savedGifsKey; _savedPeersKey = savedPeersKey; _backgroundKey = backgroundKey; @@ -1915,7 +1935,9 @@ namespace { if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_reportSpamStatusesKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64); - if (_stickersKey) mapSize += sizeof(quint32) + sizeof(quint64); + if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) { + mapSize += sizeof(quint32) + 4 * sizeof(quint64); + } if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64); @@ -1961,8 +1983,9 @@ namespace { if (_recentStickersKeyOld) { mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld); } - if (_stickersKey) { - mapData.stream << quint32(lskStickers) << quint64(_stickersKey); + if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) { + mapData.stream << quint32(lskStickersKeys); + mapData.stream << quint64(_installedStickersKey) << quint64(_featuredStickersKey) << quint64(_recentStickersKey) << quint64(_archivedStickersKey); } if (_savedGifsKey) { mapData.stream << quint32(lskSavedGifs) << quint64(_savedGifsKey); @@ -2185,12 +2208,13 @@ namespace Local { size += Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password); } - size += sizeof(quint32) + sizeof(qint32) * 6; + size += sizeof(quint32) + sizeof(qint32) * 7; EncryptedDescriptor data(size); data.stream << quint32(dbiChatSizeMax) << qint32(Global::ChatSizeMax()); data.stream << quint32(dbiMegagroupSizeMax) << qint32(Global::MegagroupSizeMax()); data.stream << quint32(dbiSavedGifsLimit) << qint32(Global::SavedGifsLimit()); + data.stream << quint32(dbiStickersRecentLimit) << qint32(Global::StickersRecentLimit()); data.stream << quint32(dbiAutoStart) << qint32(cAutoStart()); data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized()); data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu()); @@ -2247,7 +2271,9 @@ namespace Local { _webFilesMap.clear(); _storageWebFilesSize = 0; _locationsKey = _reportSpamStatusesKey = 0; - _recentStickersKeyOld = _stickersKey = _savedGifsKey = 0; + _recentStickersKeyOld = 0; + _installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0; + _savedGifsKey = 0; _backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0; _oldMapVersion = _oldSettingsVersion = 0; _mapChanged = true; @@ -3017,26 +3043,23 @@ namespace Local { } } - void _writeStickerSet(QDataStream &stream, uint64 setId) { - auto it = Global::StickerSets().constFind(setId); - if (it == Global::StickerSets().cend()) return; - - bool notLoaded = (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded); + void _writeStickerSet(QDataStream &stream, const Stickers::Set &set) { + bool notLoaded = (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded); if (notLoaded) { - stream << quint64(it->id) << quint64(it->access) << it->title << it->shortName << qint32(-it->count) << qint32(it->hash) << qint32(it->flags); + stream << quint64(set.id) << quint64(set.access) << set.title << set.shortName << qint32(-set.count) << qint32(set.hash) << qint32(set.flags); return; } else { - if (it->stickers.isEmpty()) return; + if (set.stickers.isEmpty()) return; } - stream << quint64(it->id) << quint64(it->access) << it->title << it->shortName << qint32(it->stickers.size()) << qint32(it->hash) << qint32(it->flags); - for (StickerPack::const_iterator j = it->stickers.cbegin(), e = it->stickers.cend(); j != e; ++j) { + stream << quint64(set.id) << quint64(set.access) << set.title << set.shortName << qint32(set.stickers.size()) << qint32(set.hash) << qint32(set.flags); + for (StickerPack::const_iterator j = set.stickers.cbegin(), e = set.stickers.cend(); j != e; ++j) { Serialize::Document::writeToStream(stream, *j); } if (AppVersion > 9018) { - stream << qint32(it->emoji.size()); - for (StickersByEmojiMap::const_iterator j = it->emoji.cbegin(), e = it->emoji.cend(); j != e; ++j) { + stream << qint32(set.emoji.size()); + for (StickersByEmojiMap::const_iterator j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) { stream << emojiString(j.key()) << qint32(j->size()); for (int32 k = 0, l = j->size(); k < l; ++k) { stream << quint64(j->at(k)->id); @@ -3045,61 +3068,274 @@ namespace Local { } } - void writeStickers() { + // In generic method _writeStickerSets() we look through all the sets and call a + // callback on each set to see, if we write it, skip it or abort the whole write. + enum class StickerSetCheckResult { + Write, + Skip, + Abort, + }; + + // CheckSet is a functor on Stickers::Set, which returns a StickerSetCheckResult. + template + void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::Order &order) { if (!_working()) return; - const Stickers::Sets &sets(Global::StickerSets()); + auto &sets = Global::StickerSets(); if (sets.isEmpty()) { - if (_stickersKey) { - clearKey(_stickersKey); - _stickersKey = 0; + if (stickersKey) { + clearKey(stickersKey); + stickersKey = 0; _mapChanged = true; } _writeMap(); - } else { - int32 setsCount = 0; - QByteArray hashToWrite; - quint32 size = sizeof(quint32) + Serialize::bytearraySize(hashToWrite); - for (auto i = sets.cbegin(); i != sets.cend(); ++i) { - bool notLoaded = (i->flags & MTPDstickerSet_ClientFlag::f_not_loaded); - if (notLoaded) { - if (!(i->flags & MTPDstickerSet::Flag::f_disabled) || (i->flags & MTPDstickerSet::Flag::f_official)) { // waiting to receive - return; - } - } else { - if (i->stickers.isEmpty()) continue; - } - - // id + access + title + shortName + stickersCount + hash + flags - size += sizeof(quint64) * 2 + Serialize::stringSize(i->title) + Serialize::stringSize(i->shortName) + sizeof(quint32) + sizeof(qint32) * 2; - for (StickerPack::const_iterator j = i->stickers.cbegin(), e = i->stickers.cend(); j != e; ++j) { - size += Serialize::Document::sizeInStream(*j); - } - - if (AppVersion > 9018) { - size += sizeof(qint32); // emojiCount - for (StickersByEmojiMap::const_iterator j = i->emoji.cbegin(), e = i->emoji.cend(); j != e; ++j) { - size += Serialize::stringSize(emojiString(j.key())) + sizeof(qint32) + (j->size() * sizeof(quint64)); - } - } - - ++setsCount; - } - - if (!_stickersKey) { - _stickersKey = genKey(); - _mapChanged = true; - _writeMap(WriteMapFast); - } - EncryptedDescriptor data(size); - data.stream << quint32(setsCount) << hashToWrite; - _writeStickerSet(data.stream, Stickers::CustomSetId); - for (auto i = Global::StickerSetsOrder().cbegin(), e = Global::StickerSetsOrder().cend(); i != e; ++i) { - _writeStickerSet(data.stream, *i); - } - FileWriteDescriptor file(_stickersKey); - file.writeEncrypted(data); + return; } + int32 setsCount = 0; + QByteArray hashToWrite; + quint32 size = sizeof(quint32) + Serialize::bytearraySize(hashToWrite); + for_const (auto &set, sets) { + auto result = checkSet(set); + if (result == StickerSetCheckResult::Abort) { + return; + } else if (result == StickerSetCheckResult::Skip) { + continue; + } + + // id + access + title + shortName + stickersCount + hash + flags + size += sizeof(quint64) * 2 + Serialize::stringSize(set.title) + Serialize::stringSize(set.shortName) + sizeof(quint32) + sizeof(qint32) * 2; + for_const (auto &sticker, set.stickers) { + size += Serialize::Document::sizeInStream(sticker); + } + + size += sizeof(qint32); // emojiCount + for (auto j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) { + size += Serialize::stringSize(emojiString(j.key())) + sizeof(qint32) + (j->size() * sizeof(quint64)); + } + + ++setsCount; + } + if (!setsCount && order.isEmpty()) { + if (stickersKey) { + clearKey(stickersKey); + stickersKey = 0; + _mapChanged = true; + } + _writeMap(); + return; + } + size += sizeof(qint32) + (order.size() * sizeof(quint64)); + + if (!stickersKey) { + stickersKey = genKey(); + _mapChanged = true; + _writeMap(WriteMapFast); + } + EncryptedDescriptor data(size); + data.stream << quint32(setsCount) << hashToWrite; + for_const (auto &set, sets) { + auto result = checkSet(set); + if (result == StickerSetCheckResult::Abort) { + return; + } else if (result == StickerSetCheckResult::Skip) { + continue; + } + _writeStickerSet(data.stream, set); + } + data.stream << order; + + FileWriteDescriptor file(stickersKey); + file.writeEncrypted(data); + } + + void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, MTPDstickerSet::Flags readingFlags = 0) { + FileReadDescriptor stickers; + if (!readEncryptedFile(stickers, stickersKey)) { + clearKey(stickersKey); + stickersKey = 0; + _writeMap(); + return; + } + + bool readingInstalled = (readingFlags == qFlags(MTPDstickerSet::Flag::f_installed)); + + auto &sets = Global::RefStickerSets(); + if (outOrder) outOrder->clear(); + + quint32 cnt; + QByteArray hash; + stickers.stream >> cnt >> hash; // ignore hash, it is counted + if (readingInstalled && stickers.version < 8019) { // bad data in old caches + cnt += 2; // try to read at least something + } + for (uint32 i = 0; i < cnt; ++i) { + quint64 setId = 0, setAccess = 0; + QString setTitle, setShortName; + qint32 scnt = 0; + stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt; + + qint32 setHash = 0, setFlags = 0; + if (stickers.version > 8033) { + stickers.stream >> setHash >> setFlags; + if (setFlags & qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old)) { + setFlags &= ~qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old); + setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_not_loaded); + } + } + if (readingInstalled && stickers.version < 9061) { + setFlags |= qFlags(MTPDstickerSet::Flag::f_installed); + } + + if (setId == Stickers::DefaultSetId) { + setTitle = lang(lng_stickers_default_set); + setFlags |= qFlags(MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special); + if (readingInstalled && outOrder && stickers.version < 9061) { + outOrder->push_front(setId); + } + } else if (setId == Stickers::CustomSetId) { + setTitle = lang(lng_custom_stickers); + setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special); + } else if (setId == Stickers::CloudRecentSetId) { + setTitle = lang(lng_recent_stickers); + setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special); + } else if (setId) { + if (readingInstalled && outOrder && stickers.version < 9061) { + outOrder->push_back(setId); + } + } else { + continue; + } + + auto it = sets.find(setId); + if (it == sets.cend()) { + // We will set this flags from order lists when reading those stickers. + setFlags &= ~(MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_featured); + it = sets.insert(setId, Stickers::Set(setId, setAccess, setTitle, setShortName, 0, setHash, MTPDstickerSet::Flags(setFlags))); + } + auto &set = it.value(); + + if (scnt < 0) { // disabled not loaded set + if (!set.count || set.stickers.isEmpty()) { + set.count = -scnt; + } + continue; + } + + bool fillStickers = set.stickers.isEmpty(); + if (fillStickers) { + set.stickers.reserve(scnt); + set.count = 0; + } + + Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName); + OrderedSet read; + for (int32 j = 0; j < scnt; ++j) { + auto document = Serialize::Document::readStickerFromStream(stickers.version, stickers.stream, info); + if (!document || !document->sticker()) continue; + + if (read.contains(document->id)) continue; + read.insert(document->id); + + if (fillStickers) { + set.stickers.push_back(document); + ++set.count; + } + } + + if (stickers.version > 9018) { + qint32 emojiCount; + stickers.stream >> emojiCount; + for (int32 j = 0; j < emojiCount; ++j) { + QString emojiString; + qint32 stickersCount; + stickers.stream >> emojiString >> stickersCount; + StickerPack pack; + pack.reserve(stickersCount); + for (int32 k = 0; k < stickersCount; ++k) { + quint64 id; + stickers.stream >> id; + DocumentData *doc = App::document(id); + if (!doc || !doc->sticker()) continue; + + pack.push_back(doc); + } + if (fillStickers) { + if (auto e = emojiGetNoColor(emojiFromText(emojiString))) { + set.emoji.insert(e, pack); + } + } + } + } + } + + // Read orders of installed and featured stickers. + if (outOrder && stickers.version >= 9061) { + stickers.stream >> *outOrder; + } + + // Set flags that we dropped above from the order. + if (readingFlags && outOrder) { + for_const (auto setId, *outOrder) { + auto it = sets.find(setId); + if (it != sets.cend()) { + it->flags |= readingFlags; + } + } + } + } + + void writeInstalledStickers() { + _writeStickerSets(_installedStickersKey, [](const Stickers::Set &set) { + if (set.id == Stickers::CloudRecentSetId) { // separate file for recent + return StickerSetCheckResult::Skip; + } else if (set.flags & MTPDstickerSet_ClientFlag::f_special) { + if (set.stickers.isEmpty()) { // all other special are "installed" + return StickerSetCheckResult::Skip; + } + } else if (!(set.flags & MTPDstickerSet::Flag::f_installed) || (set.flags & MTPDstickerSet::Flag::f_archived)) { + return StickerSetCheckResult::Skip; + } else if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) { // waiting to receive + return StickerSetCheckResult::Abort; + } else if (set.stickers.isEmpty()) { + return StickerSetCheckResult::Skip; + } + return StickerSetCheckResult::Write; + }, Global::StickerSetsOrder()); + } + + void writeFeaturedStickers() { + _writeStickerSets(_featuredStickersKey, [](const Stickers::Set &set) { + if (set.id == Stickers::CloudRecentSetId) { // separate file for recent + return StickerSetCheckResult::Skip; + } else if (set.flags & MTPDstickerSet_ClientFlag::f_special) { + return StickerSetCheckResult::Skip; + } else if (!(set.flags & MTPDstickerSet_ClientFlag::f_featured)) { + return StickerSetCheckResult::Skip; + } else if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) { // waiting to receive + return StickerSetCheckResult::Abort; + } else if (set.stickers.isEmpty()) { + return StickerSetCheckResult::Skip; + } + return StickerSetCheckResult::Write; + }, Global::FeaturedStickerSetsOrder()); + } + + void writeRecentStickers() { + _writeStickerSets(_recentStickersKey, [](const Stickers::Set &set) { + if (set.id != Stickers::CloudRecentSetId || set.stickers.isEmpty()) { + return StickerSetCheckResult::Skip; + } + return StickerSetCheckResult::Write; + }, Stickers::Order()); + } + + void writeArchivedStickers() { + _writeStickerSets(_archivedStickersKey, [](const Stickers::Set &set) { + if (!(set.flags & MTPDstickerSet::Flag::f_archived) || set.stickers.isEmpty()) { + return StickerSetCheckResult::Skip; + } + return StickerSetCheckResult::Write; + }, Global::ArchivedStickerSetsOrder()); } void importOldRecentStickers() { @@ -3113,17 +3349,17 @@ namespace Local { return; } - Stickers::Sets &sets(Global::RefStickerSets()); + auto &sets = Global::RefStickerSets(); sets.clear(); - Stickers::Order &order(Global::RefStickerSetsOrder()); + auto &order = Global::RefStickerSetsOrder(); order.clear(); - RecentStickerPack &recent(cRefRecentStickers()); + auto &recent = cRefRecentStickers(); recent.clear(); - Stickers::Set &def(sets.insert(Stickers::DefaultSetId, Stickers::Set(Stickers::DefaultSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::Flag::f_official)).value()); - Stickers::Set &custom(sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)).value()); + auto &def = sets.insert(Stickers::DefaultSetId, Stickers::Set(Stickers::DefaultSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::Flag::f_official | MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_special)).value(); + auto &custom = sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_special)).value(); QMap read; while (!stickers.stream.atEnd()) { @@ -3149,7 +3385,7 @@ namespace Local { attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height))); } - DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation()); + DocumentData *doc = App::documentSet(id, 0, access, 0, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation()); if (!doc->sticker()) continue; if (value > 0) { @@ -3159,7 +3395,9 @@ namespace Local { custom.stickers.push_back(doc); ++custom.count; } - if (recent.size() < StickerPanPerRow * StickerPanRowsPerPage && qAbs(value) > 1) recent.push_back(qMakePair(doc, qAbs(value))); + if (recent.size() < Global::StickersRecentLimit() && qAbs(value) > 1) { + recent.push_back(qMakePair(doc, qAbs(value))); + } } if (def.stickers.isEmpty()) { sets.remove(Stickers::DefaultSetId); @@ -3168,7 +3406,7 @@ namespace Local { } if (custom.stickers.isEmpty()) sets.remove(Stickers::CustomSetId); - writeStickers(); + writeInstalledStickers(); writeUserSettings(); clearKey(_recentStickersKeyOld); @@ -3176,130 +3414,95 @@ namespace Local { _writeMap(); } - void readStickers() { - if (!_stickersKey) { + void readInstalledStickers() { + if (!_installedStickersKey) { return importOldRecentStickers(); } - FileReadDescriptor stickers; - if (!readEncryptedFile(stickers, _stickersKey)) { - clearKey(_stickersKey); - _stickersKey = 0; - _writeMap(); - return; + Global::RefStickerSets().clear(); + _readStickerSets(_installedStickersKey, &Global::RefStickerSetsOrder(), qFlags(MTPDstickerSet::Flag::f_installed)); + } + + void readFeaturedStickers() { + _readStickerSets(_featuredStickersKey, &Global::RefFeaturedStickerSetsOrder(), qFlags(MTPDstickerSet_ClientFlag::f_featured)); + + auto &sets = Global::StickerSets(); + int unreadCount = 0; + for_const (auto setId, Global::FeaturedStickerSetsOrder()) { + auto it = sets.constFind(setId); + if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) { + ++unreadCount; + } } + Global::SetFeaturedStickerSetsUnreadCount(unreadCount); + } - Stickers::Sets &sets(Global::RefStickerSets()); - sets.clear(); + void readRecentStickers() { + _readStickerSets(_recentStickersKey); + } - Stickers::Order &order(Global::RefStickerSetsOrder()); - order.clear(); - - quint32 cnt; - QByteArray hash; - stickers.stream >> cnt >> hash; // ignore hash, it is counted - if (stickers.version < 8019) { // bad data in old caches - cnt += 2; // try to read at least something - } - for (uint32 i = 0; i < cnt; ++i) { - quint64 setId = 0, setAccess = 0; - QString setTitle, setShortName; - qint32 scnt = 0; - stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt; - - qint32 setHash = 0, setFlags = 0; - if (stickers.version > 8033) { - stickers.stream >> setHash >> setFlags; - if (setFlags & qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old)) { - setFlags &= ~qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old); - setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_not_loaded); - } - } - - if (setId == Stickers::DefaultSetId) { - setTitle = lang(lng_stickers_default_set); - setFlags |= qFlags(MTPDstickerSet::Flag::f_official); - order.push_front(setId); - } else if (setId == Stickers::CustomSetId) { - setTitle = lang(lng_custom_stickers); - } else if (setId) { - order.push_back(setId); - } else { - continue; - } - Stickers::Set &set(sets.insert(setId, Stickers::Set(setId, setAccess, setTitle, setShortName, 0, setHash, MTPDstickerSet::Flags(setFlags))).value()); - if (scnt < 0) { // disabled not loaded set - set.count = -scnt; - continue; - } - - set.stickers.reserve(scnt); - - Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName); - OrderedSet read; - for (int32 j = 0; j < scnt; ++j) { - auto document = Serialize::Document::readStickerFromStream(stickers.stream, info); - if (!document || !document->sticker()) continue; - - if (read.contains(document->id)) continue; - read.insert(document->id); - - set.stickers.push_back(document); - ++set.count; - } - - if (stickers.version > 9018) { - qint32 emojiCount; - stickers.stream >> emojiCount; - for (int32 j = 0; j < emojiCount; ++j) { - QString emojiString; - qint32 stickersCount; - stickers.stream >> emojiString >> stickersCount; - StickerPack pack; - pack.reserve(stickersCount); - for (int32 k = 0; k < stickersCount; ++k) { - quint64 id; - stickers.stream >> id; - DocumentData *doc = App::document(id); - if (!doc || !doc->sticker()) continue; - - pack.push_back(doc); - } - if (EmojiPtr e = emojiGetNoColor(emojiFromText(emojiString))) { - set.emoji.insert(e, pack); - } - } - } + void readArchivedStickers() { + static bool archivedStickersRead = false; + if (!archivedStickersRead) { + _readStickerSets(_archivedStickersKey, &Global::RefArchivedStickerSetsOrder()); + archivedStickersRead = true; } } - int32 countStickersHash(bool checkOfficial) { + int32 countStickersHash(bool checkOutdatedInfo) { uint32 acc = 0; - bool foundOfficial = false, foundBad = false;; - const Stickers::Sets &sets(Global::StickerSets()); - const Stickers::Order &order(Global::StickerSetsOrder()); + bool foundOutdated = false; + auto &sets = Global::StickerSets(); + auto &order = Global::StickerSetsOrder(); for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) { auto j = sets.constFind(*i); if (j != sets.cend()) { - if (j->id == 0) { - foundBad = true; - } else if (j->flags & MTPDstickerSet::Flag::f_official) { - foundOfficial = true; - } - if (!(j->flags & MTPDstickerSet::Flag::f_disabled)) { + if (j->id == Stickers::DefaultSetId) { + foundOutdated = true; + } else if (!(j->flags & MTPDstickerSet_ClientFlag::f_special) + && !(j->flags & MTPDstickerSet::Flag::f_archived)) { acc = (acc * 20261) + j->hash; } } } - return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0; + return (!checkOutdatedInfo || !foundOutdated) ? int32(acc & 0x7FFFFFFF) : 0; + } + + int32 countRecentStickersHash() { + uint32 acc = 0; + auto &sets = Global::StickerSets(); + auto it = sets.constFind(Stickers::CloudRecentSetId); + if (it != sets.cend()) { + for_const (auto doc, it->stickers) { + auto docId = doc->id; + acc = (acc * 20261) + uint32(docId >> 32); + acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF); + } + } + return int32(acc & 0x7FFFFFFF); + } + + int32 countFeaturedStickersHash() { + uint32 acc = 0; + auto &sets = Global::StickerSets(); + auto &featured = Global::FeaturedStickerSetsOrder(); + for_const (auto setId, featured) { + acc = (acc * 20261) + uint32(setId >> 32); + acc = (acc * 20261) + uint32(setId & 0xFFFFFFFF); + + auto it = sets.constFind(setId); + if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) { + acc = (acc * 20261) + 1U; + } + } + return int32(acc & 0x7FFFFFFF); } int32 countSavedGifsHash() { uint32 acc = 0; - const SavedGifs &saved(cSavedGifs()); - for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) { - uint64 docId = (*i)->id; - + auto &saved = cSavedGifs(); + for_const (auto doc, saved) { + auto docId = doc->id; acc = (acc * 20261) + uint32(docId >> 32); acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF); } @@ -3357,7 +3560,7 @@ namespace Local { saved.reserve(cnt); OrderedSet read; for (uint32 i = 0; i < cnt; ++i) { - DocumentData *document = Serialize::Document::readFromStream(gifs.stream); + DocumentData *document = Serialize::Document::readFromStream(gifs.version, gifs.stream); if (!document || !document->isAnimation()) continue; if (read.contains(document->id)) continue; @@ -3862,8 +4065,8 @@ namespace Local { _recentStickersKeyOld = 0; _mapChanged = true; } - if (_stickersKey) { - _stickersKey = 0; + if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) { + _installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0; _mapChanged = true; } if (_recentHashtagsAndBotsKey) { diff --git a/Telegram/SourceFiles/localstorage.h b/Telegram/SourceFiles/localstorage.h index 0f9a0fd11..ca59fe65b 100644 --- a/Telegram/SourceFiles/localstorage.h +++ b/Telegram/SourceFiles/localstorage.h @@ -153,9 +153,17 @@ namespace Local { void cancelTask(TaskId id); - void writeStickers(); - void readStickers(); - int32 countStickersHash(bool checkOfficial = false); + void writeInstalledStickers(); + void writeFeaturedStickers(); + void writeRecentStickers(); + void writeArchivedStickers(); + void readInstalledStickers(); + void readFeaturedStickers(); + void readRecentStickers(); + void readArchivedStickers(); + int32 countStickersHash(bool checkOutdatedInfo = false); + int32 countRecentStickersHash(); + int32 countFeaturedStickersHash(); void writeSavedGifs(); void readSavedGifs(); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index c99aec5e1..e49d9f1ed 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -45,9 +45,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/stickersetbox.h" #include "boxes/contactsbox.h" #include "boxes/downloadpathbox.h" +#include "boxes/confirmphonebox.h" #include "localstorage.h" #include "shortcuts.h" #include "media/media_audio.h" +#include "core/qthelp_regex.h" +#include "core/qthelp_url.h" StackItemSection::StackItemSection(std_::unique_ptr &&memento) : StackItem(nullptr) , _memento(std_::move(memento)) { @@ -56,6 +59,8 @@ StackItemSection::StackItemSection(std_::unique_ptr &&me StackItemSection::~StackItemSection() { } +#include "boxes/confirmphonebox.h" + MainWidget::MainWidget(MainWindow *window) : TWidget(window) , _a_show(animation(this, &MainWidget::step_show)) , _dialogsWidth(st::dialogsWidthMin) @@ -298,11 +303,6 @@ void MainWidget::finishForwarding(History *history, bool silent) { FullMsgId newId(peerToChannel(history->peer->id), clientMsgId()); HistoryMessage *msg = static_cast(_toForward.cbegin().value()); history->addNewForwarded(newId.msg, flags, date(MTP_int(unixtime())), showFromName ? MTP::authedId() : 0, msg); - if (HistoryMedia *media = msg->getMedia()) { - if (media->type() == MediaTypeSticker) { - App::main()->incrementSticker(media->getDocument()); - } - } App::historyRegRandom(randomId, newId); } if (forwardFrom != i.value()->history()->peer) { @@ -1519,8 +1519,8 @@ void MainWidget::onSharePhoneWithBot(PeerData *recipient) { onShareContact(recipient->id, App::self()); } -void MainWidget::ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId) { - Ui::showPeerHistory(peerId, showAtMsgId); +void MainWidget::ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way) { + Ui::showPeerHistory(peerId, showAtMsgId, way); } void MainWidget::ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId) { @@ -1995,7 +1995,7 @@ void MainWidget::ctrlEnterSubmitUpdated() { _history->updateFieldSubmitSettings(); } -void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back) { +void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way) { if (PeerData *peer = App::peerLoaded(peerId)) { if (peer->migrateTo()) { peer = peer->migrateTo(); @@ -2009,8 +2009,37 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac return; } } - if (!back && (!peerId || (_stack.size() == 1 && _stack[0]->type() == HistoryStackItem && _stack[0]->peer->id == peerId))) { - back = true; + + bool back = (way == Ui::ShowWay::Backward || !peerId); + bool foundInStack = !peerId; + if (foundInStack || (way == Ui::ShowWay::ClearStack)) { + for_const (auto &item, _stack) { + clearBotStartToken(item->peer); + } + _stack.clear(); + } else { + for (int i = 0, s = _stack.size(); i < s; ++i) { + if (_stack.at(i)->type() == HistoryStackItem && _stack.at(i)->peer->id == peerId) { + foundInStack = true; + while (_stack.size() > i) { + clearBotStartToken(_stack.back()->peer); + _stack.pop_back(); + } + if (!back) { + back = true; + } + break; + } + } + } + + if (back || (way == Ui::ShowWay::ClearStack)) { + dlgUpdated(); + _peerInStack = nullptr; + _msgIdInStack = 0; + dlgUpdated(); + } else { + saveSectionInStack(); } PeerData *wasActivePeer = activePeer(); @@ -2022,10 +2051,12 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac } Window::SectionSlideParams animationParams; - if (!_a_show.animating() && ((_history->isHidden() && (_wideSection || _overview)) || (Adaptive::OneColumn() && (_history->isHidden() || !peerId)))) { + if (!_a_show.animating() && ((_history->isHidden() && (_wideSection || _overview)) || (Adaptive::OneColumn() && (_history->isHidden() || !peerId)) || back || (way == Ui::ShowWay::Forward))) { animationParams = prepareHistoryAnimation(peerId); } - if (_history->peer() && _history->peer()->id != peerId) clearBotStartToken(_history->peer()); + if (_history->peer() && _history->peer()->id != peerId) { + clearBotStartToken(_history->peer()); + } _history->showHistory(peerId, showAtMsgId); bool noPeer = (!_history->peer() || !_history->peer()->id), onlyDialogs = noPeer && Adaptive::OneColumn(); @@ -2042,11 +2073,6 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac _overview->rpcClear(); _overview = nullptr; } - clearBotStartToken(_peerInStack); - dlgUpdated(); - _peerInStack = 0; - _msgIdInStack = 0; - _stack.clear(); } if (onlyDialogs) { _topBar->hide(); @@ -2090,6 +2116,7 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac } _dialogs->update(); } + topBar()->showAll(); App::wnd()->getTitle()->updateBackButton(); } @@ -2146,6 +2173,21 @@ bool MainWidget::mediaTypeSwitch() { return true; } +void MainWidget::saveSectionInStack() { + if (_overview) { + _stack.push_back(std_::make_unique(_overview->peer(), _overview->type(), _overview->lastWidth(), _overview->lastScrollTop())); + } else if (_wideSection) { + _stack.push_back(std_::make_unique(_wideSection->createMemento())); + } else if (_history->peer()) { + dlgUpdated(); + _peerInStack = _history->peer(); + _msgIdInStack = _history->msgId(); + dlgUpdated(); + + _stack.push_back(std_::make_unique(_peerInStack, _msgIdInStack, _history->replyReturns())); + } +} + void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool back, int32 lastScrollTop) { if (peer->migrateTo()) { peer = peer->migrateTo(); @@ -2166,17 +2208,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool animationParams = prepareOverviewAnimation(); } if (!back) { - if (_overview) { - _stack.push_back(new StackItemOverview(_overview->peer(), _overview->type(), _overview->lastWidth(), _overview->lastScrollTop())); - } else if (_wideSection) { - _stack.push_back(new StackItemSection(_wideSection->createMemento())); - } else if (_history->peer()) { - dlgUpdated(); - _peerInStack = _history->peer(); - _msgIdInStack = _history->msgId(); - dlgUpdated(); - _stack.push_back(new StackItemHistory(_peerInStack, _msgIdInStack, _history->replyReturns())); - } + saveSectionInStack(); } if (_overview) { _overview->hide(); @@ -2201,7 +2233,9 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool _overview->fastShow(); } _history->animStop(); - if (back) clearBotStartToken(_history->peer()); + if (back) { + clearBotStartToken(_history->peer()); + } _history->showHistory(0, 0); _history->hide(); if (Adaptive::OneColumn()) _dialogs->hide(); @@ -2217,17 +2251,7 @@ void MainWidget::showWideSection(const Window::SectionMemento &memento) { return; } - if (_overview) { - _stack.push_back(new StackItemOverview(_overview->peer(), _overview->type(), _overview->lastWidth(), _overview->lastScrollTop())); - } else if (_wideSection) { - _stack.push_back(new StackItemSection(_wideSection->createMemento())); - } else if (_history->peer()) { - dlgUpdated(); - _peerInStack = _history->peer(); - _msgIdInStack = _history->msgId(); - dlgUpdated(); - _stack.push_back(new StackItemHistory(_peerInStack, _msgIdInStack, _history->replyReturns())); - } + saveSectionInStack(); showWideSectionAnimated(&memento, false); } @@ -2320,6 +2344,10 @@ void MainWidget::showWideSectionAnimated(const Window::SectionMemento *memento, App::wnd()->getTitle()->updateBackButton(); } +bool MainWidget::stackIsEmpty() const { + return _stack.isEmpty(); +} + void MainWidget::showBackFromStack() { if (selectingPeer()) return; if (_stack.isEmpty()) { @@ -2327,34 +2355,33 @@ void MainWidget::showBackFromStack() { if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus())); return; } - StackItem *item = _stack.back(); + auto item = std_::move(_stack.back()); _stack.pop_back(); if (auto currentHistoryPeer = _history->peer()) { clearBotStartToken(currentHistoryPeer); } if (item->type() == HistoryStackItem) { dlgUpdated(); - _peerInStack = 0; + _peerInStack = nullptr; _msgIdInStack = 0; for (int32 i = _stack.size(); i > 0;) { if (_stack.at(--i)->type() == HistoryStackItem) { - _peerInStack = static_cast(_stack.at(i))->peer; - _msgIdInStack = static_cast(_stack.at(i))->msgId; + _peerInStack = static_cast(_stack.at(i).get())->peer; + _msgIdInStack = static_cast(_stack.at(i).get())->msgId; dlgUpdated(); break; } } - StackItemHistory *histItem = static_cast(item); - Ui::showPeerHistory(histItem->peer->id, App::main()->activeMsgId(), true); + StackItemHistory *histItem = static_cast(item.get()); + Ui::showPeerHistory(histItem->peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Backward); _history->setReplyReturns(histItem->peer->id, histItem->replyReturns); } else if (item->type() == SectionStackItem) { - StackItemSection *sectionItem = static_cast(item); + StackItemSection *sectionItem = static_cast(item.get()); showWideSectionAnimated(sectionItem->memento(), true); } else if (item->type() == OverviewStackItem) { - StackItemOverview *overItem = static_cast(item); + StackItemOverview *overItem = static_cast(item.get()); showMediaOverview(overItem->peer, overItem->mediaType, true, overItem->lastScrollTop); } - delete item; } void MainWidget::orderWidgets() { @@ -3251,7 +3278,9 @@ void MainWidget::start(const MTPUser &user) { } _started = true; App::wnd()->sendServiceHistoryRequest(); - Local::readStickers(); + Local::readInstalledStickers(); + Local::readFeaturedStickers(); + Local::readRecentStickers(); Local::readSavedGifs(); _history->start(); } @@ -3262,51 +3291,50 @@ bool MainWidget::started() { void MainWidget::openLocalUrl(const QString &url) { QString u(url.trimmed()); - if (u.startsWith(qstr("tg://resolve"), Qt::CaseInsensitive)) { - QRegularExpressionMatch m = QRegularExpression(qsl("^tg://resolve/?\\?domain=([a-zA-Z0-9\\.\\_]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u); - if (m.hasMatch()) { - QString params = u.mid(m.capturedLength(0)); + if (u.size() > 8192) u = u.mid(0, 8192); - QString start, startToken; - QRegularExpressionMatch startparam = QRegularExpression(qsl("(^|&)(start|startgroup)=([a-zA-Z0-9\\.\\_\\-]+)(&|$)")).match(params); - if (startparam.hasMatch()) { - start = startparam.captured(2); - startToken = startparam.captured(3); - } + if (!u.startsWith(qstr("tg://"), Qt::CaseInsensitive)) { + return; + } - MsgId post = (start == qsl("startgroup")) ? ShowAtProfileMsgId : ShowAtUnreadMsgId; - QRegularExpressionMatch postparam = QRegularExpression(qsl("(^|&)post=(\\d+)(&|$)")).match(params); - if (postparam.hasMatch()) { - post = postparam.captured(2).toInt(); - } - - openPeerByName(m.captured(1), post, startToken); + using namespace qthelp; + auto matchOptions = RegExOption::CaseInsensitive; + if (auto joinChatMatch = regex_match(qsl("^tg://join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), u, matchOptions)) { + joinGroupByHash(joinChatMatch->captured(1)); + } else if (auto stickerSetMatch = regex_match(qsl("^tg://addstickers/?\\?set=([a-zA-Z0-9\\.\\_]+)(&|$)"), u, matchOptions)) { + stickersBox(MTP_inputStickerSetShortName(MTP_string(stickerSetMatch->captured(1)))); + } else if (auto shareUrlMatch = regex_match(qsl("^tg://msg_url/?\\?(.+)(#|$)"), u, matchOptions)) { + auto params = url_parse_params(shareUrlMatch->captured(1), UrlParamNameTransform::ToLower); + auto url = params.value(qsl("url")); + if (!url.isEmpty()) { + shareUrlLayer(url, params.value("text")); } - } else if (u.startsWith(qstr("tg://join"), Qt::CaseInsensitive)) { - QRegularExpressionMatch m = QRegularExpression(qsl("^tg://join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u); - if (m.hasMatch()) { - joinGroupByHash(m.captured(1)); + } else if (auto confirmPhoneMatch = regex_match(qsl("^tg://confirmphone/?\\?(.+)(#|$)"), u, matchOptions)) { + auto params = url_parse_params(confirmPhoneMatch->captured(1), UrlParamNameTransform::ToLower); + auto phone = params.value(qsl("phone")); + auto hash = params.value(qsl("hash")); + if (!phone.isEmpty() && !hash.isEmpty()) { + ConfirmPhoneBox::start(phone, hash); } - } else if (u.startsWith(qstr("tg://addstickers"), Qt::CaseInsensitive)) { - QRegularExpressionMatch m = QRegularExpression(qsl("^tg://addstickers/?\\?set=([a-zA-Z0-9\\.\\_]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u); - if (m.hasMatch()) { - stickersBox(MTP_inputStickerSetShortName(MTP_string(m.captured(1)))); - } - } else if (u.startsWith(qstr("tg://msg_url"), Qt::CaseInsensitive)) { - QRegularExpressionMatch m = QRegularExpression(qsl("^tg://msg_url/?\\?(.+)(#|$)"), QRegularExpression::CaseInsensitiveOption).match(u); - if (m.hasMatch()) { - QStringList params = m.captured(1).split('&'); - QString url, text; - for (int32 i = 0, l = params.size(); i < l; ++i) { - if (params.at(i).startsWith(qstr("url="), Qt::CaseInsensitive)) { - url = myUrlDecode(params.at(i).mid(4)); - } else if (params.at(i).startsWith(qstr("text="), Qt::CaseInsensitive)) { - text = myUrlDecode(params.at(i).mid(5)); + } else if (auto usernameMatch = regex_match(qsl("^tg://resolve/?\\?(.+)(#|$)"), u, matchOptions)) { + auto params = url_parse_params(usernameMatch->captured(1), UrlParamNameTransform::ToLower); + auto domain = params.value(qsl("domain")); + if (auto domainMatch = regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), domain, matchOptions)) { + auto start = qsl("start"); + auto startToken = params.value(start); + if (startToken.isEmpty()) { + start = qsl("startgroup"); + startToken = params.value(start); + if (startToken.isEmpty()) { + start = QString(); } } - if (!url.isEmpty()) { - shareUrlLayer(url, text); + auto post = (start == qsl("startgroup")) ? ShowAtProfileMsgId : ShowAtUnreadMsgId; + auto postParam = params.value(qsl("post")); + if (auto postId = postParam.toInt()) { + post = postId; } + openPeerByName(domain, post, startToken); } } } @@ -3322,7 +3350,7 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr Ui::showLayer(new ContactsBox(peer->asUser())); } else if (peer->isUser() && peer->asUser()->botInfo) { // Always open bot chats, even from mention links. - Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId); + Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); } else { Ui::showPeerProfile(peer); } @@ -3337,7 +3365,7 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr _history->resizeEvent(0); } } - Ui::showPeerHistoryAsync(peer->id, msgId); + Ui::showPeerHistoryAsync(peer->id, msgId, Ui::ShowWay::Forward); } } else { MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, qMakePair(msgId, startToken)), rpcFail(&MainWidget::usernameResolveFail, username)); @@ -3357,7 +3385,6 @@ void MainWidget::stickersBox(const MTPInputStickerSet &set) { } void MainWidget::onStickersInstalled(uint64 setId) { - emit stickersUpdated(); _history->stickersInstalled(setId); } @@ -3405,7 +3432,7 @@ void MainWidget::usernameResolveDone(QPair msgIdAndStartToken, c Ui::showLayer(new ContactsBox(peer->asUser())); } else if (peer->isUser() && peer->asUser()->botInfo) { // Always open bot chats, even from mention links. - Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId); + Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); } else { Ui::showPeerProfile(peer); } @@ -3436,11 +3463,21 @@ bool MainWidget::usernameResolveFail(QString name, const RPCError &error) { void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) { switch (invite.type()) { case mtpc_chatInvite: { - const auto &d(invite.c_chatInvite()); - ConfirmBox *box = new ConfirmBox(((d.is_channel() && !d.is_megagroup()) ? lng_group_invite_want_join_channel : lng_group_invite_want_join)(lt_title, qs(d.vtitle)), lang(lng_group_invite_join)); + auto &d(invite.c_chatInvite()); + + QVector participants; + if (d.has_participants()) { + auto &v = d.vparticipants.c_vector().v; + participants.reserve(v.size()); + for_const (auto &user, v) { + if (auto feededUser = App::feedUser(user)) { + participants.push_back(feededUser); + } + } + } + auto box = std_::make_unique(qs(d.vtitle), d.vphoto, d.vparticipants_count.v, participants); _inviteHash = hash; - connect(box, SIGNAL(confirmed()), this, SLOT(onInviteImport())); - Ui::showLayer(box); + Ui::showLayer(box.release()); } break; case mtpc_chatInviteAlready: { @@ -3618,72 +3655,65 @@ void MainWidget::updateNotifySetting(PeerData *peer, NotifySettingStatus notify, void MainWidget::incrementSticker(DocumentData *sticker) { if (!sticker || !sticker->sticker()) return; + if (sticker->sticker()->set.type() == mtpc_inputStickerSetEmpty) return; - RecentStickerPack &recent(cGetRecentStickers()); - RecentStickerPack::iterator i = recent.begin(), e = recent.end(); - for (; i != e; ++i) { + bool writeRecentStickers = false; + auto &sets = Global::RefStickerSets(); + auto it = sets.find(Stickers::CloudRecentSetId); + if (it == sets.cend()) { + if (it == sets.cend()) { + it = sets.insert(Stickers::CloudRecentSetId, Stickers::Set(Stickers::CloudRecentSetId, 0, lang(lng_recent_stickers), QString(), 0, 0, qFlags(MTPDstickerSet_ClientFlag::f_special))); + } else { + it->title = lang(lng_recent_stickers); + } + } + auto index = it->stickers.indexOf(sticker); + if (index > 0) { + it->stickers.removeAt(index); + } + if (index) { + it->stickers.push_front(sticker); + writeRecentStickers = true; + } + + // Remove that sticker from old recent, now it is in cloud recent stickers. + bool writeOldRecent = false; + auto &recent = cGetRecentStickers(); + for (auto i = recent.begin(), e = recent.end(); i != e; ++i) { if (i->first == sticker) { - i->second = recent.begin()->second; // throw to the first place - //++i->second; - //if (i->second > 0x8000) { - // for (RecentStickerPack::iterator j = recent.begin(); j != e; ++j) { - // if (j->second > 1) { - // j->second /= 2; - // } else { - // j->second = 1; - // } - // } - //} - for (; i != recent.begin(); --i) { - if ((i - 1)->second > i->second) { - break; - } - qSwap(*i, *(i - 1)); - } + writeOldRecent = true; + recent.erase(i); break; } } - if (i == e) { - while (recent.size() >= StickerPanPerRow * StickerPanRowsPerPage) recent.pop_back(); - recent.push_front(qMakePair(sticker, recent.isEmpty() ? 1 : recent.begin()->second)); - //recent.push_back(qMakePair(sticker, 1)); - //for (i = recent.end() - 1; i != recent.begin(); --i) { - // if ((i - 1)->second > i->second) { - // break; - // } - // qSwap(*i, *(i - 1)); - //} + while (!recent.isEmpty() && it->stickers.size() + recent.size() > Global::StickersRecentLimit()) { + writeOldRecent = true; + recent.pop_back(); } - Local::writeUserSettings(); - - bool found = false; - uint64 setId = 0; - QString setName; - switch (sticker->sticker()->set.type()) { - case mtpc_inputStickerSetID: setId = sticker->sticker()->set.c_inputStickerSetID().vid.v; break; - case mtpc_inputStickerSetShortName: setName = qs(sticker->sticker()->set.c_inputStickerSetShortName().vshort_name).toLower().trimmed(); break; + if (writeOldRecent) { + Local::writeUserSettings(); } - Stickers::Sets &sets(Global::RefStickerSets()); - for (auto i = sets.cbegin(); i != sets.cend(); ++i) { - if (i->id == Stickers::CustomSetId || i->id == Stickers::DefaultSetId || (setId && i->id == setId) || (!setName.isEmpty() && i->shortName.toLower().trimmed() == setName)) { - for (int32 j = 0, l = i->stickers.size(); j < l; ++j) { - if (i->stickers.at(j) == sticker) { - found = true; - break; - } + + // Remove that sticker from custom stickers, now it is in cloud recent stickers. + bool writeInstalledStickers = false; + auto custom = sets.find(Stickers::CustomSetId); + if (custom != sets.cend()) { + int removeIndex = custom->stickers.indexOf(sticker); + if (removeIndex >= 0) { + custom->stickers.removeAt(removeIndex); + if (custom->stickers.isEmpty()) { + sets.erase(custom); } - if (found) break; + writeInstalledStickers = true; } } - if (!found) { - Stickers::Sets::iterator it = sets.find(Stickers::CustomSetId); - if (it == sets.cend()) { - it = sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)); - } - it->stickers.push_back(sticker); - ++it->count; - Local::writeStickers(); + + if (writeInstalledStickers) { + Local::writeInstalledStickers(); + } + if (writeRecentStickers) { + Local::writeRecentStickers(); } _history->updateRecentStickers(); } @@ -4628,16 +4658,23 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { ////// Cloud sticker sets case mtpc_updateNewStickerSet: { - const auto &d(update.c_updateNewStickerSet()); + auto &d = update.c_updateNewStickerSet(); + bool writeArchived = false; if (d.vstickerset.type() == mtpc_messages_stickerSet) { - const auto &set(d.vstickerset.c_messages_stickerSet()); + auto &set = d.vstickerset.c_messages_stickerSet(); if (set.vset.type() == mtpc_stickerSet) { - const auto &s(set.vset.c_stickerSet()); + auto &s = set.vset.c_stickerSet(); - Stickers::Sets &sets(Global::RefStickerSets()); + auto &sets = Global::RefStickerSets(); auto it = sets.find(s.vid.v); if (it == sets.cend()) { - it = sets.insert(s.vid.v, Stickers::Set(s.vid.v, s.vaccess_hash.v, stickerSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v)); + it = sets.insert(s.vid.v, Stickers::Set(s.vid.v, s.vaccess_hash.v, stickerSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v | MTPDstickerSet::Flag::f_installed)); + } else { + it->flags |= MTPDstickerSet::Flag::f_installed; + if (it->flags & MTPDstickerSet::Flag::f_archived) { + it->flags &= ~MTPDstickerSet::Flag::f_archived; + writeArchived = true; + } } const auto &v(set.vdocuments.c_vector().v); @@ -4650,12 +4687,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { it->stickers.push_back(doc); } it->emoji.clear(); - const auto &packs(set.vpacks.c_vector().v); + auto &packs = set.vpacks.c_vector().v; for (int32 i = 0, l = packs.size(); i < l; ++i) { if (packs.at(i).type() != mtpc_stickerPack) continue; - const auto &pack(packs.at(i).c_stickerPack()); + auto &pack = packs.at(i).c_stickerPack(); if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) { - const auto &stickers(pack.vdocuments.c_vector().v); + auto &stickers = pack.vdocuments.c_vector().v; StickerPack p; p.reserve(stickers.size()); for (int32 j = 0, c = stickers.size(); j < c; ++j) { @@ -4687,16 +4724,17 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { sets.erase(custom); } } - Local::writeStickers(); + Local::writeInstalledStickers(); + if (writeArchived) Local::writeArchivedStickers(); emit stickersUpdated(); } } } break; case mtpc_updateStickerSetsOrder: { - const auto &d(update.c_updateStickerSetsOrder()); - const auto &order(d.vorder.c_vector().v); - const auto &sets(Global::StickerSets()); + auto &d = update.c_updateStickerSetsOrder(); + auto &order = d.vorder.c_vector().v; + auto &sets = Global::StickerSets(); Stickers::Order result; for (int32 i = 0, l = order.size(); i < l; ++i) { if (sets.constFind(order.at(i).v) == sets.cend()) { @@ -4709,7 +4747,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { App::main()->updateStickers(); } else { Global::SetStickerSetsOrder(result); - Local::writeStickers(); + Local::writeInstalledStickers(); emit stickersUpdated(); } } break; @@ -4719,6 +4757,24 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { App::main()->updateStickers(); } break; + case mtpc_updateRecentStickers: { + Global::SetLastStickersUpdate(0); + App::main()->updateStickers(); + } break; + + case mtpc_updateReadFeaturedStickers: { + for (auto &set : Global::RefStickerSets()) { + if (set.flags & MTPDstickerSet_ClientFlag::f_unread) { + set.flags &= ~MTPDstickerSet_ClientFlag::f_unread; + } + } + if (Global::FeaturedStickerSetsUnreadCount()) { + Global::SetFeaturedStickerSetsUnreadCount(0); + Local::writeFeaturedStickers(); + emit stickersUpdated(); + } + } break; + ////// Cloud saved GIFs case mtpc_updateSavedGifs: { cSetLastSavedGifsUpdate(0); diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index c6a41c918..0ee2899c7 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -108,27 +108,6 @@ public: int32 lastWidth, lastScrollTop; }; -class StackItems : public QVector { -public: - bool contains(PeerData *peer) const { - for (int32 i = 0, l = size(); i < l; ++i) { - if (at(i)->peer == peer) { - return true; - } - } - return false; - } - void clear() { - for (int32 i = 0, l = size(); i < l; ++i) { - delete at(i); - } - QVector::clear(); - } - ~StackItems() { - clear(); - } -}; - enum SilentNotifiesStatus { SilentNotifiesDontChange, SilentNotifiesSetSilent, @@ -224,6 +203,7 @@ public: bool mediaTypeSwitch(); void showWideSection(const Window::SectionMemento &memento); void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1); + bool stackIsEmpty() const; void showBackFromStack(); void orderWidgets(); QRect historyRect() const; @@ -404,7 +384,7 @@ public: void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout); bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout); bool ui_isInlineItemBeingChosen(); - void ui_showPeerHistory(quint64 peer, qint32 msgId, bool back); + void ui_showPeerHistory(quint64 peer, qint32 msgId, Ui::ShowWay way); PeerData *ui_getPeerForMouseAction(); void notify_botCommandsChanged(UserData *bot); @@ -492,7 +472,7 @@ public slots: void onSharePhoneWithBot(PeerData *recipient); - void ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId); + void ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way); void ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId); private slots: @@ -518,6 +498,8 @@ private: Window::SectionSlideParams prepareOverviewAnimation(); Window::SectionSlideParams prepareDialogsAnimation(); + void saveSectionInStack(); + bool _started = false; uint64 failedObjId = 0; @@ -597,7 +579,7 @@ private: ChildWidget _topBar; ConfirmBox *_forwardConfirm = nullptr; // for single column layout ChildWidget _hider = { nullptr }; - StackItems _stack; + std_::vector_of_moveable> _stack; PeerData *_peerInStack = nullptr; MsgId _msgIdInStack = 0; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 88e49d8a0..0fe9a2283 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -1072,7 +1072,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *e) { if (obj == Application::instance()) { QString url = static_cast(e)->url().toEncoded().trimmed(); if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) { - cSetStartUrl(url); + cSetStartUrl(url.mid(0, 8192)); if (!cStartUrl().isEmpty() && App::main() && App::self()) { App::main()->openLocalUrl(cStartUrl()); cSetStartUrl(QString()); diff --git a/Telegram/SourceFiles/media/media_clip_reader.cpp b/Telegram/SourceFiles/media/media_clip_reader.cpp index f310dd1b9..49ddc2f06 100644 --- a/Telegram/SourceFiles/media/media_clip_reader.cpp +++ b/Telegram/SourceFiles/media/media_clip_reader.cpp @@ -110,7 +110,7 @@ Reader::Reader(const FileLocation &location, const QByteArray &data, Callback && } Reader::Frame *Reader::frameToShow(int32 *index) const { // 0 means not ready - int32 step = _step.loadAcquire(), i; + int step = _step.loadAcquire(), i; if (step == WaitingForDimensionsStep) { if (index) *index = 0; return nullptr; @@ -205,8 +205,8 @@ void Reader::start(int32 framew, int32 frameh, int32 outerw, int32 outerh, Image } QPixmap Reader::current(int32 framew, int32 frameh, int32 outerw, int32 outerh, uint64 ms) { - Frame *frame = frameToShow(); - t_assert(frame != 0); + auto frame = frameToShow(); + t_assert(frame != nullptr); if (ms) { frame->displayed.storeRelease(1); diff --git a/Telegram/SourceFiles/media/view/media_clip_controller.cpp b/Telegram/SourceFiles/media/view/media_clip_controller.cpp index 18c43dbae..796aee8cc 100644 --- a/Telegram/SourceFiles/media/view/media_clip_controller.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_controller.cpp @@ -183,17 +183,17 @@ void Controller::grabFinish() { void Controller::resizeEvent(QResizeEvent *e) { int playTop = (height() - _playPauseResume->height()) / 2; - _playPauseResume->moveToLeft(playTop, playTop); + _playPauseResume->moveToLeft(st::mediaviewPlayPauseLeft, playTop); int fullScreenTop = (height() - _fullScreenToggle->height()) / 2; - _fullScreenToggle->moveToRight(fullScreenTop, fullScreenTop); + _fullScreenToggle->moveToRight(st::mediaviewFullScreenLeft, fullScreenTop); - _volumeController->moveToRight(fullScreenTop + _fullScreenToggle->width() + fullScreenTop, (height() - _volumeController->height()) / 2); - _playback->resize(width() - playTop - _playPauseResume->width() - playTop - fullScreenTop - _volumeController->width() - fullScreenTop - _fullScreenToggle->width() - fullScreenTop, _volumeController->height()); - _playback->moveToLeft(playTop + _playPauseResume->width() + playTop, st::mediaviewPlaybackTop); + _volumeController->moveToRight(st::mediaviewFullScreenLeft + _fullScreenToggle->width() + st::mediaviewVolumeLeft, (height() - _volumeController->height()) / 2); + _playback->resize(width() - st::mediaviewPlayPauseLeft - _playPauseResume->width() - playTop - fullScreenTop - _volumeController->width() - st::mediaviewVolumeLeft - _fullScreenToggle->width() - st::mediaviewFullScreenLeft, st::mediaviewSeekSize.height()); + _playback->moveToLeft(st::mediaviewPlayPauseLeft + _playPauseResume->width() + playTop, st::mediaviewPlaybackTop); - _playedAlready->moveToLeft(playTop + _playPauseResume->width() + playTop, st::mediaviewPlayProgressTop); - _toPlayLeft->moveToRight(width() - (playTop + _playPauseResume->width() + playTop) - _playback->width(), st::mediaviewPlayProgressTop); + _playedAlready->moveToLeft(st::mediaviewPlayPauseLeft + _playPauseResume->width() + playTop, st::mediaviewPlayProgressTop); + _toPlayLeft->moveToRight(width() - (st::mediaviewPlayPauseLeft + _playPauseResume->width() + playTop) - _playback->width(), st::mediaviewPlayProgressTop); } void Controller::paintEvent(QPaintEvent *e) { diff --git a/Telegram/SourceFiles/media/view/media_clip_playback.cpp b/Telegram/SourceFiles/media/view/media_clip_playback.cpp index 2b1f82148..6dfbaed15 100644 --- a/Telegram/SourceFiles/media/view/media_clip_playback.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_playback.cpp @@ -61,6 +61,7 @@ void Playback::updateState(const AudioPlaybackState &playbackState, bool reset) _position = position; _duration = duration; } + update(); } void Playback::setFadeOpacity(float64 opacity) { @@ -87,7 +88,9 @@ void Playback::paintEvent(QPaintEvent *e) { p.setPen(Qt::NoPen); p.setRenderHint(QPainter::HighQualityAntialiasing); - auto over = _a_over.current(getms(), _over ? 1. : 0.); + auto ms = getms(); + _a_progress.step(ms); + auto over = _a_over.current(ms, _over ? 1. : 0.); int skip = (st::mediaviewSeekSize.width() / 2); int length = (width() - st::mediaviewSeekSize.width()); float64 prg = _mouseDown ? _downProgress : a_progress.current(); @@ -104,11 +107,17 @@ void Playback::paintEvent(QPaintEvent *e) { p.setBrush(st::mediaviewPlaybackInactive); p.drawRoundedRect(mid - radius, (height() - st::mediaviewPlaybackWidth) / 2, width() - (mid - radius), st::mediaviewPlaybackWidth, radius, radius); } - int x = mid - skip; - p.setClipRect(rect()); - p.setOpacity(_fadeOpacity * (over * st::mediaviewActiveOpacity + (1. - over) * st::mediaviewInactiveOpacity)); - p.setBrush(st::mediaviewPlaybackActive); - p.drawRoundedRect(x, (height() - st::mediaviewSeekSize.height()) / 2, st::mediaviewSeekSize.width(), st::mediaviewSeekSize.height(), st::mediaviewSeekSize.width() / 2, st::mediaviewSeekSize.width() / 2); + if (over > 0) { + int x = mid - skip; + p.setClipRect(rect()); + p.setOpacity(_fadeOpacity * st::mediaviewActiveOpacity); + auto seekButton = QRect(x, (height() - st::mediaviewSeekSize.height()) / 2, st::mediaviewSeekSize.width(), st::mediaviewSeekSize.height()); + int remove = ((1. - over) * st::mediaviewSeekSize.width()) / 2.; + if (remove * 2 < st::mediaviewSeekSize.width()) { + p.setBrush(st::mediaviewPlaybackActive); + p.drawEllipse(seekButton.marginsRemoved(QMargins(remove, remove, remove, remove))); + } + } } void Playback::mouseMoveEvent(QMouseEvent *e) { diff --git a/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp b/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp index 8a98dec90..8ffed03f2 100644 --- a/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp @@ -40,7 +40,7 @@ void VolumeController::setVolume(float64 volume) { void VolumeController::paintEvent(QPaintEvent *e) { Painter p(this); - int32 top = (height() - st::mediaviewVolumeIcon.height()) / 2; + int32 top = st::mediaviewVolumeIconTop; int32 left = (width() - st::mediaviewVolumeIcon.width()) / 2; int32 mid = left + qRound(st::mediaviewVolumeIcon.width() * _volume); int32 right = left + st::mediaviewVolumeIcon.width(); diff --git a/Telegram/SourceFiles/media/view/mediaview.style b/Telegram/SourceFiles/media/view/mediaview.style index 98e48c6e1..ef83075fc 100644 --- a/Telegram/SourceFiles/media/view/mediaview.style +++ b/Telegram/SourceFiles/media/view/mediaview.style @@ -31,7 +31,7 @@ mediaviewPlayProgressLabel: LabelSimple(defaultLabelSimple) { font: semiboldFont; textFg: #ffffffc7; } -mediaviewPlayProgressTop: 8px; +mediaviewPlayProgressTop: 11px; mediaviewPlayButton: IconButton { width: 25px; height: 24px; @@ -40,7 +40,7 @@ mediaviewPlayButton: IconButton { overOpacity: mediaviewActiveOpacity; icon: icon { - { "media_play", #ffffff, point(0px, 0px) }, + { "media_play", #ffffff, point(3px, 0px) }, }; iconPosition: point(3px, 1px); downIconPosition: point(3px, 1px); @@ -50,13 +50,16 @@ mediaviewPlayButton: IconButton { mediaviewPauseIcon: icon { { "media_pause", #ffffff, point(1px, 1px) } }; +mediaviewPlayPauseLeft: 17px; +mediaviewFullScreenLeft: 17px; +mediaviewVolumeLeft: 15px; mediaviewFullScreenButton: IconButton(mediaviewPlayButton) { icon: icon { { "media_fullscreen_to", #ffffff, point(0px, 0px) }, }; - iconPosition: point(0px, 0px); - downIconPosition: point(0px, 0px); + iconPosition: point(0px, 1px); + downIconPosition: point(0px, 1px); } mediaviewFullScreenOutIcon: icon { { "media_fullscreen_from", #ffffff, point(0px, 0px) }, @@ -65,13 +68,15 @@ mediaviewFullScreenOutIcon: icon { mediaviewPlaybackActive: #ffffff; mediaviewPlaybackInactive: #474747; mediaviewPlaybackWidth: 3px; -mediaviewPlaybackTop: 23px; -mediaviewSeekSize: size(2px, 13px); +mediaviewPlaybackTop: 28px; +mediaviewSeekSize: size(11px, 11px); -mediaviewVolumeSize: size(44px, 12px); +mediaviewVolumeSize: size(44px, 20px); mediaviewVolumeIcon: icon { { "media_volume", mediaviewPlaybackInactive, point(0px, 0px) }, }; mediaviewVolumeOnIcon: icon { { "media_volume", mediaviewPlaybackActive, point(0px, 0px) }, }; +mediaviewVolumeIconTop: 8px; +mediaviewControllerRadius: 25px; diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index f03dacae2..62307f3bd 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -731,7 +731,10 @@ void MediaView::clipCallback(Media::Clip::Notification notification) { case NotificationReinit: { if (auto item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid)) { if (_gif->state() == State::Error) { - _current = QPixmap(); + stopGif(); + updateControls(); + update(); + break; } else if (_gif->state() == State::Finished) { _videoPositionMs = _videoDurationMs; _videoStopped = true; @@ -1118,7 +1121,10 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) { void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty messages shown as docs: doc can be NULL if (!doc || (!doc->isAnimation() && !doc->isVideo()) || doc != _doc || (item && (item->id != _msgid || (item->history() != (_msgmigrated ? _migrated : _history))))) { _fullScreenVideo = false; + _current = QPixmap(); stopGif(); + } else if (gifShown()) { + _current = QPixmap(); } _doc = doc; _photo = nullptr; @@ -1128,8 +1134,6 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty _autoplayVideoDocument = nullptr; } - _current = QPixmap(); - _caption = Text(); if (_doc) { if (_doc->sticker()) { @@ -1556,7 +1560,7 @@ void MediaView::paintEvent(QPaintEvent *e) { if (_saveMsgOpacity.current() > 0) { p.setOpacity(_saveMsgOpacity.current()); App::roundRect(p, _saveMsg, st::medviewSaveMsg, MediaviewSaveCorners); - p.drawSprite(_saveMsg.topLeft() + st::medviewSaveMsgCheckPos, st::medviewSaveMsgCheck); + st::medviewSaveMsgCheck.paint(p, _saveMsg.topLeft() + st::medviewSaveMsgCheckPos, width()); p.setPen(st::white->p); textstyleSet(&st::medviewSaveAsTextStyle); diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 0fed750d1..846b8ef71 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -1060,8 +1060,17 @@ enum class MTPDstickerSet_ClientFlag : int32 { // sticker set is not yet loaded f_not_loaded = (1 << 30), + // sticker set is one of featured (should be saved locally) + f_featured = (1 << 29), + + // sticker set is an unread featured set + f_unread = (1 << 28), + + // special set like recent or custom stickers + f_special = (1 << 27), + // update this when adding new client side flags - MIN_FIELD = (1 << 30), + MIN_FIELD = (1 << 27), }; DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet) diff --git a/Telegram/SourceFiles/mtproto/dcenter.cpp b/Telegram/SourceFiles/mtproto/dcenter.cpp index 7043e26b9..f15fd2fc4 100644 --- a/Telegram/SourceFiles/mtproto/dcenter.cpp +++ b/Telegram/SourceFiles/mtproto/dcenter.cpp @@ -170,6 +170,7 @@ namespace { Global::SetPushChatLimit(data.vpush_chat_limit.v); // ? Global::SetSavedGifsLimit(data.vsaved_gifs_limit.v); Global::SetEditTimeLimit(data.vedit_time_limit.v); // ? + Global::SetStickersRecentLimit(data.vstickers_recent_limit.v); configLoadedOnce = true; Local::writeSettings(); diff --git a/Telegram/SourceFiles/mtproto/file_download.cpp b/Telegram/SourceFiles/mtproto/file_download.cpp index d8c588eee..0b8997325 100644 --- a/Telegram/SourceFiles/mtproto/file_download.cpp +++ b/Telegram/SourceFiles/mtproto/file_download.cpp @@ -351,13 +351,8 @@ void FileLoader::startLoading(bool loadFirst, bool prior) { mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading) : FileLoader(QString(), size, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading) -, _lastComplete(false) -, _skippedBytes(0) -, _nextRequestOffset(0) , _dc(location->dc()) -, _location(location) -, _id(0) -, _access(0) { +, _location(location) { LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0)); if (i == queues.cend()) { i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries)); @@ -365,15 +360,12 @@ mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, L _queue = &i.value(); } -mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading) +mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, int32 version, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading) : FileLoader(to, size, type, toCache, fromCloud, autoLoading) -, _lastComplete(false) -, _skippedBytes(0) -, _nextRequestOffset(0) , _dc(dc) -, _location(0) , _id(id) -, _access(access) { +, _access(access) +, _version(version) { LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0)); if (i == queues.cend()) { i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries)); @@ -422,7 +414,7 @@ bool mtpFileLoader::loadPart() { switch (_locationType) { case VideoFileLocation: case AudioFileLocation: - case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access)); break; + case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access), MTP_int(_version)); break; default: cancel(true); return false; break; } } @@ -532,7 +524,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe if (_localStatus == LocalNotFound || _localStatus == LocalFailed) { if (_locationType != UnknownFileLocation) { // audio, video, document - MediaKey mkey = mediaKey(_locationType, _dc, _id); + MediaKey mkey = mediaKey(_locationType, _dc, _id, _version); if (!_fname.isEmpty()) { Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(_type), _fname)); } @@ -594,7 +586,7 @@ bool mtpFileLoader::tryLoadLocal() { _localTaskId = Local::startImageLoad(storageKey(*_location), this); } else { if (_toCache == LoadToCacheAsWell) { - MediaKey mkey = mediaKey(_locationType, _dc, _id); + MediaKey mkey = mediaKey(_locationType, _dc, _id, _version); if (_locationType == DocumentFileLocation) { _localTaskId = Local::startStickerImageLoad(mkey, this); } else if (_locationType == AudioFileLocation) { diff --git a/Telegram/SourceFiles/mtproto/file_download.h b/Telegram/SourceFiles/mtproto/file_download.h index f8a05d7ea..94b65fb2b 100644 --- a/Telegram/SourceFiles/mtproto/file_download.h +++ b/Telegram/SourceFiles/mtproto/file_download.h @@ -28,6 +28,8 @@ namespace MTP { enum LocationType { UnknownFileLocation = 0, + // 1, 2, etc are used as "version" value in mediaKey() method. + DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation @@ -221,9 +223,8 @@ class mtpFileLoader : public FileLoader, public RPCSender { Q_OBJECT public: - mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading); - mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading); + mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, int32 version, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading); virtual int32 currentOffset(bool includeSkipped = false) const; @@ -245,7 +246,6 @@ public: ~mtpFileLoader(); protected: - virtual bool tryLoadLocal(); virtual void cancelRequests(); @@ -256,15 +256,16 @@ protected: void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req); bool partFailed(const RPCError &error); - bool _lastComplete; - int32 _skippedBytes; - int32 _nextRequestOffset; + bool _lastComplete = false; + int32 _skippedBytes = 0; + int32 _nextRequestOffset = 0; int32 _dc; - const StorageImageLocation *_location; + const StorageImageLocation *_location = nullptr; - uint64 _id; // for other locations - uint64 _access; + uint64 _id = 0; // for other locations + uint64 _access = 0; + int32 _version = 0; }; diff --git a/Telegram/SourceFiles/mtproto/generate.py b/Telegram/SourceFiles/mtproto/generate.py index 9d2537339..aaa0ecc94 100644 --- a/Telegram/SourceFiles/mtproto/generate.py +++ b/Telegram/SourceFiles/mtproto/generate.py @@ -136,8 +136,10 @@ with open('scheme.tl') as f: cleanline = cleanline.replace('?bytes ', '?string '); cleanline = cleanline.replace('{', ''); cleanline = cleanline.replace('}', ''); - countTypeId = hex(binascii.crc32(binascii.a2b_qp(cleanline)))[2:]; - countTypeId = '0x' + countTypeId; + countTypeId = binascii.crc32(binascii.a2b_qp(cleanline)); + if (countTypeId < 0): + countTypeId += 2 ** 32; + countTypeId = '0x' + re.sub(r'^0x|L$', '', hex(countTypeId)); if (typeid != countTypeId): print('Warning: counted ' + countTypeId + ' mismatch with provided ' + typeid + ' (' + cleanline + ')'); continue; diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index 0e5f0b11d..c418d0fdf 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -111,7 +111,7 @@ ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong; destroy_session#e7512126 session_id:long = DestroySessionRes; -#contest.saveDeveloperInfo#9a5f6e95 vk_id:int name:string phone_number:string age:int city:string = Bool; +contest.saveDeveloperInfo#9a5f6e95 vk_id:int name:string phone_number:string age:int city:string = Bool; /////////////////////////////// ///////// Main application API @@ -168,7 +168,7 @@ inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto; inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation; inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation; -inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation; +inputDocumentFileLocation#430f0724 id:long access_hash:long version:int = InputFileLocation; inputPhotoCropAuto#ade6b004 = InputPhotoCrop; inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop; @@ -392,6 +392,8 @@ updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update; updateInlineBotCallbackQuery#2cbd95af query_id:long user_id:int msg_id:InputBotInlineMessageID data:bytes = Update; updateReadChannelOutbox#25d6c9c7 channel_id:int max_id:int = Update; updateDraftMessage#ee2bb969 peer:Peer draft:DraftMessage = Update; +updateReadFeaturedStickers#571d2742 = Update; +updateRecentStickers#9a422c20 = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -416,7 +418,7 @@ upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File; dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true id:int ip_address:string port:int = DcOption; -config#c9411388 date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int disabled_features:Vector = Config; +config#f401a4bf date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int disabled_features:Vector = Config; nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc; @@ -454,7 +456,7 @@ inputDocumentEmpty#72f0eaae = InputDocument; inputDocument#18798952 id:long access_hash:long = InputDocument; documentEmpty#36f8c871 id:long = Document; -document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector = Document; +document#87232bc7 id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int version:int attributes:Vector = Document; help.support#17c6b5f6 phone_number:string user:User = help.Support; @@ -547,13 +549,13 @@ chatInviteEmpty#69df3769 = ExportedChatInvite; chatInviteExported#fc2e05bc link:string = ExportedChatInvite; chatInviteAlready#5a686d7c chat:Chat = ChatInvite; -chatInvite#93e99b60 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string = ChatInvite; +chatInvite#db74f558 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:ChatPhoto participants_count:int participants:flags.4?Vector = ChatInvite; inputStickerSetEmpty#ffb62b95 = InputStickerSet; inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet; inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet; -stickerSet#cd303b41 flags:# installed:flags.0?true disabled:flags.1?true official:flags.2?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet; +stickerSet#cd303b41 flags:# installed:flags.0?true archived:flags.1?true official:flags.2?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet; messages.stickerSet#b60a24a6 set:StickerSet packs:Vector documents:Vector = messages.StickerSet; @@ -670,7 +672,7 @@ auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType; auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType; auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType; -messages.botCallbackAnswer#1264f1c6 flags:# alert:flags.1?true message:flags.0?string = messages.BotCallbackAnswer; +messages.botCallbackAnswer#b10df1fb flags:# alert:flags.1?true message:flags.0?string url:flags.2?string = messages.BotCallbackAnswer; messages.messageEditData#26b5dde6 flags:# caption:flags.0?true = messages.MessageEditData; @@ -696,6 +698,19 @@ contacts.topPeers#70b772a8 categories:Vector chats:Vector< draftMessageEmpty#ba4baec5 = DraftMessage; draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int message:string entities:flags.3?Vector date:int = DraftMessage; +messages.featuredStickersNotModified#4ede3cf = messages.FeaturedStickers; +messages.featuredStickers#f89d88e5 hash:int sets:Vector unread:Vector = messages.FeaturedStickers; + +messages.recentStickersNotModified#b17f890 = messages.RecentStickers; +messages.recentStickers#5ce20970 hash:int stickers:Vector = messages.RecentStickers; + +messages.archivedStickers#4fcba9c8 count:int sets:Vector = messages.ArchivedStickers; + +messages.stickerSetInstallResultSuccess#38641628 = messages.StickerSetInstallResult; +messages.stickerSetInstallResultArchive#35e410a8 sets:Vector = messages.StickerSetInstallResult; + +stickerSetCovered#6410a5d2 set:StickerSet cover:Document = StickerSetCovered; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -745,6 +760,8 @@ account.resetAuthorization#df77f3bc hash:long = Bool; account.getPassword#548a30f5 = account.Password; account.getPasswordSettings#bc8d11bb current_password_hash:bytes = account.PasswordSettings; account.updatePasswordSettings#fa7c4b86 current_password_hash:bytes new_settings:account.PasswordInputSettings = Bool; +account.sendConfirmPhoneCode#1516d7bd flags:# allow_flashcall:flags.0?true hash:string current_number:flags.0?Bool = auth.SentCode; +account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool; users.getUsers#d91a548 id:Vector = Vector; users.getFullUser#ca30a5b1 id:InputUser = UserFull; @@ -806,7 +823,7 @@ messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite; messages.checkChatInvite#3eadb1bb hash:string = ChatInvite; messages.importChatInvite#6c50051c hash:string = Updates; messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet; -messages.installStickerSet#7b30c3a6 stickerset:InputStickerSet disabled:Bool = Bool; +messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult; messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool; messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates; messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector increment:Bool = Vector; @@ -826,10 +843,17 @@ messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEdi messages.editMessage#ce91e4ca flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector = Updates; messages.editInlineBotMessage#130c2c85 flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector = Bool; messages.getBotCallbackAnswer#a6e94f04 peer:InputPeer msg_id:int data:bytes = messages.BotCallbackAnswer; -messages.setBotCallbackAnswer#481c591a flags:# alert:flags.1?true query_id:long message:flags.0?string = Bool; +messages.setBotCallbackAnswer#c927d44b flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string = Bool; messages.getPeerDialogs#2d9776b9 peers:Vector = messages.PeerDialogs; messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int peer:InputPeer message:string entities:flags.3?Vector = Bool; messages.getAllDrafts#6a3f8d65 = Updates; +messages.getFeaturedStickers#2dacca4f hash:int = messages.FeaturedStickers; +messages.readFeaturedStickers#e21cbb = Bool; +messages.getRecentStickers#99197c2c hash:int = messages.RecentStickers; +messages.saveRecentSticker#348e39bf id:InputDocument unsave:Bool = Bool; +messages.clearRecentStickers#ab02e5d2 = Bool; +messages.getUnusedStickers#4309d65b limit:int = Vector; +messages.getArchivedStickers#906e241f offset_id:long limit:int = messages.ArchivedStickers; updates.getState#edd4882a = updates.State; updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference; @@ -880,4 +904,4 @@ channels.exportMessageLink#c846d22d channel:InputChannel id:int = ExportedMessag channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates; channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates; -// LAYER 53 +// LAYER 54 diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.cpp b/Telegram/SourceFiles/mtproto/scheme_auto.cpp index 230d39b93..34298d2bd 100644 --- a/Telegram/SourceFiles/mtproto/scheme_auto.cpp +++ b/Telegram/SourceFiles/mtproto/scheme_auto.cpp @@ -828,6 +828,7 @@ void _serialize_inputDocumentFileLocation(MTPStringLogger &to, int32 stage, int3 switch (stage) { case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" version: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -3012,6 +3013,14 @@ void _serialize_updateDraftMessage(MTPStringLogger &to, int32 stage, int32 lev, } } +void _serialize_updateReadFeaturedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + to.add("{ updateReadFeaturedStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_updateRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + to.add("{ updateRecentStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -3320,7 +3329,8 @@ void _serialize_config(MTPStringLogger &to, int32 stage, int32 lev, Types &types case 17: to.add(" saved_gifs_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 18: to.add(" edit_time_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 19: to.add(" rating_e_decay: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 20: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 20: to.add(" stickers_recent_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 21: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -3672,7 +3682,8 @@ void _serialize_document(MTPStringLogger &to, int32 stage, int32 lev, Types &typ case 4: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 5: to.add(" thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 6: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 7: to.add(" attributes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 7: to.add(" version: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 8: to.add(" attributes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -4339,6 +4350,9 @@ void _serialize_chatInvite(MTPStringLogger &to, int32 stage, int32 lev, Types &t case 3: to.add(" public: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_public) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; case 4: to.add(" megagroup: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_megagroup) { to.add("YES [ BY BIT 3 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break; case 5: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 6: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 7: to.add(" participants_count: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 8: to.add(" participants: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_participants) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 4 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -4386,7 +4400,7 @@ void _serialize_stickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &t switch (stage) { case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" installed: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_installed) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; - case 2: to.add(" disabled: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_disabled) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; + case 2: to.add(" archived: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_archived) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; case 3: to.add(" official: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_official) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; case 4: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 5: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; @@ -5587,6 +5601,7 @@ void _serialize_messages_botCallbackAnswer(MTPStringLogger &to, int32 stage, int case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" alert: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_alert) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; case 2: to.add(" message: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 3: to.add(" url: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_url) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -5745,6 +5760,88 @@ void _serialize_draftMessage(MTPStringLogger &to, int32 stage, int32 lev, Types } } +void _serialize_messages_featuredStickersNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + to.add("{ messages_featuredStickersNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_messages_featuredStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_featuredStickers"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" unread: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long+0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_messages_recentStickersNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + to.add("{ messages_recentStickersNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_messages_recentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_recentStickers"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" stickers: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_messages_archivedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_archivedStickers"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" count: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_messages_stickerSetInstallResultSuccess(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + to.add("{ messages_stickerSetInstallResultSuccess }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_messages_stickerSetInstallResultArchive(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_stickerSetInstallResultArchive"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_stickerSetCovered(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ stickerSetCovered"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" set: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" cover: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_req_pq(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -5857,228 +5954,19 @@ void _serialize_destroy_session(MTPStringLogger &to, int32 stage, int32 lev, Typ } } -void _serialize_invokeAfterMsg(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { +void _serialize_contest_saveDeveloperInfo(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); } else { - to.add("{ invokeAfterMsg"); + to.add("{ contest_saveDeveloperInfo"); to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" msg_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_invokeAfterMsgs(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ invokeAfterMsgs"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" msg_ids: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long+0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_initConnection(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ initConnection"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" device_model: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" system_version: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" app_version: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" lang_code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_invokeWithLayer(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ invokeWithLayer"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" layer: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_invokeWithoutUpdates(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ invokeWithoutUpdates"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_checkPhone(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_checkPhone"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_sendCode(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - MTPauth_sendCode::Flags flag(iflag); - - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_sendCode"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" allow_flashcall: "); ++stages.back(); if (flag & MTPauth_sendCode::Flag::f_allow_flashcall) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 0: to.add(" vk_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" name: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 2: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" current_number: "); ++stages.back(); if (flag & MTPauth_sendCode::Flag::f_current_number) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; - case 4: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" api_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_resendCode(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_resendCode"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" phone_code_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_account_sendChangePhoneCode(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - MTPaccount_sendChangePhoneCode::Flags flag(iflag); - - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ account_sendChangePhoneCode"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" allow_flashcall: "); ++stages.back(); if (flag & MTPaccount_sendChangePhoneCode::Flag::f_allow_flashcall) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; - case 2: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" current_number: "); ++stages.back(); if (flag & MTPaccount_sendChangePhoneCode::Flag::f_current_number) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_signUp(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_signUp"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" phone_code_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" phone_code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" first_name: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" last_name: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_signIn(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_signIn"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" phone_code_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" phone_code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_importAuthorization(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_importAuthorization"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" bytes: "); ++stages.back(); types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_importBotAuthorization(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_importBotAuthorization"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" flags: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" api_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" bot_auth_token: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_checkPassword(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_checkPassword"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" password_hash: "); ++stages.back(); types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - -void _serialize_auth_recoverPassword(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ auth_recoverPassword"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" age: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" city: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -6287,6 +6175,20 @@ void _serialize_account_updatePasswordSettings(MTPStringLogger &to, int32 stage, } } +void _serialize_account_confirmPhone(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_confirmPhone"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" phone_code_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" phone_code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_contacts_deleteContacts(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -6421,20 +6323,6 @@ void _serialize_messages_readEncryptedHistory(MTPStringLogger &to, int32 stage, } } -void _serialize_messages_installStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_installStickerSet"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" stickerset: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" disabled: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } -} - void _serialize_messages_uninstallStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -6546,6 +6434,7 @@ void _serialize_messages_setBotCallbackAnswer(MTPStringLogger &to, int32 stage, case 1: to.add(" alert: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_alert) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; case 2: to.add(" query_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 3: to.add(" message: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 4: to.add(" url: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_url) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -6570,6 +6459,28 @@ void _serialize_messages_saveDraft(MTPStringLogger &to, int32 stage, int32 lev, } } +void _serialize_messages_readFeaturedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + to.add("{ messages_readFeaturedStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_messages_saveRecentSticker(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_saveRecentSticker"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" unsave: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_messages_clearRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + to.add("{ messages_clearRecentStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + void _serialize_upload_saveFilePart(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -6685,6 +6596,250 @@ void _serialize_channels_updateUsername(MTPStringLogger &to, int32 stage, int32 } } +void _serialize_invokeAfterMsg(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ invokeAfterMsg"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" msg_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_invokeAfterMsgs(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ invokeAfterMsgs"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" msg_ids: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long+0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_initConnection(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ initConnection"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" device_model: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" system_version: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" app_version: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" lang_code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_invokeWithLayer(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ invokeWithLayer"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" layer: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_invokeWithoutUpdates(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ invokeWithoutUpdates"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" query: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_checkPhone(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_checkPhone"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_sendCode(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + MTPauth_sendCode::Flags flag(iflag); + + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_sendCode"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" allow_flashcall: "); ++stages.back(); if (flag & MTPauth_sendCode::Flag::f_allow_flashcall) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 2: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" current_number: "); ++stages.back(); if (flag & MTPauth_sendCode::Flag::f_current_number) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 4: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" api_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_resendCode(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_resendCode"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" phone_code_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_account_sendChangePhoneCode(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + MTPaccount_sendChangePhoneCode::Flags flag(iflag); + + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_sendChangePhoneCode"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" allow_flashcall: "); ++stages.back(); if (flag & MTPaccount_sendChangePhoneCode::Flag::f_allow_flashcall) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 2: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" current_number: "); ++stages.back(); if (flag & MTPaccount_sendChangePhoneCode::Flag::f_current_number) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_account_sendConfirmPhoneCode(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + MTPaccount_sendConfirmPhoneCode::Flags flag(iflag); + + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_sendConfirmPhoneCode"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" allow_flashcall: "); ++stages.back(); if (flag & MTPaccount_sendConfirmPhoneCode::Flag::f_allow_flashcall) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 2: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" current_number: "); ++stages.back(); if (flag & MTPaccount_sendConfirmPhoneCode::Flag::f_current_number) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_signUp(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_signUp"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" phone_code_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" phone_code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" first_name: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" last_name: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_signIn(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_signIn"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" phone_number: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" phone_code_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" phone_code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_importAuthorization(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_importAuthorization"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" bytes: "); ++stages.back(); types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_importBotAuthorization(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_importBotAuthorization"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" flags: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" api_hash: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" bot_auth_token: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_checkPassword(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_checkPassword"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" password_hash: "); ++stages.back(); types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_auth_recoverPassword(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_recoverPassword"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" code: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_auth_exportAuthorization(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -7906,6 +8061,20 @@ void _serialize_messages_getStickerSet(MTPStringLogger &to, int32 stage, int32 l } } +void _serialize_messages_installStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_installStickerSet"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" stickerset: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" archived: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_messages_getDocumentByHash(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -8010,6 +8179,59 @@ void _serialize_messages_getPeerDialogs(MTPStringLogger &to, int32 stage, int32 } } +void _serialize_messages_getFeaturedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_getFeaturedStickers"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_messages_getRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_getRecentStickers"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_messages_getUnusedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_getUnusedStickers"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_messages_getArchivedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_getArchivedStickers"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" offset_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_updates_getState(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { to.add("{ updates_getState }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); } @@ -8467,6 +8689,8 @@ namespace { _serializers.insert(mtpc_updateInlineBotCallbackQuery, _serialize_updateInlineBotCallbackQuery); _serializers.insert(mtpc_updateReadChannelOutbox, _serialize_updateReadChannelOutbox); _serializers.insert(mtpc_updateDraftMessage, _serialize_updateDraftMessage); + _serializers.insert(mtpc_updateReadFeaturedStickers, _serialize_updateReadFeaturedStickers); + _serializers.insert(mtpc_updateRecentStickers, _serialize_updateRecentStickers); _serializers.insert(mtpc_updates_state, _serialize_updates_state); _serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty); _serializers.insert(mtpc_updates_difference, _serialize_updates_difference); @@ -8680,6 +8904,14 @@ namespace { _serializers.insert(mtpc_contacts_topPeers, _serialize_contacts_topPeers); _serializers.insert(mtpc_draftMessageEmpty, _serialize_draftMessageEmpty); _serializers.insert(mtpc_draftMessage, _serialize_draftMessage); + _serializers.insert(mtpc_messages_featuredStickersNotModified, _serialize_messages_featuredStickersNotModified); + _serializers.insert(mtpc_messages_featuredStickers, _serialize_messages_featuredStickers); + _serializers.insert(mtpc_messages_recentStickersNotModified, _serialize_messages_recentStickersNotModified); + _serializers.insert(mtpc_messages_recentStickers, _serialize_messages_recentStickers); + _serializers.insert(mtpc_messages_archivedStickers, _serialize_messages_archivedStickers); + _serializers.insert(mtpc_messages_stickerSetInstallResultSuccess, _serialize_messages_stickerSetInstallResultSuccess); + _serializers.insert(mtpc_messages_stickerSetInstallResultArchive, _serialize_messages_stickerSetInstallResultArchive); + _serializers.insert(mtpc_stickerSetCovered, _serialize_stickerSetCovered); _serializers.insert(mtpc_req_pq, _serialize_req_pq); _serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params); @@ -8689,21 +8921,7 @@ namespace { _serializers.insert(mtpc_ping, _serialize_ping); _serializers.insert(mtpc_ping_delay_disconnect, _serialize_ping_delay_disconnect); _serializers.insert(mtpc_destroy_session, _serialize_destroy_session); - _serializers.insert(mtpc_invokeAfterMsg, _serialize_invokeAfterMsg); - _serializers.insert(mtpc_invokeAfterMsgs, _serialize_invokeAfterMsgs); - _serializers.insert(mtpc_initConnection, _serialize_initConnection); - _serializers.insert(mtpc_invokeWithLayer, _serialize_invokeWithLayer); - _serializers.insert(mtpc_invokeWithoutUpdates, _serialize_invokeWithoutUpdates); - _serializers.insert(mtpc_auth_checkPhone, _serialize_auth_checkPhone); - _serializers.insert(mtpc_auth_sendCode, _serialize_auth_sendCode); - _serializers.insert(mtpc_auth_resendCode, _serialize_auth_resendCode); - _serializers.insert(mtpc_account_sendChangePhoneCode, _serialize_account_sendChangePhoneCode); - _serializers.insert(mtpc_auth_signUp, _serialize_auth_signUp); - _serializers.insert(mtpc_auth_signIn, _serialize_auth_signIn); - _serializers.insert(mtpc_auth_importAuthorization, _serialize_auth_importAuthorization); - _serializers.insert(mtpc_auth_importBotAuthorization, _serialize_auth_importBotAuthorization); - _serializers.insert(mtpc_auth_checkPassword, _serialize_auth_checkPassword); - _serializers.insert(mtpc_auth_recoverPassword, _serialize_auth_recoverPassword); + _serializers.insert(mtpc_contest_saveDeveloperInfo, _serialize_contest_saveDeveloperInfo); _serializers.insert(mtpc_auth_logOut, _serialize_auth_logOut); _serializers.insert(mtpc_auth_resetAuthorizations, _serialize_auth_resetAuthorizations); _serializers.insert(mtpc_auth_sendInvites, _serialize_auth_sendInvites); @@ -8721,6 +8939,7 @@ namespace { _serializers.insert(mtpc_account_updateDeviceLocked, _serialize_account_updateDeviceLocked); _serializers.insert(mtpc_account_resetAuthorization, _serialize_account_resetAuthorization); _serializers.insert(mtpc_account_updatePasswordSettings, _serialize_account_updatePasswordSettings); + _serializers.insert(mtpc_account_confirmPhone, _serialize_account_confirmPhone); _serializers.insert(mtpc_contacts_deleteContacts, _serialize_contacts_deleteContacts); _serializers.insert(mtpc_contacts_block, _serialize_contacts_block); _serializers.insert(mtpc_contacts_unblock, _serialize_contacts_unblock); @@ -8731,7 +8950,6 @@ namespace { _serializers.insert(mtpc_messages_discardEncryption, _serialize_messages_discardEncryption); _serializers.insert(mtpc_messages_setEncryptedTyping, _serialize_messages_setEncryptedTyping); _serializers.insert(mtpc_messages_readEncryptedHistory, _serialize_messages_readEncryptedHistory); - _serializers.insert(mtpc_messages_installStickerSet, _serialize_messages_installStickerSet); _serializers.insert(mtpc_messages_uninstallStickerSet, _serialize_messages_uninstallStickerSet); _serializers.insert(mtpc_messages_editChatAdmin, _serialize_messages_editChatAdmin); _serializers.insert(mtpc_messages_reorderStickerSets, _serialize_messages_reorderStickerSets); @@ -8740,6 +8958,9 @@ namespace { _serializers.insert(mtpc_messages_editInlineBotMessage, _serialize_messages_editInlineBotMessage); _serializers.insert(mtpc_messages_setBotCallbackAnswer, _serialize_messages_setBotCallbackAnswer); _serializers.insert(mtpc_messages_saveDraft, _serialize_messages_saveDraft); + _serializers.insert(mtpc_messages_readFeaturedStickers, _serialize_messages_readFeaturedStickers); + _serializers.insert(mtpc_messages_saveRecentSticker, _serialize_messages_saveRecentSticker); + _serializers.insert(mtpc_messages_clearRecentStickers, _serialize_messages_clearRecentStickers); _serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart); _serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart); _serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog); @@ -8748,6 +8969,22 @@ namespace { _serializers.insert(mtpc_channels_editAbout, _serialize_channels_editAbout); _serializers.insert(mtpc_channels_checkUsername, _serialize_channels_checkUsername); _serializers.insert(mtpc_channels_updateUsername, _serialize_channels_updateUsername); + _serializers.insert(mtpc_invokeAfterMsg, _serialize_invokeAfterMsg); + _serializers.insert(mtpc_invokeAfterMsgs, _serialize_invokeAfterMsgs); + _serializers.insert(mtpc_initConnection, _serialize_initConnection); + _serializers.insert(mtpc_invokeWithLayer, _serialize_invokeWithLayer); + _serializers.insert(mtpc_invokeWithoutUpdates, _serialize_invokeWithoutUpdates); + _serializers.insert(mtpc_auth_checkPhone, _serialize_auth_checkPhone); + _serializers.insert(mtpc_auth_sendCode, _serialize_auth_sendCode); + _serializers.insert(mtpc_auth_resendCode, _serialize_auth_resendCode); + _serializers.insert(mtpc_account_sendChangePhoneCode, _serialize_account_sendChangePhoneCode); + _serializers.insert(mtpc_account_sendConfirmPhoneCode, _serialize_account_sendConfirmPhoneCode); + _serializers.insert(mtpc_auth_signUp, _serialize_auth_signUp); + _serializers.insert(mtpc_auth_signIn, _serialize_auth_signIn); + _serializers.insert(mtpc_auth_importAuthorization, _serialize_auth_importAuthorization); + _serializers.insert(mtpc_auth_importBotAuthorization, _serialize_auth_importBotAuthorization); + _serializers.insert(mtpc_auth_checkPassword, _serialize_auth_checkPassword); + _serializers.insert(mtpc_auth_recoverPassword, _serialize_auth_recoverPassword); _serializers.insert(mtpc_auth_exportAuthorization, _serialize_auth_exportAuthorization); _serializers.insert(mtpc_auth_requestPasswordRecovery, _serialize_auth_requestPasswordRecovery); _serializers.insert(mtpc_account_getNotifySettings, _serialize_account_getNotifySettings); @@ -8836,6 +9073,7 @@ namespace { _serializers.insert(mtpc_channels_exportInvite, _serialize_channels_exportInvite); _serializers.insert(mtpc_messages_checkChatInvite, _serialize_messages_checkChatInvite); _serializers.insert(mtpc_messages_getStickerSet, _serialize_messages_getStickerSet); + _serializers.insert(mtpc_messages_installStickerSet, _serialize_messages_installStickerSet); _serializers.insert(mtpc_messages_getDocumentByHash, _serialize_messages_getDocumentByHash); _serializers.insert(mtpc_messages_searchGifs, _serialize_messages_searchGifs); _serializers.insert(mtpc_messages_getSavedGifs, _serialize_messages_getSavedGifs); @@ -8843,6 +9081,10 @@ namespace { _serializers.insert(mtpc_messages_getMessageEditData, _serialize_messages_getMessageEditData); _serializers.insert(mtpc_messages_getBotCallbackAnswer, _serialize_messages_getBotCallbackAnswer); _serializers.insert(mtpc_messages_getPeerDialogs, _serialize_messages_getPeerDialogs); + _serializers.insert(mtpc_messages_getFeaturedStickers, _serialize_messages_getFeaturedStickers); + _serializers.insert(mtpc_messages_getRecentStickers, _serialize_messages_getRecentStickers); + _serializers.insert(mtpc_messages_getUnusedStickers, _serialize_messages_getUnusedStickers); + _serializers.insert(mtpc_messages_getArchivedStickers, _serialize_messages_getArchivedStickers); _serializers.insert(mtpc_updates_getState, _serialize_updates_getState); _serializers.insert(mtpc_updates_getDifference, _serialize_updates_getDifference); _serializers.insert(mtpc_updates_getChannelDifference, _serialize_updates_getChannelDifference); diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.h b/Telegram/SourceFiles/mtproto/scheme_auto.h index 7c6769561..ff8bb5e72 100644 --- a/Telegram/SourceFiles/mtproto/scheme_auto.h +++ b/Telegram/SourceFiles/mtproto/scheme_auto.h @@ -30,7 +30,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org namespace MTP { namespace internal { -static constexpr mtpPrime CurrentLayer = 53; +static constexpr mtpPrime CurrentLayer = 54; class TypeCreator; @@ -76,6 +76,7 @@ enum { mtpc_ping = 0x7abe77ec, mtpc_ping_delay_disconnect = 0xf3427b8c, mtpc_destroy_session = 0xe7512126, + mtpc_contest_saveDeveloperInfo = 0x9a5f6e95, mtpc_boolFalse = 0xbc799737, mtpc_boolTrue = 0x997275b5, mtpc_true = 0x3fedd339, @@ -111,7 +112,7 @@ enum { mtpc_inputPhoto = 0xfb95c6c4, mtpc_inputFileLocation = 0x14637196, mtpc_inputEncryptedFileLocation = 0xf5235d55, - mtpc_inputDocumentFileLocation = 0x4e45abe9, + mtpc_inputDocumentFileLocation = 0x430f0724, mtpc_inputPhotoCropAuto = 0xade6b004, mtpc_inputPhotoCrop = 0xd9915325, mtpc_inputAppEvent = 0x770656a8, @@ -287,6 +288,8 @@ enum { mtpc_updateInlineBotCallbackQuery = 0x2cbd95af, mtpc_updateReadChannelOutbox = 0x25d6c9c7, mtpc_updateDraftMessage = 0xee2bb969, + mtpc_updateReadFeaturedStickers = 0x571d2742, + mtpc_updateRecentStickers = 0x9a422c20, mtpc_updates_state = 0xa56c2a3e, mtpc_updates_differenceEmpty = 0x5d75a138, mtpc_updates_difference = 0xf49ca0, @@ -303,7 +306,7 @@ enum { mtpc_photos_photo = 0x20212ca8, mtpc_upload_file = 0x96a18d5, mtpc_dcOption = 0x5d8c6cc, - mtpc_config = 0xc9411388, + mtpc_config = 0xf401a4bf, mtpc_nearestDc = 0x8e1a1775, mtpc_help_appUpdate = 0x8987f311, mtpc_help_noAppUpdate = 0xc45a6536, @@ -329,7 +332,7 @@ enum { mtpc_inputDocumentEmpty = 0x72f0eaae, mtpc_inputDocument = 0x18798952, mtpc_documentEmpty = 0x36f8c871, - mtpc_document = 0xf9a39f4f, + mtpc_document = 0x87232bc7, mtpc_help_support = 0x17c6b5f6, mtpc_notifyPeer = 0x9fd40bd8, mtpc_notifyUsers = 0xb4c83b4c, @@ -395,7 +398,7 @@ enum { mtpc_chatInviteEmpty = 0x69df3769, mtpc_chatInviteExported = 0xfc2e05bc, mtpc_chatInviteAlready = 0x5a686d7c, - mtpc_chatInvite = 0x93e99b60, + mtpc_chatInvite = 0xdb74f558, mtpc_inputStickerSetEmpty = 0xffb62b95, mtpc_inputStickerSetID = 0x9de7a269, mtpc_inputStickerSetShortName = 0x861cc8a0, @@ -484,7 +487,7 @@ enum { mtpc_auth_sentCodeTypeSms = 0xc000bba2, mtpc_auth_sentCodeTypeCall = 0x5353e5a7, mtpc_auth_sentCodeTypeFlashCall = 0xab03c6d9, - mtpc_messages_botCallbackAnswer = 0x1264f1c6, + mtpc_messages_botCallbackAnswer = 0xb10df1fb, mtpc_messages_messageEditData = 0x26b5dde6, mtpc_inputBotInlineMessageID = 0x890c3d89, mtpc_inlineBotSwitchPM = 0x3c20629f, @@ -500,6 +503,14 @@ enum { mtpc_contacts_topPeers = 0x70b772a8, mtpc_draftMessageEmpty = 0xba4baec5, mtpc_draftMessage = 0xfd8e711f, + mtpc_messages_featuredStickersNotModified = 0x4ede3cf, + mtpc_messages_featuredStickers = 0xf89d88e5, + mtpc_messages_recentStickersNotModified = 0xb17f890, + mtpc_messages_recentStickers = 0x5ce20970, + mtpc_messages_archivedStickers = 0x4fcba9c8, + mtpc_messages_stickerSetInstallResultSuccess = 0x38641628, + mtpc_messages_stickerSetInstallResultArchive = 0x35e410a8, + mtpc_stickerSetCovered = 0x6410a5d2, mtpc_invokeAfterMsg = 0xcb9f372d, mtpc_invokeAfterMsgs = 0x3dc4b4f0, mtpc_initConnection = 0x69796de9, @@ -545,6 +556,8 @@ enum { mtpc_account_getPassword = 0x548a30f5, mtpc_account_getPasswordSettings = 0xbc8d11bb, mtpc_account_updatePasswordSettings = 0xfa7c4b86, + mtpc_account_sendConfirmPhoneCode = 0x1516d7bd, + mtpc_account_confirmPhone = 0x5f2178c3, mtpc_users_getUsers = 0xd91a548, mtpc_users_getFullUser = 0xca30a5b1, mtpc_contacts_getStatuses = 0xc4a353ee, @@ -603,7 +616,7 @@ enum { mtpc_messages_checkChatInvite = 0x3eadb1bb, mtpc_messages_importChatInvite = 0x6c50051c, mtpc_messages_getStickerSet = 0x2619a90e, - mtpc_messages_installStickerSet = 0x7b30c3a6, + mtpc_messages_installStickerSet = 0xc78fe460, mtpc_messages_uninstallStickerSet = 0xf96e55de, mtpc_messages_startBot = 0xe6df7378, mtpc_messages_getMessagesViews = 0xc4c8a55d, @@ -623,10 +636,17 @@ enum { mtpc_messages_editMessage = 0xce91e4ca, mtpc_messages_editInlineBotMessage = 0x130c2c85, mtpc_messages_getBotCallbackAnswer = 0xa6e94f04, - mtpc_messages_setBotCallbackAnswer = 0x481c591a, + mtpc_messages_setBotCallbackAnswer = 0xc927d44b, mtpc_messages_getPeerDialogs = 0x2d9776b9, mtpc_messages_saveDraft = 0xbc39e14b, mtpc_messages_getAllDrafts = 0x6a3f8d65, + mtpc_messages_getFeaturedStickers = 0x2dacca4f, + mtpc_messages_readFeaturedStickers = 0xe21cbb, + mtpc_messages_getRecentStickers = 0x99197c2c, + mtpc_messages_saveRecentSticker = 0x348e39bf, + mtpc_messages_clearRecentStickers = 0xab02e5d2, + mtpc_messages_getUnusedStickers = 0x4309d65b, + mtpc_messages_getArchivedStickers = 0x906e241f, mtpc_updates_getState = 0xedd4882a, mtpc_updates_getDifference = 0xa041495, mtpc_updates_getChannelDifference = 0xbb32d7c0, @@ -1352,6 +1372,21 @@ class MTPDcontacts_topPeers; class MTPdraftMessage; class MTPDdraftMessage; +class MTPmessages_featuredStickers; +class MTPDmessages_featuredStickers; + +class MTPmessages_recentStickers; +class MTPDmessages_recentStickers; + +class MTPmessages_archivedStickers; +class MTPDmessages_archivedStickers; + +class MTPmessages_stickerSetInstallResult; +class MTPDmessages_stickerSetInstallResultArchive; + +class MTPstickerSetCovered; +class MTPDstickerSetCovered; + // Boxed types definitions typedef MTPBoxed MTPResPQ; @@ -1526,6 +1561,11 @@ typedef MTPBoxed MTPTopPeerCategory; typedef MTPBoxed MTPTopPeerCategoryPeers; typedef MTPBoxed MTPcontacts_TopPeers; typedef MTPBoxed MTPDraftMessage; +typedef MTPBoxed MTPmessages_FeaturedStickers; +typedef MTPBoxed MTPmessages_RecentStickers; +typedef MTPBoxed MTPmessages_ArchivedStickers; +typedef MTPBoxed MTPmessages_StickerSetInstallResult; +typedef MTPBoxed MTPStickerSetCovered; // Type classes definitions @@ -9531,6 +9571,179 @@ private: }; typedef MTPBoxed MTPDraftMessage; +class MTPmessages_featuredStickers : private mtpDataOwner { +public: + MTPmessages_featuredStickers() : mtpDataOwner(0), _type(0) { + } + MTPmessages_featuredStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDmessages_featuredStickers &_messages_featuredStickers() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messages_featuredStickers) throw mtpErrorWrongTypeId(_type, mtpc_messages_featuredStickers); + split(); + return *(MTPDmessages_featuredStickers*)data; + } + const MTPDmessages_featuredStickers &c_messages_featuredStickers() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messages_featuredStickers) throw mtpErrorWrongTypeId(_type, mtpc_messages_featuredStickers); + return *(const MTPDmessages_featuredStickers*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPmessages_featuredStickers(mtpTypeId type); + explicit MTPmessages_featuredStickers(MTPDmessages_featuredStickers *_data); + + friend class MTP::internal::TypeCreator; + + mtpTypeId _type; +}; +typedef MTPBoxed MTPmessages_FeaturedStickers; + +class MTPmessages_recentStickers : private mtpDataOwner { +public: + MTPmessages_recentStickers() : mtpDataOwner(0), _type(0) { + } + MTPmessages_recentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDmessages_recentStickers &_messages_recentStickers() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messages_recentStickers) throw mtpErrorWrongTypeId(_type, mtpc_messages_recentStickers); + split(); + return *(MTPDmessages_recentStickers*)data; + } + const MTPDmessages_recentStickers &c_messages_recentStickers() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messages_recentStickers) throw mtpErrorWrongTypeId(_type, mtpc_messages_recentStickers); + return *(const MTPDmessages_recentStickers*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPmessages_recentStickers(mtpTypeId type); + explicit MTPmessages_recentStickers(MTPDmessages_recentStickers *_data); + + friend class MTP::internal::TypeCreator; + + mtpTypeId _type; +}; +typedef MTPBoxed MTPmessages_RecentStickers; + +class MTPmessages_archivedStickers : private mtpDataOwner { +public: + MTPmessages_archivedStickers(); + MTPmessages_archivedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_archivedStickers) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDmessages_archivedStickers &_messages_archivedStickers() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDmessages_archivedStickers*)data; + } + const MTPDmessages_archivedStickers &c_messages_archivedStickers() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDmessages_archivedStickers*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_archivedStickers); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPmessages_archivedStickers(MTPDmessages_archivedStickers *_data); + + friend class MTP::internal::TypeCreator; +}; +typedef MTPBoxed MTPmessages_ArchivedStickers; + +class MTPmessages_stickerSetInstallResult : private mtpDataOwner { +public: + MTPmessages_stickerSetInstallResult() : mtpDataOwner(0), _type(0) { + } + MTPmessages_stickerSetInstallResult(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDmessages_stickerSetInstallResultArchive &_messages_stickerSetInstallResultArchive() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messages_stickerSetInstallResultArchive) throw mtpErrorWrongTypeId(_type, mtpc_messages_stickerSetInstallResultArchive); + split(); + return *(MTPDmessages_stickerSetInstallResultArchive*)data; + } + const MTPDmessages_stickerSetInstallResultArchive &c_messages_stickerSetInstallResultArchive() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messages_stickerSetInstallResultArchive) throw mtpErrorWrongTypeId(_type, mtpc_messages_stickerSetInstallResultArchive); + return *(const MTPDmessages_stickerSetInstallResultArchive*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPmessages_stickerSetInstallResult(mtpTypeId type); + explicit MTPmessages_stickerSetInstallResult(MTPDmessages_stickerSetInstallResultArchive *_data); + + friend class MTP::internal::TypeCreator; + + mtpTypeId _type; +}; +typedef MTPBoxed MTPmessages_StickerSetInstallResult; + +class MTPstickerSetCovered : private mtpDataOwner { +public: + MTPstickerSetCovered(); + MTPstickerSetCovered(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_stickerSetCovered) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDstickerSetCovered &_stickerSetCovered() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDstickerSetCovered*)data; + } + const MTPDstickerSetCovered &c_stickerSetCovered() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDstickerSetCovered*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_stickerSetCovered); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPstickerSetCovered(MTPDstickerSetCovered *_data); + + friend class MTP::internal::TypeCreator; +}; +typedef MTPBoxed MTPStickerSetCovered; + // Type constructors with data class MTPDresPQ : public mtpDataImpl { @@ -10123,11 +10336,12 @@ class MTPDinputDocumentFileLocation : public mtpDataImpl { @@ -12267,7 +12481,7 @@ class MTPDconfig : public mtpDataImpl { public: MTPDconfig() { } - MTPDconfig(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, const MTPVector &_disabled_features) : vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vmegagroup_size_max(_megagroup_size_max), vforwarded_count_max(_forwarded_count_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vpush_chat_period_ms(_push_chat_period_ms), vpush_chat_limit(_push_chat_limit), vsaved_gifs_limit(_saved_gifs_limit), vedit_time_limit(_edit_time_limit), vrating_e_decay(_rating_e_decay), vdisabled_features(_disabled_features) { + MTPDconfig(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, const MTPVector &_disabled_features) : vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vmegagroup_size_max(_megagroup_size_max), vforwarded_count_max(_forwarded_count_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vpush_chat_period_ms(_push_chat_period_ms), vpush_chat_limit(_push_chat_limit), vsaved_gifs_limit(_saved_gifs_limit), vedit_time_limit(_edit_time_limit), vrating_e_decay(_rating_e_decay), vstickers_recent_limit(_stickers_recent_limit), vdisabled_features(_disabled_features) { } MTPint vdate; @@ -12290,6 +12504,7 @@ public: MTPint vsaved_gifs_limit; MTPint vedit_time_limit; MTPint vrating_e_decay; + MTPint vstickers_recent_limit; MTPVector vdisabled_features; }; @@ -12550,7 +12765,7 @@ class MTPDdocument : public mtpDataImpl { public: MTPDdocument() { } - MTPDdocument(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, const MTPVector &_attributes) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vmime_type(_mime_type), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vattributes(_attributes) { + MTPDdocument(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _version, const MTPVector &_attributes) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vmime_type(_mime_type), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vversion(_version), vattributes(_attributes) { } MTPlong vid; @@ -12560,6 +12775,7 @@ public: MTPint vsize; MTPPhotoSize vthumb; MTPint vdc_id; + MTPint vversion; MTPVector vattributes; }; @@ -13049,8 +13265,9 @@ public: f_broadcast = (1 << 1), f_public = (1 << 2), f_megagroup = (1 << 3), + f_participants = (1 << 4), - MAX_FIELD = (1 << 3), + MAX_FIELD = (1 << 4), }; Q_DECLARE_FLAGS(Flags, Flag); friend inline Flags operator~(Flag v) { return QFlag(~static_cast(v)); } @@ -13059,14 +13276,18 @@ public: bool is_broadcast() const { return vflags.v & Flag::f_broadcast; } bool is_public() const { return vflags.v & Flag::f_public; } bool is_megagroup() const { return vflags.v & Flag::f_megagroup; } + bool has_participants() const { return vflags.v & Flag::f_participants; } MTPDchatInvite() { } - MTPDchatInvite(const MTPflags &_flags, const MTPstring &_title) : vflags(_flags), vtitle(_title) { + MTPDchatInvite(const MTPflags &_flags, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _participants_count, const MTPVector &_participants) : vflags(_flags), vtitle(_title), vphoto(_photo), vparticipants_count(_participants_count), vparticipants(_participants) { } MTPflags vflags; MTPstring vtitle; + MTPChatPhoto vphoto; + MTPint vparticipants_count; + MTPVector vparticipants; }; class MTPDinputStickerSetID : public mtpDataImpl { @@ -13094,7 +13315,7 @@ class MTPDstickerSet : public mtpDataImpl { public: enum class Flag : int32 { f_installed = (1 << 0), - f_disabled = (1 << 1), + f_archived = (1 << 1), f_official = (1 << 2), MAX_FIELD = (1 << 2), @@ -13103,7 +13324,7 @@ public: friend inline Flags operator~(Flag v) { return QFlag(~static_cast(v)); } bool is_installed() const { return vflags.v & Flag::f_installed; } - bool is_disabled() const { return vflags.v & Flag::f_disabled; } + bool is_archived() const { return vflags.v & Flag::f_archived; } bool is_official() const { return vflags.v & Flag::f_official; } MTPDstickerSet() { @@ -14274,22 +14495,25 @@ public: enum class Flag : int32 { f_alert = (1 << 1), f_message = (1 << 0), + f_url = (1 << 2), - MAX_FIELD = (1 << 1), + MAX_FIELD = (1 << 2), }; Q_DECLARE_FLAGS(Flags, Flag); friend inline Flags operator~(Flag v) { return QFlag(~static_cast(v)); } bool is_alert() const { return vflags.v & Flag::f_alert; } bool has_message() const { return vflags.v & Flag::f_message; } + bool has_url() const { return vflags.v & Flag::f_url; } MTPDmessages_botCallbackAnswer() { } - MTPDmessages_botCallbackAnswer(const MTPflags &_flags, const MTPstring &_message) : vflags(_flags), vmessage(_message) { + MTPDmessages_botCallbackAnswer(const MTPflags &_flags, const MTPstring &_message, const MTPstring &_url) : vflags(_flags), vmessage(_message), vurl(_url) { } MTPflags vflags; MTPstring vmessage; + MTPstring vurl; }; class MTPDmessages_messageEditData : public mtpDataImpl { @@ -14411,6 +14635,61 @@ public: MTPint vdate; }; +class MTPDmessages_featuredStickers : public mtpDataImpl { +public: + MTPDmessages_featuredStickers() { + } + MTPDmessages_featuredStickers(MTPint _hash, const MTPVector &_sets, const MTPVector &_unread) : vhash(_hash), vsets(_sets), vunread(_unread) { + } + + MTPint vhash; + MTPVector vsets; + MTPVector vunread; +}; + +class MTPDmessages_recentStickers : public mtpDataImpl { +public: + MTPDmessages_recentStickers() { + } + MTPDmessages_recentStickers(MTPint _hash, const MTPVector &_stickers) : vhash(_hash), vstickers(_stickers) { + } + + MTPint vhash; + MTPVector vstickers; +}; + +class MTPDmessages_archivedStickers : public mtpDataImpl { +public: + MTPDmessages_archivedStickers() { + } + MTPDmessages_archivedStickers(MTPint _count, const MTPVector &_sets) : vcount(_count), vsets(_sets) { + } + + MTPint vcount; + MTPVector vsets; +}; + +class MTPDmessages_stickerSetInstallResultArchive : public mtpDataImpl { +public: + MTPDmessages_stickerSetInstallResultArchive() { + } + MTPDmessages_stickerSetInstallResultArchive(const MTPVector &_sets) : vsets(_sets) { + } + + MTPVector vsets; +}; + +class MTPDstickerSetCovered : public mtpDataImpl { +public: + MTPDstickerSetCovered() { + } + MTPDstickerSetCovered(const MTPStickerSet &_set, const MTPDocument &_cover) : vset(_set), vcover(_cover) { + } + + MTPStickerSet vset; + MTPDocument vcover; +}; + // RPC methods class MTPreq_pq { // RPC method 'req_pq' @@ -14749,6 +15028,57 @@ public: } }; +class MTPcontest_saveDeveloperInfo { // RPC method 'contest.saveDeveloperInfo' +public: + MTPint vvk_id; + MTPstring vname; + MTPstring vphone_number; + MTPint vage; + MTPstring vcity; + + MTPcontest_saveDeveloperInfo() { + } + MTPcontest_saveDeveloperInfo(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_contest_saveDeveloperInfo) { + read(from, end, cons); + } + MTPcontest_saveDeveloperInfo(MTPint _vk_id, const MTPstring &_name, const MTPstring &_phone_number, MTPint _age, const MTPstring &_city) : vvk_id(_vk_id), vname(_name), vphone_number(_phone_number), vage(_age), vcity(_city) { + } + + uint32 innerLength() const { + return vvk_id.innerLength() + vname.innerLength() + vphone_number.innerLength() + vage.innerLength() + vcity.innerLength(); + } + mtpTypeId type() const { + return mtpc_contest_saveDeveloperInfo; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_contest_saveDeveloperInfo) { + vvk_id.read(from, end); + vname.read(from, end); + vphone_number.read(from, end); + vage.read(from, end); + vcity.read(from, end); + } + void write(mtpBuffer &to) const { + vvk_id.write(to); + vname.write(to); + vphone_number.write(to); + vage.write(to); + vcity.write(to); + } + + typedef MTPBool ResponseType; +}; +class MTPcontest_SaveDeveloperInfo : public MTPBoxed { +public: + MTPcontest_SaveDeveloperInfo() { + } + MTPcontest_SaveDeveloperInfo(const MTPcontest_saveDeveloperInfo &v) : MTPBoxed(v) { + } + MTPcontest_SaveDeveloperInfo(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPcontest_SaveDeveloperInfo(MTPint _vk_id, const MTPstring &_name, const MTPstring &_phone_number, MTPint _age, const MTPstring &_city) : MTPBoxed(MTPcontest_saveDeveloperInfo(_vk_id, _name, _phone_number, _age, _city)) { + } +}; + template class MTPinvokeAfterMsg { // RPC method 'invokeAfterMsg' public: @@ -16605,6 +16935,106 @@ public: } }; +class MTPaccount_sendConfirmPhoneCode { // RPC method 'account.sendConfirmPhoneCode' +public: + enum class Flag : int32 { + f_allow_flashcall = (1 << 0), + f_current_number = (1 << 0), + MAX_FIELD = (1 << 0), + }; + Q_DECLARE_FLAGS(Flags, Flag); + friend inline Flags operator~(Flag v) { return QFlag(~static_cast(v)); } + + bool is_allow_flashcall() const { return vflags.v & Flag::f_allow_flashcall; } + bool has_current_number() const { return vflags.v & Flag::f_current_number; } + + MTPflags vflags; + MTPstring vhash; + MTPBool vcurrent_number; + + MTPaccount_sendConfirmPhoneCode() { + } + MTPaccount_sendConfirmPhoneCode(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_sendConfirmPhoneCode) { + read(from, end, cons); + } + MTPaccount_sendConfirmPhoneCode(const MTPflags &_flags, const MTPstring &_hash, MTPBool _current_number) : vflags(_flags), vhash(_hash), vcurrent_number(_current_number) { + } + + uint32 innerLength() const { + return vflags.innerLength() + vhash.innerLength() + (has_current_number() ? vcurrent_number.innerLength() : 0); + } + mtpTypeId type() const { + return mtpc_account_sendConfirmPhoneCode; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_sendConfirmPhoneCode) { + vflags.read(from, end); + vhash.read(from, end); + if (has_current_number()) { vcurrent_number.read(from, end); } else { vcurrent_number = MTPBool(); } + } + void write(mtpBuffer &to) const { + vflags.write(to); + vhash.write(to); + if (has_current_number()) vcurrent_number.write(to); + } + + typedef MTPauth_SentCode ResponseType; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(MTPaccount_sendConfirmPhoneCode::Flags) + +class MTPaccount_SendConfirmPhoneCode : public MTPBoxed { +public: + MTPaccount_SendConfirmPhoneCode() { + } + MTPaccount_SendConfirmPhoneCode(const MTPaccount_sendConfirmPhoneCode &v) : MTPBoxed(v) { + } + MTPaccount_SendConfirmPhoneCode(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPaccount_SendConfirmPhoneCode(const MTPflags &_flags, const MTPstring &_hash, MTPBool _current_number) : MTPBoxed(MTPaccount_sendConfirmPhoneCode(_flags, _hash, _current_number)) { + } +}; + +class MTPaccount_confirmPhone { // RPC method 'account.confirmPhone' +public: + MTPstring vphone_code_hash; + MTPstring vphone_code; + + MTPaccount_confirmPhone() { + } + MTPaccount_confirmPhone(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_confirmPhone) { + read(from, end, cons); + } + MTPaccount_confirmPhone(const MTPstring &_phone_code_hash, const MTPstring &_phone_code) : vphone_code_hash(_phone_code_hash), vphone_code(_phone_code) { + } + + uint32 innerLength() const { + return vphone_code_hash.innerLength() + vphone_code.innerLength(); + } + mtpTypeId type() const { + return mtpc_account_confirmPhone; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_confirmPhone) { + vphone_code_hash.read(from, end); + vphone_code.read(from, end); + } + void write(mtpBuffer &to) const { + vphone_code_hash.write(to); + vphone_code.write(to); + } + + typedef MTPBool ResponseType; +}; +class MTPaccount_ConfirmPhone : public MTPBoxed { +public: + MTPaccount_ConfirmPhone() { + } + MTPaccount_ConfirmPhone(const MTPaccount_confirmPhone &v) : MTPBoxed(v) { + } + MTPaccount_ConfirmPhone(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPaccount_ConfirmPhone(const MTPstring &_phone_code_hash, const MTPstring &_phone_code) : MTPBoxed(MTPaccount_confirmPhone(_phone_code_hash, _phone_code)) { + } +}; + class MTPusers_getUsers { // RPC method 'users.getUsers' public: MTPVector vid; @@ -19156,32 +19586,32 @@ public: class MTPmessages_installStickerSet { // RPC method 'messages.installStickerSet' public: MTPInputStickerSet vstickerset; - MTPBool vdisabled; + MTPBool varchived; MTPmessages_installStickerSet() { } MTPmessages_installStickerSet(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_installStickerSet) { read(from, end, cons); } - MTPmessages_installStickerSet(const MTPInputStickerSet &_stickerset, MTPBool _disabled) : vstickerset(_stickerset), vdisabled(_disabled) { + MTPmessages_installStickerSet(const MTPInputStickerSet &_stickerset, MTPBool _archived) : vstickerset(_stickerset), varchived(_archived) { } uint32 innerLength() const { - return vstickerset.innerLength() + vdisabled.innerLength(); + return vstickerset.innerLength() + varchived.innerLength(); } mtpTypeId type() const { return mtpc_messages_installStickerSet; } void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_installStickerSet) { vstickerset.read(from, end); - vdisabled.read(from, end); + varchived.read(from, end); } void write(mtpBuffer &to) const { vstickerset.write(to); - vdisabled.write(to); + varchived.write(to); } - typedef MTPBool ResponseType; + typedef MTPmessages_StickerSetInstallResult ResponseType; }; class MTPmessages_InstallStickerSet : public MTPBoxed { public: @@ -19191,7 +19621,7 @@ public: } MTPmessages_InstallStickerSet(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_InstallStickerSet(const MTPInputStickerSet &_stickerset, MTPBool _disabled) : MTPBoxed(MTPmessages_installStickerSet(_stickerset, _disabled)) { + MTPmessages_InstallStickerSet(const MTPInputStickerSet &_stickerset, MTPBool _archived) : MTPBoxed(MTPmessages_installStickerSet(_stickerset, _archived)) { } }; @@ -20153,29 +20583,32 @@ public: enum class Flag : int32 { f_alert = (1 << 1), f_message = (1 << 0), + f_url = (1 << 2), - MAX_FIELD = (1 << 1), + MAX_FIELD = (1 << 2), }; Q_DECLARE_FLAGS(Flags, Flag); friend inline Flags operator~(Flag v) { return QFlag(~static_cast(v)); } bool is_alert() const { return vflags.v & Flag::f_alert; } bool has_message() const { return vflags.v & Flag::f_message; } + bool has_url() const { return vflags.v & Flag::f_url; } MTPflags vflags; MTPlong vquery_id; MTPstring vmessage; + MTPstring vurl; MTPmessages_setBotCallbackAnswer() { } MTPmessages_setBotCallbackAnswer(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_setBotCallbackAnswer) { read(from, end, cons); } - MTPmessages_setBotCallbackAnswer(const MTPflags &_flags, const MTPlong &_query_id, const MTPstring &_message) : vflags(_flags), vquery_id(_query_id), vmessage(_message) { + MTPmessages_setBotCallbackAnswer(const MTPflags &_flags, const MTPlong &_query_id, const MTPstring &_message, const MTPstring &_url) : vflags(_flags), vquery_id(_query_id), vmessage(_message), vurl(_url) { } uint32 innerLength() const { - return vflags.innerLength() + vquery_id.innerLength() + (has_message() ? vmessage.innerLength() : 0); + return vflags.innerLength() + vquery_id.innerLength() + (has_message() ? vmessage.innerLength() : 0) + (has_url() ? vurl.innerLength() : 0); } mtpTypeId type() const { return mtpc_messages_setBotCallbackAnswer; @@ -20184,11 +20617,13 @@ public: vflags.read(from, end); vquery_id.read(from, end); if (has_message()) { vmessage.read(from, end); } else { vmessage = MTPstring(); } + if (has_url()) { vurl.read(from, end); } else { vurl = MTPstring(); } } void write(mtpBuffer &to) const { vflags.write(to); vquery_id.write(to); if (has_message()) vmessage.write(to); + if (has_url()) vurl.write(to); } typedef MTPBool ResponseType; @@ -20203,7 +20638,7 @@ public: } MTPmessages_SetBotCallbackAnswer(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_SetBotCallbackAnswer(const MTPflags &_flags, const MTPlong &_query_id, const MTPstring &_message) : MTPBoxed(MTPmessages_setBotCallbackAnswer(_flags, _query_id, _message)) { + MTPmessages_SetBotCallbackAnswer(const MTPflags &_flags, const MTPlong &_query_id, const MTPstring &_message, const MTPstring &_url) : MTPBoxed(MTPmessages_setBotCallbackAnswer(_flags, _query_id, _message, _url)) { } }; @@ -20344,6 +20779,269 @@ public: } }; +class MTPmessages_getFeaturedStickers { // RPC method 'messages.getFeaturedStickers' +public: + MTPint vhash; + + MTPmessages_getFeaturedStickers() { + } + MTPmessages_getFeaturedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getFeaturedStickers) { + read(from, end, cons); + } + MTPmessages_getFeaturedStickers(MTPint _hash) : vhash(_hash) { + } + + uint32 innerLength() const { + return vhash.innerLength(); + } + mtpTypeId type() const { + return mtpc_messages_getFeaturedStickers; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getFeaturedStickers) { + vhash.read(from, end); + } + void write(mtpBuffer &to) const { + vhash.write(to); + } + + typedef MTPmessages_FeaturedStickers ResponseType; +}; +class MTPmessages_GetFeaturedStickers : public MTPBoxed { +public: + MTPmessages_GetFeaturedStickers() { + } + MTPmessages_GetFeaturedStickers(const MTPmessages_getFeaturedStickers &v) : MTPBoxed(v) { + } + MTPmessages_GetFeaturedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPmessages_GetFeaturedStickers(MTPint _hash) : MTPBoxed(MTPmessages_getFeaturedStickers(_hash)) { + } +}; + +class MTPmessages_readFeaturedStickers { // RPC method 'messages.readFeaturedStickers' +public: + MTPmessages_readFeaturedStickers() { + } + MTPmessages_readFeaturedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_readFeaturedStickers) { + read(from, end, cons); + } + + uint32 innerLength() const { + return 0; + } + mtpTypeId type() const { + return mtpc_messages_readFeaturedStickers; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_readFeaturedStickers) { + } + void write(mtpBuffer &to) const { + } + + typedef MTPBool ResponseType; +}; +class MTPmessages_ReadFeaturedStickers : public MTPBoxed { +public: + MTPmessages_ReadFeaturedStickers() { + } + MTPmessages_ReadFeaturedStickers(const MTPmessages_readFeaturedStickers &v) : MTPBoxed(v) { + } + MTPmessages_ReadFeaturedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } +}; + +class MTPmessages_getRecentStickers { // RPC method 'messages.getRecentStickers' +public: + MTPint vhash; + + MTPmessages_getRecentStickers() { + } + MTPmessages_getRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getRecentStickers) { + read(from, end, cons); + } + MTPmessages_getRecentStickers(MTPint _hash) : vhash(_hash) { + } + + uint32 innerLength() const { + return vhash.innerLength(); + } + mtpTypeId type() const { + return mtpc_messages_getRecentStickers; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getRecentStickers) { + vhash.read(from, end); + } + void write(mtpBuffer &to) const { + vhash.write(to); + } + + typedef MTPmessages_RecentStickers ResponseType; +}; +class MTPmessages_GetRecentStickers : public MTPBoxed { +public: + MTPmessages_GetRecentStickers() { + } + MTPmessages_GetRecentStickers(const MTPmessages_getRecentStickers &v) : MTPBoxed(v) { + } + MTPmessages_GetRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPmessages_GetRecentStickers(MTPint _hash) : MTPBoxed(MTPmessages_getRecentStickers(_hash)) { + } +}; + +class MTPmessages_saveRecentSticker { // RPC method 'messages.saveRecentSticker' +public: + MTPInputDocument vid; + MTPBool vunsave; + + MTPmessages_saveRecentSticker() { + } + MTPmessages_saveRecentSticker(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_saveRecentSticker) { + read(from, end, cons); + } + MTPmessages_saveRecentSticker(const MTPInputDocument &_id, MTPBool _unsave) : vid(_id), vunsave(_unsave) { + } + + uint32 innerLength() const { + return vid.innerLength() + vunsave.innerLength(); + } + mtpTypeId type() const { + return mtpc_messages_saveRecentSticker; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_saveRecentSticker) { + vid.read(from, end); + vunsave.read(from, end); + } + void write(mtpBuffer &to) const { + vid.write(to); + vunsave.write(to); + } + + typedef MTPBool ResponseType; +}; +class MTPmessages_SaveRecentSticker : public MTPBoxed { +public: + MTPmessages_SaveRecentSticker() { + } + MTPmessages_SaveRecentSticker(const MTPmessages_saveRecentSticker &v) : MTPBoxed(v) { + } + MTPmessages_SaveRecentSticker(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPmessages_SaveRecentSticker(const MTPInputDocument &_id, MTPBool _unsave) : MTPBoxed(MTPmessages_saveRecentSticker(_id, _unsave)) { + } +}; + +class MTPmessages_clearRecentStickers { // RPC method 'messages.clearRecentStickers' +public: + MTPmessages_clearRecentStickers() { + } + MTPmessages_clearRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_clearRecentStickers) { + read(from, end, cons); + } + + uint32 innerLength() const { + return 0; + } + mtpTypeId type() const { + return mtpc_messages_clearRecentStickers; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_clearRecentStickers) { + } + void write(mtpBuffer &to) const { + } + + typedef MTPBool ResponseType; +}; +class MTPmessages_ClearRecentStickers : public MTPBoxed { +public: + MTPmessages_ClearRecentStickers() { + } + MTPmessages_ClearRecentStickers(const MTPmessages_clearRecentStickers &v) : MTPBoxed(v) { + } + MTPmessages_ClearRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } +}; + +class MTPmessages_getUnusedStickers { // RPC method 'messages.getUnusedStickers' +public: + MTPint vlimit; + + MTPmessages_getUnusedStickers() { + } + MTPmessages_getUnusedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getUnusedStickers) { + read(from, end, cons); + } + MTPmessages_getUnusedStickers(MTPint _limit) : vlimit(_limit) { + } + + uint32 innerLength() const { + return vlimit.innerLength(); + } + mtpTypeId type() const { + return mtpc_messages_getUnusedStickers; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getUnusedStickers) { + vlimit.read(from, end); + } + void write(mtpBuffer &to) const { + vlimit.write(to); + } + + typedef MTPVector ResponseType; +}; +class MTPmessages_GetUnusedStickers : public MTPBoxed { +public: + MTPmessages_GetUnusedStickers() { + } + MTPmessages_GetUnusedStickers(const MTPmessages_getUnusedStickers &v) : MTPBoxed(v) { + } + MTPmessages_GetUnusedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPmessages_GetUnusedStickers(MTPint _limit) : MTPBoxed(MTPmessages_getUnusedStickers(_limit)) { + } +}; + +class MTPmessages_getArchivedStickers { // RPC method 'messages.getArchivedStickers' +public: + MTPlong voffset_id; + MTPint vlimit; + + MTPmessages_getArchivedStickers() { + } + MTPmessages_getArchivedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getArchivedStickers) { + read(from, end, cons); + } + MTPmessages_getArchivedStickers(const MTPlong &_offset_id, MTPint _limit) : voffset_id(_offset_id), vlimit(_limit) { + } + + uint32 innerLength() const { + return voffset_id.innerLength() + vlimit.innerLength(); + } + mtpTypeId type() const { + return mtpc_messages_getArchivedStickers; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getArchivedStickers) { + voffset_id.read(from, end); + vlimit.read(from, end); + } + void write(mtpBuffer &to) const { + voffset_id.write(to); + vlimit.write(to); + } + + typedef MTPmessages_ArchivedStickers ResponseType; +}; +class MTPmessages_GetArchivedStickers : public MTPBoxed { +public: + MTPmessages_GetArchivedStickers() { + } + MTPmessages_GetArchivedStickers(const MTPmessages_getArchivedStickers &v) : MTPBoxed(v) { + } + MTPmessages_GetArchivedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPmessages_GetArchivedStickers(const MTPlong &_offset_id, MTPint _limit) : MTPBoxed(MTPmessages_getArchivedStickers(_offset_id, _limit)) { + } +}; + class MTPupdates_getState { // RPC method 'updates.getState' public: MTPupdates_getState() { @@ -22357,8 +23055,8 @@ public: inline static MTPinputFileLocation new_inputEncryptedFileLocation(const MTPlong &_id, const MTPlong &_access_hash) { return MTPinputFileLocation(new MTPDinputEncryptedFileLocation(_id, _access_hash)); } - inline static MTPinputFileLocation new_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash) { - return MTPinputFileLocation(new MTPDinputDocumentFileLocation(_id, _access_hash)); + inline static MTPinputFileLocation new_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash, MTPint _version) { + return MTPinputFileLocation(new MTPDinputDocumentFileLocation(_id, _access_hash, _version)); } inline static MTPinputPhotoCrop new_inputPhotoCropAuto() { return MTPinputPhotoCrop(mtpc_inputPhotoCropAuto); @@ -22885,6 +23583,12 @@ public: inline static MTPupdate new_updateDraftMessage(const MTPPeer &_peer, const MTPDraftMessage &_draft) { return MTPupdate(new MTPDupdateDraftMessage(_peer, _draft)); } + inline static MTPupdate new_updateReadFeaturedStickers() { + return MTPupdate(mtpc_updateReadFeaturedStickers); + } + inline static MTPupdate new_updateRecentStickers() { + return MTPupdate(mtpc_updateRecentStickers); + } inline static MTPupdates_state new_updates_state(MTPint _pts, MTPint _qts, MTPint _date, MTPint _seq, MTPint _unread_count) { return MTPupdates_state(new MTPDupdates_state(_pts, _qts, _date, _seq, _unread_count)); } @@ -22933,8 +23637,8 @@ public: inline static MTPdcOption new_dcOption(const MTPflags &_flags, MTPint _id, const MTPstring &_ip_address, MTPint _port) { return MTPdcOption(new MTPDdcOption(_flags, _id, _ip_address, _port)); } - inline static MTPconfig new_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, const MTPVector &_disabled_features) { - return MTPconfig(new MTPDconfig(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _disabled_features)); + inline static MTPconfig new_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, const MTPVector &_disabled_features) { + return MTPconfig(new MTPDconfig(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _stickers_recent_limit, _disabled_features)); } inline static MTPnearestDc new_nearestDc(const MTPstring &_country, MTPint _this_dc, MTPint _nearest_dc) { return MTPnearestDc(new MTPDnearestDc(_country, _this_dc, _nearest_dc)); @@ -23011,8 +23715,8 @@ public: inline static MTPdocument new_documentEmpty(const MTPlong &_id) { return MTPdocument(new MTPDdocumentEmpty(_id)); } - inline static MTPdocument new_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, const MTPVector &_attributes) { - return MTPdocument(new MTPDdocument(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _attributes)); + inline static MTPdocument new_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _version, const MTPVector &_attributes) { + return MTPdocument(new MTPDdocument(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _version, _attributes)); } inline static MTPhelp_support new_help_support(const MTPstring &_phone_number, const MTPUser &_user) { return MTPhelp_support(new MTPDhelp_support(_phone_number, _user)); @@ -23209,8 +23913,8 @@ public: inline static MTPchatInvite new_chatInviteAlready(const MTPChat &_chat) { return MTPchatInvite(new MTPDchatInviteAlready(_chat)); } - inline static MTPchatInvite new_chatInvite(const MTPflags &_flags, const MTPstring &_title) { - return MTPchatInvite(new MTPDchatInvite(_flags, _title)); + inline static MTPchatInvite new_chatInvite(const MTPflags &_flags, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _participants_count, const MTPVector &_participants) { + return MTPchatInvite(new MTPDchatInvite(_flags, _title, _photo, _participants_count, _participants)); } inline static MTPinputStickerSet new_inputStickerSetEmpty() { return MTPinputStickerSet(mtpc_inputStickerSetEmpty); @@ -23476,8 +24180,8 @@ public: inline static MTPauth_sentCodeType new_auth_sentCodeTypeFlashCall(const MTPstring &_pattern) { return MTPauth_sentCodeType(new MTPDauth_sentCodeTypeFlashCall(_pattern)); } - inline static MTPmessages_botCallbackAnswer new_messages_botCallbackAnswer(const MTPflags &_flags, const MTPstring &_message) { - return MTPmessages_botCallbackAnswer(new MTPDmessages_botCallbackAnswer(_flags, _message)); + inline static MTPmessages_botCallbackAnswer new_messages_botCallbackAnswer(const MTPflags &_flags, const MTPstring &_message, const MTPstring &_url) { + return MTPmessages_botCallbackAnswer(new MTPDmessages_botCallbackAnswer(_flags, _message, _url)); } inline static MTPmessages_messageEditData new_messages_messageEditData(const MTPflags &_flags) { return MTPmessages_messageEditData(new MTPDmessages_messageEditData(_flags)); @@ -23524,6 +24228,30 @@ public: inline static MTPdraftMessage new_draftMessage(const MTPflags &_flags, MTPint _reply_to_msg_id, const MTPstring &_message, const MTPVector &_entities, MTPint _date) { return MTPdraftMessage(new MTPDdraftMessage(_flags, _reply_to_msg_id, _message, _entities, _date)); } + inline static MTPmessages_featuredStickers new_messages_featuredStickersNotModified() { + return MTPmessages_featuredStickers(mtpc_messages_featuredStickersNotModified); + } + inline static MTPmessages_featuredStickers new_messages_featuredStickers(MTPint _hash, const MTPVector &_sets, const MTPVector &_unread) { + return MTPmessages_featuredStickers(new MTPDmessages_featuredStickers(_hash, _sets, _unread)); + } + inline static MTPmessages_recentStickers new_messages_recentStickersNotModified() { + return MTPmessages_recentStickers(mtpc_messages_recentStickersNotModified); + } + inline static MTPmessages_recentStickers new_messages_recentStickers(MTPint _hash, const MTPVector &_stickers) { + return MTPmessages_recentStickers(new MTPDmessages_recentStickers(_hash, _stickers)); + } + inline static MTPmessages_archivedStickers new_messages_archivedStickers(MTPint _count, const MTPVector &_sets) { + return MTPmessages_archivedStickers(new MTPDmessages_archivedStickers(_count, _sets)); + } + inline static MTPmessages_stickerSetInstallResult new_messages_stickerSetInstallResultSuccess() { + return MTPmessages_stickerSetInstallResult(mtpc_messages_stickerSetInstallResultSuccess); + } + inline static MTPmessages_stickerSetInstallResult new_messages_stickerSetInstallResultArchive(const MTPVector &_sets) { + return MTPmessages_stickerSetInstallResult(new MTPDmessages_stickerSetInstallResultArchive(_sets)); + } + inline static MTPstickerSetCovered new_stickerSetCovered(const MTPStickerSet &_set, const MTPDocument &_cover) { + return MTPstickerSetCovered(new MTPDstickerSetCovered(_set, _cover)); + } }; } // namespace internal @@ -25190,7 +25918,7 @@ inline uint32 MTPinputFileLocation::innerLength() const { } case mtpc_inputDocumentFileLocation: { const MTPDinputDocumentFileLocation &v(c_inputDocumentFileLocation()); - return v.vid.innerLength() + v.vaccess_hash.innerLength(); + return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vversion.innerLength(); } } return 0; @@ -25220,6 +25948,7 @@ inline void MTPinputFileLocation::read(const mtpPrime *&from, const mtpPrime *en MTPDinputDocumentFileLocation &v(_inputDocumentFileLocation()); v.vid.read(from, end); v.vaccess_hash.read(from, end); + v.vversion.read(from, end); } break; default: throw mtpErrorUnexpected(cons, "MTPinputFileLocation"); } @@ -25241,6 +25970,7 @@ inline void MTPinputFileLocation::write(mtpBuffer &to) const { const MTPDinputDocumentFileLocation &v(c_inputDocumentFileLocation()); v.vid.write(to); v.vaccess_hash.write(to); + v.vversion.write(to); } break; } } @@ -25264,8 +25994,8 @@ inline MTPinputFileLocation MTP_inputFileLocation(const MTPlong &_volume_id, MTP inline MTPinputFileLocation MTP_inputEncryptedFileLocation(const MTPlong &_id, const MTPlong &_access_hash) { return MTP::internal::TypeCreator::new_inputEncryptedFileLocation(_id, _access_hash); } -inline MTPinputFileLocation MTP_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash) { - return MTP::internal::TypeCreator::new_inputDocumentFileLocation(_id, _access_hash); +inline MTPinputFileLocation MTP_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash, MTPint _version) { + return MTP::internal::TypeCreator::new_inputDocumentFileLocation(_id, _access_hash, _version); } inline uint32 MTPinputPhotoCrop::innerLength() const { @@ -28741,6 +29471,8 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI v.vpeer.read(from, end); v.vdraft.read(from, end); } break; + case mtpc_updateReadFeaturedStickers: _type = cons; break; + case mtpc_updateRecentStickers: _type = cons; break; default: throw mtpErrorUnexpected(cons, "MTPupdate"); } } @@ -29074,6 +29806,8 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { case mtpc_updateInlineBotCallbackQuery: setData(new MTPDupdateInlineBotCallbackQuery()); break; case mtpc_updateReadChannelOutbox: setData(new MTPDupdateReadChannelOutbox()); break; case mtpc_updateDraftMessage: setData(new MTPDupdateDraftMessage()); break; + case mtpc_updateReadFeaturedStickers: break; + case mtpc_updateRecentStickers: break; default: throw mtpErrorBadTypeId(type, "MTPupdate"); } } @@ -29321,6 +30055,12 @@ inline MTPupdate MTP_updateReadChannelOutbox(MTPint _channel_id, MTPint _max_id) inline MTPupdate MTP_updateDraftMessage(const MTPPeer &_peer, const MTPDraftMessage &_draft) { return MTP::internal::TypeCreator::new_updateDraftMessage(_peer, _draft); } +inline MTPupdate MTP_updateReadFeaturedStickers() { + return MTP::internal::TypeCreator::new_updateReadFeaturedStickers(); +} +inline MTPupdate MTP_updateRecentStickers() { + return MTP::internal::TypeCreator::new_updateRecentStickers(); +} inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) { } @@ -29850,7 +30590,7 @@ inline MTPconfig::MTPconfig() : mtpDataOwner(new MTPDconfig()) { inline uint32 MTPconfig::innerLength() const { const MTPDconfig &v(c_config()); - return v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vmegagroup_size_max.innerLength() + v.vforwarded_count_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vpush_chat_period_ms.innerLength() + v.vpush_chat_limit.innerLength() + v.vsaved_gifs_limit.innerLength() + v.vedit_time_limit.innerLength() + v.vrating_e_decay.innerLength() + v.vdisabled_features.innerLength(); + return v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vmegagroup_size_max.innerLength() + v.vforwarded_count_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vpush_chat_period_ms.innerLength() + v.vpush_chat_limit.innerLength() + v.vsaved_gifs_limit.innerLength() + v.vedit_time_limit.innerLength() + v.vrating_e_decay.innerLength() + v.vstickers_recent_limit.innerLength() + v.vdisabled_features.innerLength(); } inline mtpTypeId MTPconfig::type() const { return mtpc_config; @@ -29880,6 +30620,7 @@ inline void MTPconfig::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI v.vsaved_gifs_limit.read(from, end); v.vedit_time_limit.read(from, end); v.vrating_e_decay.read(from, end); + v.vstickers_recent_limit.read(from, end); v.vdisabled_features.read(from, end); } inline void MTPconfig::write(mtpBuffer &to) const { @@ -29904,12 +30645,13 @@ inline void MTPconfig::write(mtpBuffer &to) const { v.vsaved_gifs_limit.write(to); v.vedit_time_limit.write(to); v.vrating_e_decay.write(to); + v.vstickers_recent_limit.write(to); v.vdisabled_features.write(to); } inline MTPconfig::MTPconfig(MTPDconfig *_data) : mtpDataOwner(_data) { } -inline MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, const MTPVector &_disabled_features) { - return MTP::internal::TypeCreator::new_config(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _disabled_features); +inline MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, const MTPVector &_disabled_features) { + return MTP::internal::TypeCreator::new_config(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _stickers_recent_limit, _disabled_features); } inline MTPnearestDc::MTPnearestDc() : mtpDataOwner(new MTPDnearestDc()) { @@ -30630,7 +31372,7 @@ inline uint32 MTPdocument::innerLength() const { } case mtpc_document: { const MTPDdocument &v(c_document()); - return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vattributes.innerLength(); + return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vversion.innerLength() + v.vattributes.innerLength(); } } return 0; @@ -30657,6 +31399,7 @@ inline void MTPdocument::read(const mtpPrime *&from, const mtpPrime *end, mtpTyp v.vsize.read(from, end); v.vthumb.read(from, end); v.vdc_id.read(from, end); + v.vversion.read(from, end); v.vattributes.read(from, end); } break; default: throw mtpErrorUnexpected(cons, "MTPdocument"); @@ -30677,6 +31420,7 @@ inline void MTPdocument::write(mtpBuffer &to) const { v.vsize.write(to); v.vthumb.write(to); v.vdc_id.write(to); + v.vversion.write(to); v.vattributes.write(to); } break; } @@ -30695,8 +31439,8 @@ inline MTPdocument::MTPdocument(MTPDdocument *_data) : mtpDataOwner(_data), _typ inline MTPdocument MTP_documentEmpty(const MTPlong &_id) { return MTP::internal::TypeCreator::new_documentEmpty(_id); } -inline MTPdocument MTP_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, const MTPVector &_attributes) { - return MTP::internal::TypeCreator::new_document(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _attributes); +inline MTPdocument MTP_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _version, const MTPVector &_attributes) { + return MTP::internal::TypeCreator::new_document(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _version, _attributes); } inline MTPhelp_support::MTPhelp_support() : mtpDataOwner(new MTPDhelp_support()) { @@ -32044,7 +32788,7 @@ inline uint32 MTPchatInvite::innerLength() const { } case mtpc_chatInvite: { const MTPDchatInvite &v(c_chatInvite()); - return v.vflags.innerLength() + v.vtitle.innerLength(); + return v.vflags.innerLength() + v.vtitle.innerLength() + v.vphoto.innerLength() + v.vparticipants_count.innerLength() + (v.has_participants() ? v.vparticipants.innerLength() : 0); } } return 0; @@ -32066,6 +32810,9 @@ inline void MTPchatInvite::read(const mtpPrime *&from, const mtpPrime *end, mtpT MTPDchatInvite &v(_chatInvite()); v.vflags.read(from, end); v.vtitle.read(from, end); + v.vphoto.read(from, end); + v.vparticipants_count.read(from, end); + if (v.has_participants()) { v.vparticipants.read(from, end); } else { v.vparticipants = MTPVector(); } } break; default: throw mtpErrorUnexpected(cons, "MTPchatInvite"); } @@ -32080,6 +32827,9 @@ inline void MTPchatInvite::write(mtpBuffer &to) const { const MTPDchatInvite &v(c_chatInvite()); v.vflags.write(to); v.vtitle.write(to); + v.vphoto.write(to); + v.vparticipants_count.write(to); + if (v.has_participants()) v.vparticipants.write(to); } break; } } @@ -32098,8 +32848,8 @@ inline MTPchatInvite MTP_chatInviteAlready(const MTPChat &_chat) { return MTP::internal::TypeCreator::new_chatInviteAlready(_chat); } Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDchatInvite::Flags) -inline MTPchatInvite MTP_chatInvite(const MTPflags &_flags, const MTPstring &_title) { - return MTP::internal::TypeCreator::new_chatInvite(_flags, _title); +inline MTPchatInvite MTP_chatInvite(const MTPflags &_flags, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _participants_count, const MTPVector &_participants) { + return MTP::internal::TypeCreator::new_chatInvite(_flags, _title, _photo, _participants_count, _participants); } inline uint32 MTPinputStickerSet::innerLength() const { @@ -34481,7 +35231,7 @@ inline MTPmessages_botCallbackAnswer::MTPmessages_botCallbackAnswer() : mtpDataO inline uint32 MTPmessages_botCallbackAnswer::innerLength() const { const MTPDmessages_botCallbackAnswer &v(c_messages_botCallbackAnswer()); - return v.vflags.innerLength() + (v.has_message() ? v.vmessage.innerLength() : 0); + return v.vflags.innerLength() + (v.has_message() ? v.vmessage.innerLength() : 0) + (v.has_url() ? v.vurl.innerLength() : 0); } inline mtpTypeId MTPmessages_botCallbackAnswer::type() const { return mtpc_messages_botCallbackAnswer; @@ -34493,17 +35243,19 @@ inline void MTPmessages_botCallbackAnswer::read(const mtpPrime *&from, const mtp MTPDmessages_botCallbackAnswer &v(_messages_botCallbackAnswer()); v.vflags.read(from, end); if (v.has_message()) { v.vmessage.read(from, end); } else { v.vmessage = MTPstring(); } + if (v.has_url()) { v.vurl.read(from, end); } else { v.vurl = MTPstring(); } } inline void MTPmessages_botCallbackAnswer::write(mtpBuffer &to) const { const MTPDmessages_botCallbackAnswer &v(c_messages_botCallbackAnswer()); v.vflags.write(to); if (v.has_message()) v.vmessage.write(to); + if (v.has_url()) v.vurl.write(to); } inline MTPmessages_botCallbackAnswer::MTPmessages_botCallbackAnswer(MTPDmessages_botCallbackAnswer *_data) : mtpDataOwner(_data) { } Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDmessages_botCallbackAnswer::Flags) -inline MTPmessages_botCallbackAnswer MTP_messages_botCallbackAnswer(const MTPflags &_flags, const MTPstring &_message) { - return MTP::internal::TypeCreator::new_messages_botCallbackAnswer(_flags, _message); +inline MTPmessages_botCallbackAnswer MTP_messages_botCallbackAnswer(const MTPflags &_flags, const MTPstring &_message, const MTPstring &_url) { + return MTP::internal::TypeCreator::new_messages_botCallbackAnswer(_flags, _message, _url); } inline MTPmessages_messageEditData::MTPmessages_messageEditData() : mtpDataOwner(new MTPDmessages_messageEditData()) { @@ -34844,6 +35596,217 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDdraftMessage::Flags) inline MTPdraftMessage MTP_draftMessage(const MTPflags &_flags, MTPint _reply_to_msg_id, const MTPstring &_message, const MTPVector &_entities, MTPint _date) { return MTP::internal::TypeCreator::new_draftMessage(_flags, _reply_to_msg_id, _message, _entities, _date); } + +inline uint32 MTPmessages_featuredStickers::innerLength() const { + switch (_type) { + case mtpc_messages_featuredStickers: { + const MTPDmessages_featuredStickers &v(c_messages_featuredStickers()); + return v.vhash.innerLength() + v.vsets.innerLength() + v.vunread.innerLength(); + } + } + return 0; +} +inline mtpTypeId MTPmessages_featuredStickers::type() const { + if (!_type) throw mtpErrorUninitialized(); + return _type; +} +inline void MTPmessages_featuredStickers::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != _type) setData(0); + switch (cons) { + case mtpc_messages_featuredStickersNotModified: _type = cons; break; + case mtpc_messages_featuredStickers: _type = cons; { + if (!data) setData(new MTPDmessages_featuredStickers()); + MTPDmessages_featuredStickers &v(_messages_featuredStickers()); + v.vhash.read(from, end); + v.vsets.read(from, end); + v.vunread.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPmessages_featuredStickers"); + } +} +inline void MTPmessages_featuredStickers::write(mtpBuffer &to) const { + switch (_type) { + case mtpc_messages_featuredStickers: { + const MTPDmessages_featuredStickers &v(c_messages_featuredStickers()); + v.vhash.write(to); + v.vsets.write(to); + v.vunread.write(to); + } break; + } +} +inline MTPmessages_featuredStickers::MTPmessages_featuredStickers(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_messages_featuredStickersNotModified: break; + case mtpc_messages_featuredStickers: setData(new MTPDmessages_featuredStickers()); break; + default: throw mtpErrorBadTypeId(type, "MTPmessages_featuredStickers"); + } +} +inline MTPmessages_featuredStickers::MTPmessages_featuredStickers(MTPDmessages_featuredStickers *_data) : mtpDataOwner(_data), _type(mtpc_messages_featuredStickers) { +} +inline MTPmessages_featuredStickers MTP_messages_featuredStickersNotModified() { + return MTP::internal::TypeCreator::new_messages_featuredStickersNotModified(); +} +inline MTPmessages_featuredStickers MTP_messages_featuredStickers(MTPint _hash, const MTPVector &_sets, const MTPVector &_unread) { + return MTP::internal::TypeCreator::new_messages_featuredStickers(_hash, _sets, _unread); +} + +inline uint32 MTPmessages_recentStickers::innerLength() const { + switch (_type) { + case mtpc_messages_recentStickers: { + const MTPDmessages_recentStickers &v(c_messages_recentStickers()); + return v.vhash.innerLength() + v.vstickers.innerLength(); + } + } + return 0; +} +inline mtpTypeId MTPmessages_recentStickers::type() const { + if (!_type) throw mtpErrorUninitialized(); + return _type; +} +inline void MTPmessages_recentStickers::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != _type) setData(0); + switch (cons) { + case mtpc_messages_recentStickersNotModified: _type = cons; break; + case mtpc_messages_recentStickers: _type = cons; { + if (!data) setData(new MTPDmessages_recentStickers()); + MTPDmessages_recentStickers &v(_messages_recentStickers()); + v.vhash.read(from, end); + v.vstickers.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPmessages_recentStickers"); + } +} +inline void MTPmessages_recentStickers::write(mtpBuffer &to) const { + switch (_type) { + case mtpc_messages_recentStickers: { + const MTPDmessages_recentStickers &v(c_messages_recentStickers()); + v.vhash.write(to); + v.vstickers.write(to); + } break; + } +} +inline MTPmessages_recentStickers::MTPmessages_recentStickers(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_messages_recentStickersNotModified: break; + case mtpc_messages_recentStickers: setData(new MTPDmessages_recentStickers()); break; + default: throw mtpErrorBadTypeId(type, "MTPmessages_recentStickers"); + } +} +inline MTPmessages_recentStickers::MTPmessages_recentStickers(MTPDmessages_recentStickers *_data) : mtpDataOwner(_data), _type(mtpc_messages_recentStickers) { +} +inline MTPmessages_recentStickers MTP_messages_recentStickersNotModified() { + return MTP::internal::TypeCreator::new_messages_recentStickersNotModified(); +} +inline MTPmessages_recentStickers MTP_messages_recentStickers(MTPint _hash, const MTPVector &_stickers) { + return MTP::internal::TypeCreator::new_messages_recentStickers(_hash, _stickers); +} + +inline MTPmessages_archivedStickers::MTPmessages_archivedStickers() : mtpDataOwner(new MTPDmessages_archivedStickers()) { +} + +inline uint32 MTPmessages_archivedStickers::innerLength() const { + const MTPDmessages_archivedStickers &v(c_messages_archivedStickers()); + return v.vcount.innerLength() + v.vsets.innerLength(); +} +inline mtpTypeId MTPmessages_archivedStickers::type() const { + return mtpc_messages_archivedStickers; +} +inline void MTPmessages_archivedStickers::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_messages_archivedStickers) throw mtpErrorUnexpected(cons, "MTPmessages_archivedStickers"); + + if (!data) setData(new MTPDmessages_archivedStickers()); + MTPDmessages_archivedStickers &v(_messages_archivedStickers()); + v.vcount.read(from, end); + v.vsets.read(from, end); +} +inline void MTPmessages_archivedStickers::write(mtpBuffer &to) const { + const MTPDmessages_archivedStickers &v(c_messages_archivedStickers()); + v.vcount.write(to); + v.vsets.write(to); +} +inline MTPmessages_archivedStickers::MTPmessages_archivedStickers(MTPDmessages_archivedStickers *_data) : mtpDataOwner(_data) { +} +inline MTPmessages_archivedStickers MTP_messages_archivedStickers(MTPint _count, const MTPVector &_sets) { + return MTP::internal::TypeCreator::new_messages_archivedStickers(_count, _sets); +} + +inline uint32 MTPmessages_stickerSetInstallResult::innerLength() const { + switch (_type) { + case mtpc_messages_stickerSetInstallResultArchive: { + const MTPDmessages_stickerSetInstallResultArchive &v(c_messages_stickerSetInstallResultArchive()); + return v.vsets.innerLength(); + } + } + return 0; +} +inline mtpTypeId MTPmessages_stickerSetInstallResult::type() const { + if (!_type) throw mtpErrorUninitialized(); + return _type; +} +inline void MTPmessages_stickerSetInstallResult::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != _type) setData(0); + switch (cons) { + case mtpc_messages_stickerSetInstallResultSuccess: _type = cons; break; + case mtpc_messages_stickerSetInstallResultArchive: _type = cons; { + if (!data) setData(new MTPDmessages_stickerSetInstallResultArchive()); + MTPDmessages_stickerSetInstallResultArchive &v(_messages_stickerSetInstallResultArchive()); + v.vsets.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPmessages_stickerSetInstallResult"); + } +} +inline void MTPmessages_stickerSetInstallResult::write(mtpBuffer &to) const { + switch (_type) { + case mtpc_messages_stickerSetInstallResultArchive: { + const MTPDmessages_stickerSetInstallResultArchive &v(c_messages_stickerSetInstallResultArchive()); + v.vsets.write(to); + } break; + } +} +inline MTPmessages_stickerSetInstallResult::MTPmessages_stickerSetInstallResult(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_messages_stickerSetInstallResultSuccess: break; + case mtpc_messages_stickerSetInstallResultArchive: setData(new MTPDmessages_stickerSetInstallResultArchive()); break; + default: throw mtpErrorBadTypeId(type, "MTPmessages_stickerSetInstallResult"); + } +} +inline MTPmessages_stickerSetInstallResult::MTPmessages_stickerSetInstallResult(MTPDmessages_stickerSetInstallResultArchive *_data) : mtpDataOwner(_data), _type(mtpc_messages_stickerSetInstallResultArchive) { +} +inline MTPmessages_stickerSetInstallResult MTP_messages_stickerSetInstallResultSuccess() { + return MTP::internal::TypeCreator::new_messages_stickerSetInstallResultSuccess(); +} +inline MTPmessages_stickerSetInstallResult MTP_messages_stickerSetInstallResultArchive(const MTPVector &_sets) { + return MTP::internal::TypeCreator::new_messages_stickerSetInstallResultArchive(_sets); +} + +inline MTPstickerSetCovered::MTPstickerSetCovered() : mtpDataOwner(new MTPDstickerSetCovered()) { +} + +inline uint32 MTPstickerSetCovered::innerLength() const { + const MTPDstickerSetCovered &v(c_stickerSetCovered()); + return v.vset.innerLength() + v.vcover.innerLength(); +} +inline mtpTypeId MTPstickerSetCovered::type() const { + return mtpc_stickerSetCovered; +} +inline void MTPstickerSetCovered::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_stickerSetCovered) throw mtpErrorUnexpected(cons, "MTPstickerSetCovered"); + + if (!data) setData(new MTPDstickerSetCovered()); + MTPDstickerSetCovered &v(_stickerSetCovered()); + v.vset.read(from, end); + v.vcover.read(from, end); +} +inline void MTPstickerSetCovered::write(mtpBuffer &to) const { + const MTPDstickerSetCovered &v(c_stickerSetCovered()); + v.vset.write(to); + v.vcover.write(to); +} +inline MTPstickerSetCovered::MTPstickerSetCovered(MTPDstickerSetCovered *_data) : mtpDataOwner(_data) { +} +inline MTPstickerSetCovered MTP_stickerSetCovered(const MTPStickerSet &_set, const MTPDocument &_cover) { + return MTP::internal::TypeCreator::new_stickerSetCovered(_set, _cover); +} inline MTPDmessage::Flags mtpCastFlags(MTPDmessageService::Flags flags) { return MTPDmessage::Flags(QFlag(flags)); } inline MTPDmessage::Flags mtpCastFlags(MTPflags flags) { return mtpCastFlags(flags.v); } inline MTPDmessage::Flags mtpCastFlags(MTPDupdateShortMessage::Flags flags) { return MTPDmessage::Flags(QFlag(flags)); } diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp index f782a9eb9..0d9331782 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -103,7 +103,10 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa } } return false; - case WM_NCPAINT: if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; *result = 0; return true; + case WM_NCPAINT: { + if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; + if (result) *result = 0; + } return true; case WM_NCCALCSIZE: { WINDOWPLACEMENT wp; @@ -120,12 +123,13 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa } } } - *result = 0; + if (result) *result = 0; return true; } case WM_NCACTIVATE: { - *result = DefWindowProc(hWnd, msg, wParam, -1); + auto res = DefWindowProc(hWnd, msg, wParam, -1); + if (result) *result = res; } return true; case WM_WINDOWPOSCHANGING: @@ -172,6 +176,8 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa } return false; case WM_NCHITTEST: { + if (!result) return false; + POINTS p = MAKEPOINTS(lParam); RECT r; GetWindowRect(hWnd, &r); diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp index 9c58ddca0..a6df50772 100644 --- a/Telegram/SourceFiles/profile/profile_cover.cpp +++ b/Telegram/SourceFiles/profile/profile_cover.cpp @@ -467,7 +467,7 @@ void CoverWidget::onOnlineCountUpdated(int onlineCount) { } void CoverWidget::onSendMessage() { - Ui::showPeerHistory(_peer, ShowAtUnreadMsgId); + Ui::showPeerHistory(_peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward); } void CoverWidget::onShareContact() { diff --git a/Telegram/SourceFiles/profile/profile_info_widget.cpp b/Telegram/SourceFiles/profile/profile_info_widget.cpp index 12d7e8ec9..bbb62d9e2 100644 --- a/Telegram/SourceFiles/profile/profile_info_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_info_widget.cpp @@ -140,7 +140,7 @@ void InfoWidget::refreshAbout() { }; _about.destroy(); - auto aboutText = getAboutText(); + auto aboutText = textClean(getAboutText()); if (!aboutText.isEmpty()) { _about = new FlatLabel(this, st::profileBlockTextPart); _about->show(); diff --git a/Telegram/SourceFiles/serialize/serialize_document.cpp b/Telegram/SourceFiles/serialize/serialize_document.cpp index 73823edf5..b83f420f3 100644 --- a/Telegram/SourceFiles/serialize/serialize_document.cpp +++ b/Telegram/SourceFiles/serialize/serialize_document.cpp @@ -37,6 +37,7 @@ namespace Serialize { void Document::writeToStream(QDataStream &stream, DocumentData *document) { stream << quint64(document->id) << quint64(document->_access) << qint32(document->date); + stream << qint32(document->_version); stream << document->name << document->mime << qint32(document->_dc) << qint32(document->size); stream << qint32(document->dimensions.width()) << qint32(document->dimensions.height()); stream << qint32(document->type); @@ -61,11 +62,16 @@ void Document::writeToStream(QDataStream &stream, DocumentData *document) { } } -DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerSetInfo *info) { +DocumentData *Document::readFromStreamHelper(int streamAppVersion, QDataStream &stream, const StickerSetInfo *info) { quint64 id, access; QString name, mime; - qint32 date, dc, size, width, height, type; + qint32 date, dc, size, width, height, type, version; stream >> id >> access >> date; + if (streamAppVersion >= 9061) { + stream >> version; + } else { + version = 0; + } stream >> name >> mime >> dc >> size; stream >> width >> height; stream >> type; @@ -87,7 +93,7 @@ DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerS if (typeOfSet == StickerSetTypeEmpty) { attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetEmpty())); } else if (info) { - if (info->setId == Stickers::DefaultSetId || info->setId == Stickers::CustomSetId) { + if (info->setId == Stickers::DefaultSetId || info->setId == Stickers::CloudRecentSetId || info->setId == Stickers::CustomSetId) { typeOfSet = StickerSetTypeEmpty; } @@ -122,22 +128,22 @@ DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerS if (!dc && !access) { return nullptr; } - return App::documentSet(id, nullptr, access, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb); + return App::documentSet(id, nullptr, access, version, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb); } -DocumentData *Document::readStickerFromStream(QDataStream &stream, const StickerSetInfo &info) { - return readFromStreamHelper(stream, &info); +DocumentData *Document::readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info) { + return readFromStreamHelper(streamAppVersion, stream, &info); } -DocumentData *Document::readFromStream(QDataStream &stream) { - return readFromStreamHelper(stream, nullptr); +DocumentData *Document::readFromStream(int streamAppVersion, QDataStream &stream) { + return readFromStreamHelper(streamAppVersion, stream, nullptr); } int Document::sizeInStream(DocumentData *document) { int result = 0; - // id + access + date - result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32); + // id + access + date + version + result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32); // + namelen + name + mimelen + mime + dc + size result += stringSize(document->name) + stringSize(document->mime) + sizeof(qint32) + sizeof(qint32); // + width + height diff --git a/Telegram/SourceFiles/serialize/serialize_document.h b/Telegram/SourceFiles/serialize/serialize_document.h index b0ed77282..44ad8cd2f 100644 --- a/Telegram/SourceFiles/serialize/serialize_document.h +++ b/Telegram/SourceFiles/serialize/serialize_document.h @@ -39,12 +39,12 @@ public: }; static void writeToStream(QDataStream &stream, DocumentData *document); - static DocumentData *readStickerFromStream(QDataStream &stream, const StickerSetInfo &info); - static DocumentData *readFromStream(QDataStream &stream); + static DocumentData *readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info); + static DocumentData *readFromStream(int streamAppVersion, QDataStream &stream); static int sizeInStream(DocumentData *document); private: - static DocumentData *readFromStreamHelper(QDataStream &stream, const StickerSetInfo *info); + static DocumentData *readFromStreamHelper(int streamAppVersion, QDataStream &stream, const StickerSetInfo *info); }; diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index 030bf7a67..f24dcbb36 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -237,7 +237,7 @@ void settingsParseArgs(int argc, char *argv[]) { gWorkingDir = dir; } } else if (string("--") == argv[i] && i + 1 < argc) { - gStartUrl = fromUtf8Safe(argv[++i]); + gStartUrl = fromUtf8Safe(argv[++i]).mid(0, 8192); } } } diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp index cd051bcf4..c6bb3ac19 100644 --- a/Telegram/SourceFiles/settingswidget.cpp +++ b/Telegram/SourceFiles/settingswidget.cpp @@ -849,16 +849,10 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) { connect(box.get(), SIGNAL(confirmed()), this, SLOT(onSwitchModerateMode())); Ui::showLayer(box.release()); break; - } else if (str == qstr("clearstickers")) { - auto box = std_::make_unique(qsl("Clear frequently used stickers list?")); - connect(box.get(), SIGNAL(confirmed()), this, SLOT(onClearStickers())); - Ui::showLayer(box.release()); - break; } else if ( qsl("debugmode").startsWith(str) || qsl("testmode").startsWith(str) || qsl("loadlang").startsWith(str) || - qsl("clearstickers").startsWith(str) || qsl("moderate").startsWith(str) || qsl("debugfiles").startsWith(str) || qsl("workmode").startsWith(str) || @@ -1267,24 +1261,6 @@ void SettingsInner::onShowSessions() { Ui::showLayer(box); } -void SettingsInner::onClearStickers() { - auto &recent(cGetRecentStickers()); - if (!recent.isEmpty()) { - recent.clear(); - Local::writeUserSettings(); - } - auto &sets(Global::RefStickerSets()); - auto it = sets.find(Stickers::CustomSetId); - if (it != sets.cend()) { - sets.erase(it); - Local::writeStickers(); - } - if (auto m = App::main()) { - emit m->stickersUpdated(); - } - Ui::hideLayer(); -} - void SettingsInner::onSwitchModerateMode() { Global::SetModerateModeEnabled(!Global::ModerateModeEnabled()); Local::writeUserSettings(); diff --git a/Telegram/SourceFiles/settingswidget.h b/Telegram/SourceFiles/settingswidget.h index d88df93c8..8dffd1ed1 100644 --- a/Telegram/SourceFiles/settingswidget.h +++ b/Telegram/SourceFiles/settingswidget.h @@ -26,7 +26,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "core/observer.h" class MainWindow; -class Settings; class Slider : public QWidget { Q_OBJECT @@ -187,7 +186,6 @@ public slots: void onUpdateLocalStorage(); private slots: - void onClearStickers(); void onSwitchModerateMode(); void onAskQuestion(); diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 5575db300..0f2be68a5 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -889,13 +889,13 @@ bool StickerData::setInstalled() const { switch (set.type()) { case mtpc_inputStickerSetID: { auto it = Global::StickerSets().constFind(set.c_inputStickerSetID().vid.v); - return (it != Global::StickerSets().cend()) && !(it->flags & MTPDstickerSet::Flag::f_disabled); + return (it != Global::StickerSets().cend()) && !(it->flags & MTPDstickerSet::Flag::f_archived) && (it->flags & MTPDstickerSet::Flag::f_installed); } break; case mtpc_inputStickerSetShortName: { QString name = qs(set.c_inputStickerSetShortName().vshort_name).toLower(); for (auto it = Global::StickerSets().cbegin(), e = Global::StickerSets().cend(); it != e; ++it) { if (it->shortName.toLower() == name) { - return !(it->flags & MTPDstickerSet::Flag::f_disabled); + return !(it->flags & MTPDstickerSet::Flag::f_archived) && (it->flags & MTPDstickerSet::Flag::f_installed); } } } break; @@ -1095,10 +1095,11 @@ VoiceData::~VoiceData() { DocumentAdditionalData::~DocumentAdditionalData() { } -DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QString &url, const QVector &attributes) +DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector &attributes) : id(id) , _dc(dc) , _access(accessHash) +, _version(version) , _url(url) { setattributes(attributes); if (_dc && _access) { @@ -1107,15 +1108,15 @@ DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QSt } DocumentData *DocumentData::create(DocumentId id) { - return new DocumentData(id, 0, 0, QString(), QVector()); + return new DocumentData(id, 0, 0, 0, QString(), QVector()); } -DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, const QVector &attributes) { - return new DocumentData(id, dc, accessHash, QString(), attributes); +DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QVector &attributes) { + return new DocumentData(id, dc, accessHash, version, QString(), attributes); } DocumentData *DocumentData::create(DocumentId id, const QString &url, const QVector &attributes) { - return new DocumentData(id, 0, 0, url, attributes); + return new DocumentData(id, 0, 0, 0, url, attributes); } void DocumentData::setattributes(const QVector &attributes) { @@ -1396,7 +1397,7 @@ void DocumentData::save(const QString &toFile, ActionOnLoad action, const FullMs if (!_access && !_url.isEmpty()) { _loader = new webFileLoader(_url, toFile, fromCloud, autoLoading); } else { - _loader = new mtpFileLoader(_dc, id, _access, locationType(), toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading); + _loader = new mtpFileLoader(_dc, id, _access, _version, locationType(), toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading); } _loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*))); _loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool))); @@ -1537,6 +1538,22 @@ void DocumentData::recountIsImage() { _duration = fileIsImage(name, mime) ? 1 : -1; // hack } +bool DocumentData::setRemoteVersion(int32 version) { + if (_version == version) { + return false; + } + _version = version; + _location = FileLocation(); + _data = QByteArray(); + status = FileReady; + if (loading()) { + _loader->deleteLater(); + _loader->stop(); + _loader = nullptr; + } + return true; +} + void DocumentData::setRemoteLocation(int32 dc, uint64 access) { _dc = dc; _access = access; diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 4e7ed2fab..2a88d23c8 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -1068,7 +1068,7 @@ class Document; class DocumentData { public: static DocumentData *create(DocumentId id); - static DocumentData *create(DocumentId id, int32 dc, uint64 accessHash, const QVector &attributes); + static DocumentData *create(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QVector &attributes); static DocumentData *create(DocumentId id, const QString &url, const QVector &attributes); void setattributes(const QVector &attributes); @@ -1159,6 +1159,7 @@ public: _data = data; } + bool setRemoteVersion(int32 version); // Returns true if version has changed. void setRemoteLocation(int32 dc, uint64 access); void setContentUrl(const QString &url); bool hasRemoteLocation() const { @@ -1196,11 +1197,11 @@ public: int32 md5[8]; MediaKey mediaKey() const { - return ::mediaKey(locationType(), _dc, id); + return ::mediaKey(locationType(), _dc, id, _version); } private: - DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QString &url, const QVector &attributes); + DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector &attributes); friend class Serialize::Document; @@ -1208,9 +1209,10 @@ private: return voice() ? AudioFileLocation : (isVideo() ? VideoFileLocation : DocumentFileLocation); } - // Two types of location: from MTProto by dc+access or from web by url + // Two types of location: from MTProto by dc+access+version or from web by url int32 _dc = 0; uint64 _access = 0; + int32 _version = 0; QString _url; FileLocation _location; diff --git a/Telegram/SourceFiles/ui/flatbutton.cpp b/Telegram/SourceFiles/ui/flatbutton.cpp index 365e5297e..df5a762be 100644 --- a/Telegram/SourceFiles/ui/flatbutton.cpp +++ b/Telegram/SourceFiles/ui/flatbutton.cpp @@ -349,6 +349,7 @@ void BoxButton::setText(const QString &text) { _fullText = text; _textWidth = _st.font->width(_text); resizeToText(); + update(); } void BoxButton::resizeToText() { diff --git a/Telegram/SourceFiles/ui/flatlabel.cpp b/Telegram/SourceFiles/ui/flatlabel.cpp index ebacebdc8..94ce3882c 100644 --- a/Telegram/SourceFiles/ui/flatlabel.cpp +++ b/Telegram/SourceFiles/ui/flatlabel.cpp @@ -32,7 +32,7 @@ namespace { Qt::LayoutDirectionAuto, // dir }; TextParseOptions _labelMarkedOptions = { - TextParseMultiline | TextParseLinks | TextParseHashtags | TextParseMentions | TextParseBotCommands, // flags + TextParseMultiline | TextParseRichText | TextParseLinks | TextParseHashtags | TextParseMentions | TextParseBotCommands, // flags 0, // maxw 0, // maxh Qt::LayoutDirectionAuto, // dir diff --git a/Telegram/SourceFiles/ui/images.h b/Telegram/SourceFiles/ui/images.h index 2a2ca3b2d..ed97d9247 100644 --- a/Telegram/SourceFiles/ui/images.h +++ b/Telegram/SourceFiles/ui/images.h @@ -487,8 +487,13 @@ typedef QPair MediaKey; inline uint64 mediaMix32To64(int32 a, int32 b) { return (uint64(*reinterpret_cast(&a)) << 32) | uint64(*reinterpret_cast(&b)); } -inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) { - return MediaKey(mediaMix32To64(type, dc), id); +// Old method, should not be used anymore. +//inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) { +// return MediaKey(mediaMix32To64(type, dc), id); +//} +// New method when version was introduced, type is not relevant anymore (all files are Documents). +inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id, int32 version) { + return (version > 0) ? MediaKey(mediaMix32To64(version, dc), id) : MediaKey(mediaMix32To64(type, dc), id); } inline StorageKey mediaKey(const MTPDfileLocation &location) { return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v); diff --git a/Telegram/SourceFiles/ui/text/text.h b/Telegram/SourceFiles/ui/text/text.h index e407b4fc2..d88980375 100644 --- a/Telegram/SourceFiles/ui/text/text.h +++ b/Telegram/SourceFiles/ui/text/text.h @@ -291,7 +291,7 @@ inline bool chIsSpace(QChar ch, bool rich = false) { return ch.isSpace() || (ch < 32 && !(rich && ch == TextCommand)) || (ch == QChar::ParagraphSeparator) || (ch == QChar::LineSeparator) || (ch == QChar::ObjectReplacementCharacter) || (ch == QChar::CarriageReturn) || (ch == QChar::Tabulation); } inline bool chIsDiac(QChar ch) { // diac and variation selectors - return (ch.category() == QChar::Mark_NonSpacing) || (ch.unicode() == 1652); + return (ch.category() == QChar::Mark_NonSpacing) || (ch == 1652) || (ch >= 64606 && ch <= 64611); } inline bool chIsBad(QChar ch) { return (ch == 0) || (ch >= 8232 && ch < 8237) || (ch >= 65024 && ch < 65040 && ch != 65039) || (ch >= 127 && ch < 160 && ch != 156) || (cPlatform() == dbipMac && ch >= 0x0B00 && ch <= 0x0B7F && chIsDiac(ch) && cIsElCapitan()); // tmp hack see https://bugreports.qt.io/browse/QTBUG-48910 @@ -404,11 +404,4 @@ inline bool chIsParagraphSeparator(QChar ch) { return false; } -inline QString myUrlEncode(const QString &str) { - return QString::fromLatin1(QUrl::toPercentEncoding(str)); -} -inline QString myUrlDecode(const QString &enc) { - return QUrl::fromPercentEncoding(enc.toUtf8()); -} - void emojiDraw(QPainter &p, EmojiPtr e, int x, int y); diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index aa6701a43..6760a2698 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -199,6 +199,13 @@ public: } } + QPointer weakThis() { + return QPointer(this); + } + QPointer weakThis() const { + return QPointer(this); + } + virtual ~TWidget() { } diff --git a/Telegram/SourceFiles/window/top_bar_widget.cpp b/Telegram/SourceFiles/window/top_bar_widget.cpp index 7218dfa8d..fdc290a8b 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.cpp +++ b/Telegram/SourceFiles/window/top_bar_widget.cpp @@ -228,7 +228,7 @@ void TopBarWidget::showAll() { } } if (h && !o && _clearSelection->isHidden()) { - if (Adaptive::OneColumn()) { + if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) { _info->setPeer(h); _info->show(); } else { diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index 4fe6d5d37..9f26dc072 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -63,6 +63,8 @@ file_style_basic.target = GeneratedFiles/styles/style_basic.cpp file_style_basic.depends = style_target file_style_basic_types.target = GeneratedFiles/styles/style_basic_types.cpp file_style_basic_types.depends = style_target +file_style_boxes.target = GeneratedFiles/styles/style_boxes.cpp +file_style_boxes.depends = style_target file_style_dialogs.target = GeneratedFiles/styles/style_dialogs.cpp file_style_dialogs.depends = style_target file_style_history.target = GeneratedFiles/styles/style_history.cpp @@ -77,9 +79,9 @@ file_style_widgets.target = GeneratedFiles/styles/style_widgets.cpp file_style_widgets.depends = style_target QMAKE_EXTRA_TARGETS += codegen_style codegen_numbers codegen_lang \ - file_style_basic file_style_basic_types file_style_dialogs \ - file_style_history file_style_mediaview file_style_overview \ - file_style_profile file_style_widgets + file_style_basic file_style_basic_types file_style_boxes \ + file_style_dialogs file_style_history file_style_mediaview \ + file_style_overview file_style_profile file_style_widgets PRE_TARGETDEPS += style_target numbers_target lang_target @@ -100,6 +102,7 @@ SOURCES += \ ./GeneratedFiles/numbers.cpp \ ./GeneratedFiles/styles/style_basic.cpp \ ./GeneratedFiles/styles/style_basic_types.cpp \ + ./GeneratedFiles/styles/style_boxes.cpp \ ./GeneratedFiles/styles/style_dialogs.cpp \ ./GeneratedFiles/styles/style_history.cpp \ ./GeneratedFiles/styles/style_mediaview.cpp \ @@ -144,6 +147,7 @@ SOURCES += \ ./SourceFiles/boxes/autolockbox.cpp \ ./SourceFiles/boxes/backgroundbox.cpp \ ./SourceFiles/boxes/confirmbox.cpp \ + ./SourceFiles/boxes/confirmphonebox.cpp \ ./SourceFiles/boxes/connectionbox.cpp \ ./SourceFiles/boxes/contactsbox.cpp \ ./SourceFiles/boxes/downloadpathbox.cpp \ @@ -160,6 +164,7 @@ SOURCES += \ ./SourceFiles/core/click_handler.cpp \ ./SourceFiles/core/click_handler_types.cpp \ ./SourceFiles/core/observer.cpp \ + ./SourceFiles/core/qthelp_url.cpp \ ./SourceFiles/data/data_abstract_structure.cpp \ ./SourceFiles/data/data_drafts.cpp \ ./SourceFiles/dialogs/dialogs_indexed_list.cpp \ @@ -269,6 +274,7 @@ HEADERS += \ ./GeneratedFiles/numbers.h \ ./GeneratedFiles/styles/style_basic.h \ ./GeneratedFiles/styles/style_basic_types.h \ + ./GeneratedFiles/styles/style_boxes.h \ ./GeneratedFiles/styles/style_dialogs.h \ ./GeneratedFiles/styles/style_history.h \ ./GeneratedFiles/styles/style_mediaview.h \ @@ -314,6 +320,7 @@ HEADERS += \ ./SourceFiles/boxes/autolockbox.h \ ./SourceFiles/boxes/backgroundbox.h \ ./SourceFiles/boxes/confirmbox.h \ + ./SourceFiles/boxes/confirmphonebox.h \ ./SourceFiles/boxes/connectionbox.h \ ./SourceFiles/boxes/contactsbox.h \ ./SourceFiles/boxes/downloadpathbox.h \ @@ -330,6 +337,8 @@ HEADERS += \ ./SourceFiles/core/click_handler.h \ ./SourceFiles/core/click_handler_types.h \ ./SourceFiles/core/observer.h \ + ./SourceFiles/core/qthelp_regex.h \ + ./SourceFiles/core/qthelp_url.h \ ./SourceFiles/core/vector_of_moveable.h \ ./SourceFiles/core/version.h \ ./SourceFiles/data/data_abstract_structure.h \ diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 474bffb8e..fe6751439 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -210,6 +210,10 @@ true true + + true + true + true true @@ -550,6 +554,10 @@ true true + + true + true + true true @@ -931,6 +939,10 @@ true true + + true + true + true true @@ -1240,6 +1252,7 @@ + @@ -1256,6 +1269,7 @@ + @@ -1271,6 +1285,7 @@ + @@ -1528,6 +1543,7 @@ + @@ -1549,9 +1565,25 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/report_box.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing confirmphonebox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/confirmphonebox.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" "-IC:\Program Files (x86)\Visual Leak Detector\include" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing confirmphonebox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/confirmphonebox.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl_debug\Debug\include" "-IC:\Program Files (x86)\Visual Leak Detector\include" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing confirmphonebox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/confirmphonebox.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" "-IC:\Program Files (x86)\Visual Leak Detector\include" + + + @@ -3030,6 +3062,7 @@ Compiling style %(Identity)... + diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters index 61425a2d4..ef9cabae0 100644 --- a/Telegram/Telegram.vcxproj.filters +++ b/Telegram/Telegram.vcxproj.filters @@ -1446,6 +1446,24 @@ GeneratedFiles\Release + + GeneratedFiles\styles + + + SourceFiles\core + + + SourceFiles\boxes + + + GeneratedFiles\Deploy + + + GeneratedFiles\Debug + + + GeneratedFiles\Release + @@ -1727,6 +1745,15 @@ SourceFiles\ui\buttons + + GeneratedFiles\styles + + + SourceFiles\core + + + SourceFiles\core + @@ -2035,6 +2062,9 @@ SourceFiles\media\view + + SourceFiles\boxes + @@ -2122,6 +2152,9 @@ SourceFiles\media\view + + SourceFiles\boxes + diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index 624061e50..4538d8758 100644 --- a/Telegram/Telegram.xcodeproj/project.pbxproj +++ b/Telegram/Telegram.xcodeproj/project.pbxproj @@ -141,6 +141,11 @@ 0785004D1CCA847400168DBB /* libqtfreetype.a in Link Binary With Libraries */ = {isa = PBXBuildFile; fileRef = 0785004C1CCA847400168DBB /* libqtfreetype.a */; }; 078A2FCA1A811C5900CCC7A0 /* moc_backgroundbox.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 078A2FC91A811C5900CCC7A0 /* moc_backgroundbox.cpp */; }; 078A2FCD1A811CA600CCC7A0 /* backgroundbox.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 078A2FCB1A811CA600CCC7A0 /* backgroundbox.cpp */; }; + 079B51411D4935C0002FB6AF /* style_boxes.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 079B513F1D4935C0002FB6AF /* style_boxes.cpp */; }; + 079B51461D4B636C002FB6AF /* qthelp_url.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 079B51441D4B636C002FB6AF /* qthelp_url.cpp */; }; + 079B514A1D4B6398002FB6AF /* boxes.style in Resources */ = {isa = PBXBuildFile; fileRef = 079B51471D4B6398002FB6AF /* boxes.style */; }; + 079B514B1D4B6398002FB6AF /* confirmphonebox.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 079B51481D4B6398002FB6AF /* confirmphonebox.cpp */; }; + 079B514D1D4B6423002FB6AF /* moc_confirmphonebox.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 079B514C1D4B6423002FB6AF /* moc_confirmphonebox.cpp */; }; 07A69332199277BA0099CB9F /* mediaview.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 07A69330199277BA0099CB9F /* mediaview.cpp */; }; 07A6933519927B160099CB9F /* moc_mediaview.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 07A6933419927B160099CB9F /* moc_mediaview.cpp */; }; 07AF95F41AFD03B90060B057 /* qrc_telegram_emojis.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 07AF95F21AFD03B90060B057 /* qrc_telegram_emojis.cpp */; }; @@ -582,6 +587,15 @@ 078A2FCC1A811CA600CCC7A0 /* backgroundbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = backgroundbox.h; path = SourceFiles/boxes/backgroundbox.h; sourceTree = SOURCE_ROOT; }; 078DD0241A48DD9E00DD14CC /* lang_de.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = lang_de.strings; path = Resources/langs/lang_de.strings; sourceTree = SOURCE_ROOT; }; 078DD0251A48DD9E00DD14CC /* lang_nl.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = lang_nl.strings; path = Resources/langs/lang_nl.strings; sourceTree = SOURCE_ROOT; }; + 079B513F1D4935C0002FB6AF /* style_boxes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = style_boxes.cpp; path = GeneratedFiles/styles/style_boxes.cpp; sourceTree = SOURCE_ROOT; }; + 079B51401D4935C0002FB6AF /* style_boxes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = style_boxes.h; path = GeneratedFiles/styles/style_boxes.h; sourceTree = SOURCE_ROOT; }; + 079B51431D4B636C002FB6AF /* qthelp_regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qthelp_regex.h; path = SourceFiles/core/qthelp_regex.h; sourceTree = SOURCE_ROOT; }; + 079B51441D4B636C002FB6AF /* qthelp_url.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qthelp_url.cpp; path = SourceFiles/core/qthelp_url.cpp; sourceTree = SOURCE_ROOT; }; + 079B51451D4B636C002FB6AF /* qthelp_url.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qthelp_url.h; path = SourceFiles/core/qthelp_url.h; sourceTree = SOURCE_ROOT; }; + 079B51471D4B6398002FB6AF /* boxes.style */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = boxes.style; path = SourceFiles/boxes/boxes.style; sourceTree = SOURCE_ROOT; }; + 079B51481D4B6398002FB6AF /* confirmphonebox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = confirmphonebox.cpp; path = SourceFiles/boxes/confirmphonebox.cpp; sourceTree = SOURCE_ROOT; }; + 079B51491D4B6398002FB6AF /* confirmphonebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = confirmphonebox.h; path = SourceFiles/boxes/confirmphonebox.h; sourceTree = SOURCE_ROOT; }; + 079B514C1D4B6423002FB6AF /* moc_confirmphonebox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = moc_confirmphonebox.cpp; path = GeneratedFiles/Debug/moc_confirmphonebox.cpp; sourceTree = SOURCE_ROOT; }; 07A190511A723E0A004287AE /* lang_ko.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = lang_ko.strings; path = Resources/langs/lang_ko.strings; sourceTree = SOURCE_ROOT; }; 07A69330199277BA0099CB9F /* mediaview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mediaview.cpp; path = SourceFiles/mediaview.cpp; sourceTree = SOURCE_ROOT; }; 07A69331199277BA0099CB9F /* mediaview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mediaview.h; path = SourceFiles/mediaview.h; sourceTree = SOURCE_ROOT; }; @@ -1092,6 +1106,8 @@ 0747FF7D1CC6435100096FC3 /* style_basic.h */, 0747FF7A1CC6435100096FC3 /* style_basic_types.cpp */, 0747FF7B1CC6435100096FC3 /* style_basic_types.h */, + 079B513F1D4935C0002FB6AF /* style_boxes.cpp */, + 079B51401D4935C0002FB6AF /* style_boxes.h */, 0716C99C1D08251C00797B22 /* style_dialogs.cpp */, 0716C99D1D08251C00797B22 /* style_dialogs.h */, 0716C99E1D08251C00797B22 /* style_history.cpp */, @@ -1146,6 +1162,9 @@ 076B1C531CBFC6F2002C0BC2 /* click_handler.h */, 0716C98D1D05954900797B22 /* observer.cpp */, 0716C98E1D05954900797B22 /* observer.h */, + 079B51431D4B636C002FB6AF /* qthelp_regex.h */, + 079B51441D4B636C002FB6AF /* qthelp_url.cpp */, + 079B51451D4B636C002FB6AF /* qthelp_url.h */, 0716C98F1D05954900797B22 /* vector_of_moveable.h */, 07D518D41CD0E27600F5FF59 /* version.h */, ); @@ -1634,6 +1653,7 @@ 074756181A1372C600CA07F7 /* moc_basic_types.cpp */, 46292F489228B60010794CE4 /* moc_button.cpp */, CE7FFE194127BD789A2C877A /* moc_confirmbox.cpp */, + 079B514C1D4B6423002FB6AF /* moc_confirmphonebox.cpp */, B714EA71A09A832FAA846A0A /* moc_connection.cpp */, 077A4AFF1CA41EE2002188D2 /* moc_connection_abstract.cpp */, 077A4B001CA41EE2002188D2 /* moc_connection_auto.cpp */, @@ -1724,8 +1744,11 @@ 07DE92A41AA4925B00A18F6F /* autolockbox.h */, 078A2FCB1A811CA600CCC7A0 /* backgroundbox.cpp */, 078A2FCC1A811CA600CCC7A0 /* backgroundbox.h */, + 079B51471D4B6398002FB6AF /* boxes.style */, 6610564B876E47D289A596DB /* confirmbox.cpp */, 1DEFC0760BB9340529F582F7 /* confirmbox.h */, + 079B51481D4B6398002FB6AF /* confirmphonebox.cpp */, + 079B51491D4B6398002FB6AF /* confirmphonebox.h */, 51355181C0E6689B0B764543 /* connectionbox.cpp */, 8EB83A4D34226609E79A613A /* connectionbox.h */, 8C800AAC9549E6E9E7046BED /* contactsbox.cpp */, @@ -1947,6 +1970,7 @@ 07E102F81D3E4E8C00BD33B1 /* widgets.style in Resources */, 0716C95A1D0589B600797B22 /* overview.style in Resources */, 0716C9291D05893900797B22 /* basic_types.style in Resources */, + 079B514A1D4B6398002FB6AF /* boxes.style in Resources */, 07D7EABA1A597DD000838BA2 /* Localizable.strings in Resources */, 07E102EE1D3E4E3B00BD33B1 /* mediaview.style in Resources */, 0716C9A71D08258A00797B22 /* history.style in Resources */, @@ -2164,6 +2188,7 @@ BA41D511A9BBCA09365DF88C /* downloadpathbox.cpp in Compile Sources */, 07DB67511AD07CB800A51329 /* intropwdcheck.cpp in Compile Sources */, 07C8FE0F1CB80890007A8702 /* toast_widget.cpp in Compile Sources */, + 079B51411D4935C0002FB6AF /* style_boxes.cpp in Compile Sources */, 0716C9741D058C8600797B22 /* moc_profile_inner_widget.cpp in Compile Sources */, 3ABE4F9B2264F770D944106D /* emojibox.cpp in Compile Sources */, 07D703BB19B88FB900C4EED2 /* moc_media_audio.cpp in Compile Sources */, @@ -2198,6 +2223,7 @@ 07E102D01D3E4B7F00BD33B1 /* media_clip_ffmpeg.cpp in Compile Sources */, 98E4F55DB5D8E64AB9F08C83 /* moc_localimageloader.cpp in Compile Sources */, A24E4B5B683764E07683ECEC /* moc_mainwidget.cpp in Compile Sources */, + 079B51461D4B636C002FB6AF /* qthelp_url.cpp in Compile Sources */, 0710CA051B0B9404001B4272 /* moc_stickersetbox.cpp in Compile Sources */, 0716C9AA1D0825A800797B22 /* history_down_button.cpp in Compile Sources */, 0716C94A1D0589A700797B22 /* profile_actions_widget.cpp in Compile Sources */, @@ -2244,6 +2270,7 @@ 07A69332199277BA0099CB9F /* mediaview.cpp in Compile Sources */, 9A523F51135FD4E2464673A6 /* moc_session.cpp in Compile Sources */, 076B1C631CBFCC53002C0BC2 /* moc_top_bar_widget.cpp in Compile Sources */, + 079B514B1D4B6398002FB6AF /* confirmphonebox.cpp in Compile Sources */, C329997D36D34D568CE16C9A /* moc_animation.cpp in Compile Sources */, 0716C9801D058F2400797B22 /* section_widget.cpp in Compile Sources */, B2F5B08BFFBBE7E37D3863BB /* moc_button.cpp in Compile Sources */, @@ -2290,6 +2317,7 @@ 074968D01A44D14C00394F46 /* languagebox.cpp in Compile Sources */, 077A4AF91CA41C38002188D2 /* connection_http.cpp in Compile Sources */, 07BE85121A20961F008ACB9F /* moc_localstorage.cpp in Compile Sources */, + 079B514D1D4B6423002FB6AF /* moc_confirmphonebox.cpp in Compile Sources */, 07E1B1961D12DFD200722BC7 /* main_window.cpp in Compile Sources */, 07AF95F41AFD03B90060B057 /* qrc_telegram_emojis.cpp in Compile Sources */, 07C759721B1F7E2800662169 /* moc_autoupdater.cpp in Compile Sources */, @@ -2530,8 +2558,8 @@ QT_PATH = "/usr/local/tdesktop/Qt-5.6.0"; SDKROOT = macosx; SYMROOT = ./../Mac; - TDESKTOP_MAJOR_VERSION = 0.9; - TDESKTOP_VERSION = 0.9.60; + TDESKTOP_MAJOR_VERSION = 0.10; + TDESKTOP_VERSION = 0.10; }; name = Release; }; @@ -2671,8 +2699,8 @@ QT_PATH = "/usr/local/tdesktop/Qt-5.6.0"; SDKROOT = macosx; SYMROOT = ./../Mac; - TDESKTOP_MAJOR_VERSION = 0.9; - TDESKTOP_VERSION = 0.9.60; + TDESKTOP_MAJOR_VERSION = 0.10; + TDESKTOP_VERSION = 0.10; }; name = Debug; }; diff --git a/Telegram/Telegram.xcodeproj/qt_preprocess.mak b/Telegram/Telegram.xcodeproj/qt_preprocess.mak index 7250e65e8..24baedfab 100644 --- a/Telegram/Telegram.xcodeproj/qt_preprocess.mak +++ b/Telegram/Telegram.xcodeproj/qt_preprocess.mak @@ -61,6 +61,7 @@ compilers: GeneratedFiles/qrc_telegram.cpp\ GeneratedFiles/Debug/moc_basic_types.cpp\ GeneratedFiles/Debug/moc_button.cpp\ GeneratedFiles/Debug/moc_confirmbox.cpp\ + GeneratedFiles/Debug/moc_confirmphonebox.cpp\ GeneratedFiles/Debug/moc_connection.cpp\ GeneratedFiles/Debug/moc_connection_abstract.cpp\ GeneratedFiles/Debug/moc_connection_auto.cpp\ @@ -204,6 +205,7 @@ compiler_moc_header_make_all: GeneratedFiles/Debug/moc_aboutbox.cpp\ GeneratedFiles/Debug/moc_basic_types.cpp\ GeneratedFiles/Debug/moc_button.cpp\ GeneratedFiles/Debug/moc_confirmbox.cpp\ + GeneratedFiles/Debug/moc_confirmphonebox.cpp\ GeneratedFiles/Debug/moc_connection.cpp\ GeneratedFiles/Debug/moc_connection_abstract.cpp\ GeneratedFiles/Debug/moc_connection_auto.cpp\ @@ -290,6 +292,7 @@ compiler_moc_header_clean: GeneratedFiles/Debug/moc_basic_types.cpp\ GeneratedFiles/Debug/moc_button.cpp\ GeneratedFiles/Debug/moc_confirmbox.cpp\ + GeneratedFiles/Debug/moc_confirmphonebox.cpp\ GeneratedFiles/Debug/moc_connection.cpp\ GeneratedFiles/Debug/moc_connection_abstract.cpp\ GeneratedFiles/Debug/moc_connection_auto.cpp\ @@ -399,6 +402,9 @@ GeneratedFiles/Debug/moc_button.cpp: SourceFiles/ui/button.h GeneratedFiles/Debug/moc_confirmbox.cpp: SourceFiles/boxes/confirmbox.h $(MOC_FILE) SourceFiles/boxes/confirmbox.h -o GeneratedFiles/Debug/moc_confirmbox.cpp +GeneratedFiles/Debug/moc_confirmphonebox.cpp: SourceFiles/boxes/confirmphonebox.h + $(MOC_FILE) SourceFiles/boxes/confirmphonebox.h -o GeneratedFiles/Debug/moc_confirmphonebox.cpp + GeneratedFiles/Debug/moc_connection.cpp: SourceFiles/mtproto/connection.h $(MOC_FILE) SourceFiles/mtproto/connection.h -o GeneratedFiles/Debug/moc_connection.cpp diff --git a/Telegram/build/version b/Telegram/build/version index 1921f28f9..4dc03752b 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,6 +1,6 @@ -AppVersion 9060 -AppVersionStrMajor 0.9 -AppVersionStrSmall 0.9.60 -AppVersionStr 0.9.60 -AlphaChannel 1 +AppVersion 10000 +AppVersionStrMajor 0.10 +AppVersionStrSmall 0.10 +AppVersionStr 0.10.0 +AlphaChannel 0 BetaVersion 0