diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt
index f79ceb35bb..0c88d5d498 100644
--- a/Telegram/CMakeLists.txt
+++ b/Telegram/CMakeLists.txt
@@ -231,6 +231,8 @@ PRIVATE
api/api_peer_colors.h
api/api_peer_photo.cpp
api/api_peer_photo.h
+ api/api_peer_search.cpp
+ api/api_peer_search.h
api/api_polls.cpp
api/api_polls.h
api/api_premium.cpp
@@ -764,6 +766,8 @@ PRIVATE
dialogs/dialogs_main_list.h
dialogs/dialogs_pinned_list.cpp
dialogs/dialogs_pinned_list.h
+ dialogs/dialogs_quick_action.cpp
+ dialogs/dialogs_quick_action.h
dialogs/dialogs_row.cpp
dialogs/dialogs_row.h
dialogs/dialogs_search_from_controllers.cpp
@@ -1001,6 +1005,8 @@ PRIVATE
history/history_unread_things.h
history/history_view_highlight_manager.cpp
history/history_view_highlight_manager.h
+ history/history_view_swipe_back_session.cpp
+ history/history_view_swipe_back_session.h
history/history_widget.cpp
history/history_widget.h
info/bot/earn/info_bot_earn_list.cpp
@@ -2143,14 +2149,16 @@ if (LINUX AND DESKTOP_APP_USE_PACKAGED)
configure_file("../lib/xdg/com.ayugram.desktop.metainfo.xml" "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.metainfo.xml" @ONLY)
generate_appdata_changelog(Telegram "${CMAKE_SOURCE_DIR}/changelog.txt" "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.metainfo.xml")
install(TARGETS Telegram RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}")
- install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "ayugram.png")
- install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "ayugram.png")
- install(FILES "Resources/art/icon48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "ayugram.png")
- install(FILES "Resources/art/icon64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "ayugram.png")
- install(FILES "Resources/art/icon128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "ayugram.png")
- install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "ayugram.png")
- install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "ayugram.png")
- install(FILES "Resources/icons/tray_monochrome.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "ayugram-symbolic.svg")
+ install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "com.ayugram.desktop.png")
+ install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "com.ayugram.desktop.png")
+ install(FILES "Resources/art/icon48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "com.ayugram.desktop.png")
+ install(FILES "Resources/art/icon64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "com.ayugram.desktop.png")
+ install(FILES "Resources/art/icon128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "com.ayugram.desktop.png")
+ install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "com.ayugram.desktop.png")
+ install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "com.ayugram.desktop.png")
+ install(FILES "Resources/icons/tray_monochrome.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "com.ayugram.desktop-symbolic.svg")
+ install(FILES "Resources/icons/tray_monochrome_attention.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "com.ayugram.desktop-attention-symbolic.svg")
+ install(FILES "Resources/icons/tray_monochrome_mute.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "com.ayugram.desktop-mute-symbolic.svg")
install(FILES "../lib/xdg/com.ayugram.desktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.service" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/dbus-1/services")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
diff --git a/Telegram/Resources/animations/media_forbidden.tgs b/Telegram/Resources/animations/media_forbidden.tgs
new file mode 100644
index 0000000000..b1846cd5db
--- /dev/null
+++ b/Telegram/Resources/animations/media_forbidden.tgs
@@ -0,0 +1 @@
+{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":180,"w":512,"h":512,"nm":"_051_GHSTBST_OUT","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"mouth","parent":4,"sr":1,"ks":{"p":{"a":0,"k":[0.333,12.11,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[0,-0.528],[7.067,0],[0,0.528],[-7.067,0]],"o":[[0,0.528],[-7.067,0],[0,-0.528],[7.067,0]],"v":[[33.711,-12.993],[-3.656,-7.631],[-37.522,-9.604],[-3.656,-9.545]],"c":true}]},{"i":{"x":0.677,"y":1},"o":{"x":1,"y":0},"t":74,"s":[{"i":[[-8.771,-8.472],[15.699,0],[-13.434,18.726],[-15.699,0]],"o":[[16.228,15.674],[-15.699,0],[6.52,-9.088],[15.699,0]],"v":[[43.825,-6.263],[-1.98,-0.006],[-47.357,-3.407],[-1.871,-13.433]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":92,"s":[{"i":[[0,-0.528],[7.067,0],[0,0.528],[-7.067,0]],"o":[[0,0.528],[-7.067,0],[0,-0.528],[7.067,0]],"v":[[33.711,-12.993],[-3.656,-12.631],[-37.522,-9.604],[-3.656,-14.545]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":106,"s":[{"i":[[0,-0.528],[7.067,0],[0,0.528],[-7.067,0]],"o":[[0,0.528],[-7.067,0],[0,-0.528],[7.067,0]],"v":[[40.66,-12.018],[6.297,-12.548],[-33.768,-8.034],[6.297,-14.462]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.7,"y":0},"t":136,"s":[{"i":[[0,-0.528],[7.067,0],[0,0.528],[-7.067,0]],"o":[[0,0.528],[-7.067,0],[0,-0.528],[7.067,0]],"v":[[40.66,-12.018],[6.297,-12.548],[-33.768,-8.034],[6.297,-14.462]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,-0.528],[5.996,0],[0,0.528],[-5.996,0]],"o":[[0,0.528],[-5.996,0],[0,-0.528],[5.996,0]],"v":[[39.448,-12.413],[-1.678,-12.848],[-33.87,-9.837],[-1.678,-14.762]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":186,"s":[{"i":[[0,-0.528],[5.996,0],[0,0.528],[-5.996,0]],"o":[[0,0.528],[-5.996,0],[0,-0.528],[5.996,0]],"v":[[39.448,-12.413],[-1.678,-12.848],[-33.87,-9.837],[-1.678,-14.762]],"c":true}]},{"t":212,"s":[{"i":[[0,-8.033],[7.067,0],[0,8.033],[-7.067,0]],"o":[[0,8.033],[-7.067,0],[0,-8.033],[7.067,0]],"v":[[12.796,0],[0,14.546],[-12.796,0],[0,-14.546]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.490196079016,0.035294119269,0.035294119269,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.490196079016,0.035294119269,0.035294119269,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"beak_bl","parent":4,"sr":1,"ks":{"o":{"a":0,"k":33},"p":{"a":0,"k":[-7.949,-24.179,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[0,0],[-4.412,4.147]],"o":[[5.678,-4.69],[0,0]],"v":[[-7.943,6.682],[3.424,-6.971]],"c":false}]},{"i":{"x":0.677,"y":1},"o":{"x":1,"y":0},"t":74,"s":[{"i":[[0,0],[-4.403,5.549]],"o":[[6.446,-4.392],[0,0]],"v":[[-10.628,6.975],[1.455,-6.971]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":92,"s":[{"i":[[0,0],[-4.403,5.549]],"o":[[6.446,-4.392],[0,0]],"v":[[-7.674,6.721],[3.424,-6.971]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":106,"s":[{"i":[[0,0],[-4.264,5.647]],"o":[[5.641,-5.851],[0,0]],"v":[[-8.051,8.282],[3.424,-6.971]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.7,"y":0},"t":136,"s":[{"i":[[0,0],[-4.264,5.647]],"o":[[5.641,-5.851],[0,0]],"v":[[-8.051,8.282],[3.424,-6.971]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.373,5.044]],"o":[[5.523,-2.968],[0,0]],"v":[[-5.282,12.038],[3.424,-6.971]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":186,"s":[{"i":[[0,0],[-0.373,5.044]],"o":[[5.523,-2.968],[0,0]],"v":[[-5.282,12.038],[3.424,-6.971]],"c":false}]},{"t":212,"s":[{"i":[[0,0],[-4.412,4.147]],"o":[[1.964,-7.603],[0,0]],"v":[[-5.443,10.182],[3.424,-6.971]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":216,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":228,"s":[5]},{"t":240,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":216,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":228,"s":[100]},{"t":240,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"NULL CONTROL","parent":18,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":1.559},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[-6.826,76.052,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":194.666,"s":[18.173,76.217,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":205.334,"s":[-26.826,76.142,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":218.666,"s":[8.174,76.142,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[-6.826,76.052,0]}]},"a":{"a":0,"k":[60,60,0]}},"ao":0,"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"beak","parent":3,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[-8.95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":74,"s":[-1.559]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":92,"s":[-1.559]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":106,"s":[-13.63]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":136,"s":[-13.63]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[-8.299]},{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":186,"s":[-8.299]},{"t":212,"s":[-1.559]}]},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.789,"y":0},"t":60,"s":[76.503,30.265,0],"to":[-1.303,3.086,0],"ti":[2.223,-1.998,0]},{"i":{"x":0.419,"y":1},"o":{"x":0.167,"y":0.167},"t":68,"s":[68.242,9.778,0],"to":[-1.808,1.625,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":74,"s":[66.953,40.91,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[66.953,40.91,0],"to":[0,0,0],"ti":[-30.538,1.683,0]},{"t":106,"s":[120.906,38.44,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":136,"s":[120.906,38.44,0],"to":[0,0,0],"ti":[38.176,-10.366,0]},{"t":150,"s":[29.143,75.951,0],"h":1},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":186,"s":[29.143,75.951,0],"to":[37.106,-3.862,0],"ti":[0,0,0]},{"t":212,"s":[66.953,40.91,0]}]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":67.5,"s":[110,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":76.5,"s":[90,130,100]},{"t":90,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[7.988,0.4],[16.048,-2.349],[27.593,-7.415],[-0.76,-4.01],[-8.507,-1.957],[-12.737,1.211],[-6.332,1.939],[-0.446,4.013]],"o":[[-29.32,-1.47],[-13.151,1.925],[-7.923,2.129],[0.679,3.582],[6.961,1.601],[12.334,-1.173],[8.449,-2.587],[0.684,-6.149]],"v":[[39.197,-13.901],[-6.251,-41.866],[-46.922,-6.336],[-57.964,3.906],[-44.397,12.952],[-1.355,16.043],[40.722,9.34],[53.214,-1.325]],"c":true}]},{"i":{"x":0.677,"y":1},"o":{"x":1,"y":0},"t":74,"s":[{"i":[[6.309,1.307],[16.048,-2.349],[36.607,-17.968],[-0.882,-5.709],[-5.328,-2.761],[-11.843,0.728],[-5.624,6.202],[-0.191,4.479]],"o":[[-33.997,-8.466],[-13.151,1.925],[-6.185,2.526],[0.788,5.1],[9.679,5.133],[13.616,-0.791],[4.681,-3.634],[0.292,-6.863]],"v":[[48.12,-8.237],[-6.251,-41.866],[-51.424,-6.236],[-62.689,14.421],[-53.5,27.125],[-0.365,29.968],[55.123,20.91],[62.025,8.224]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":92,"s":[{"i":[[7.988,0.4],[16.048,-2.349],[30.244,-4.765],[-0.567,-6.434],[-8.692,-0.813],[-12.737,1.211],[-6.332,1.939],[0.309,4.532]],"o":[[-29.32,-1.47],[-13.151,1.925],[-8.105,1.277],[0.507,5.748],[15.469,1.447],[12.334,-1.173],[8.449,-2.587],[-0.473,-6.944]],"v":[[39.197,-13.901],[-6.251,-41.866],[-46.922,-8.836],[-58.646,5.725],[-45.147,17.702],[-2.105,8.543],[44.722,12.09],[55.836,0.478]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":106,"s":[{"i":[[8.444,0.423],[16.048,-2.349],[30.244,-4.765],[-0.567,-6.434],[-8.692,-0.813],[-12.737,1.211],[-6.332,1.939],[4.732,3.233]],"o":[[-29.32,-1.47],[-13.151,1.925],[-8.105,1.277],[0.507,5.748],[15.469,1.447],[12.334,-1.173],[7.709,-2.361],[7.982,-3.767]],"v":[[39.197,-13.901],[-6.251,-41.866],[-46.922,-8.836],[-58.646,5.725],[-45.147,17.702],[2.145,12.293],[37.722,11.84],[43.34,0.666]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.7,"y":0},"t":136,"s":[{"i":[[8.444,0.423],[16.048,-2.349],[30.244,-4.765],[-0.567,-6.434],[-8.692,-0.813],[-12.737,1.211],[-6.332,1.939],[4.732,3.233]],"o":[[-29.32,-1.47],[-13.151,1.925],[-8.105,1.277],[0.507,5.748],[15.469,1.447],[12.334,-1.173],[7.709,-2.361],[7.982,-3.767]],"v":[[39.197,-13.901],[-6.251,-41.866],[-46.922,-8.836],[-58.646,5.725],[-45.147,17.702],[2.145,12.293],[37.722,11.84],[43.34,0.666]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[8.444,0.423],[16.048,-2.349],[30.244,-4.765],[-14.233,-1.737],[-8.352,-0.781],[-12.737,1.211],[-6.572,-0.817],[1.9,16.015]],"o":[[-29.32,-1.47],[-13.151,1.925],[-8.387,1.321],[-7.971,3.727],[15.469,1.447],[12.334,-1.173],[8.179,1.017],[-0.935,-7.882]],"v":[[35.422,-16.826],[-6.251,-41.866],[-35.806,-11.299],[-33.327,1.916],[-34.031,15.24],[2.145,12.293],[37.722,11.84],[56.931,-7.328]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0},"t":186,"s":[{"i":[[8.444,0.423],[16.048,-2.349],[30.244,-4.765],[-14.233,-1.737],[-8.352,-0.781],[-12.737,1.211],[-6.572,-0.817],[1.9,16.015]],"o":[[-29.32,-1.47],[-13.151,1.925],[-8.387,1.321],[-7.971,3.727],[15.469,1.447],[12.334,-1.173],[8.179,1.017],[-0.935,-7.882]],"v":[[35.422,-16.826],[-6.251,-41.866],[-35.806,-11.299],[-33.327,1.916],[-34.031,15.24],[2.145,12.293],[37.722,11.84],[56.931,-7.328]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":196,"s":[{"i":[[6.027,2.375],[16.048,-2.349],[19.954,-12.615],[-0.527,-5.248],[-5.678,-2.454],[-11.977,0.8],[-5.84,4.308],[0.609,9.716]],"o":[[-20.173,-7.491],[-13.151,1.925],[-5.495,3.434],[0.527,5.248],[10.548,4.58],[13.424,-0.848],[5.123,-1.836],[-0.033,-7.302]],"v":[[32.125,-10.211],[-6.251,-41.866],[-33.353,-4.497],[-38.305,11.207],[-30.361,23.484],[1.309,28.462],[33.416,19.473],[44.636,3.508]],"c":true}]},{"t":212,"s":[{"i":[[4.007,4.007],[16.048,-2.349],[11.351,-19.18],[-1.059,-5.302],[-3.442,-3.852],[-11.341,0.456],[-5.227,8.592],[-0.471,4.449]],"o":[[-12.525,-12.525],[-13.151,1.925],[-3.078,5.2],[0.946,4.737],[6.433,7.2],[14.335,-0.577],[2.568,-4.221],[0.721,-6.817]],"v":[[29.368,-4.68],[-6.251,-41.866],[-31.302,1.191],[-34.064,17.264],[-27.292,30.376],[0.611,41.98],[29.815,25.855],[34.357,12.568]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.811764717102,0.207843139768,0.007843137719,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.364705890417,0.121568627656,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"/_bl2","parent":9,"sr":1,"ks":{"p":{"a":0,"k":[-83.645,15.256,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":68,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-17.422,51.723],[16.715,33.851]],"c":false}]},{"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-17.081,8.657],[17.081,-8.657]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":82.133,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":92.268,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":102.4,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":112.533,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":122.666,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132.801,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142.934,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":153.066,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":163.199,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":173.334,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":183.467,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":193.6,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":203.732,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":213.867,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":224,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":234.133,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":244.266,"s":[0]},{"t":254.400390625,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":82.133,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":92.268,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":102.4,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":112.533,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":122.666,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132.801,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142.934,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":153.066,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":163.199,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":173.334,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":183.467,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":193.6,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":203.732,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":213.867,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":224,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":234.133,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":244.266,"s":[95]},{"t":254.400390625,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":68,"op":300,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"/_bl","parent":9,"sr":1,"ks":{"p":{"a":0,"k":[-96.129,22.065,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":68,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-48.709,69.279],[75.289,1.117]],"c":false}]},{"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-54.457,27.599],[54.457,-27.599]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":68,"op":300,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"/_sh","parent":9,"sr":1,"ks":{"o":{"a":0,"k":33},"p":{"a":0,"k":[11.345,21.386,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":68,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[133.255,-87.597],[-167.909,75.145]],"c":false}]},{"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[137.947,-69.913],[-137.947,69.913]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.639215707779,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":68,"op":300,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"/_l","parent":9,"sr":1,"ks":{"a":{"a":0,"k":[248.263,265.461,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":68,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[130.546,-90.927],[-169.425,71.392]],"c":false}]},{"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[144.191,-73.077],[-144.191,73.077]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.639215707779,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[262.772,294.09]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":68,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-143.63,123.931],[158.113,-36.23]],"c":false}]},{"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-144.191,73.077],[144.191,-73.077]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.639215707779,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[233.753,236.832]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false}],"ip":68,"op":300,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"/","parent":32,"sr":1,"ks":{"p":{"a":0,"k":[-7.737,9.461,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[165.769,-74.392],[-166.487,103.885],[-169.202,98.025],[163.103,-79.136]],"c":true}]},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[158.7,-44.448],[-129.681,101.706],[-158.7,44.448],[129.681,-101.706]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.800000011921,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":68,"op":300,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"eye_bl","parent":11,"sr":1,"ks":{"p":{"a":0,"k":[-5.809,-11.517,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[{"i":[[0.768,-4.443],[-4.443,-0.768],[-0.768,4.443],[4.443,0.768]],"o":[[-0.768,4.443],[4.443,0.768],[0.768,-4.443],[-4.443,-0.768]],"v":[[-8.044,-1.39],[-1.39,8.044],[8.044,1.39],[1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[{"i":[[0.677,-0.825],[-4.428,0.387],[-0.677,0.825],[4.428,-0.387]],"o":[[-0.677,0.825],[4.428,-0.387],[0.677,-0.825],[-4.428,0.387]],"v":[[-4.559,18.359],[2.233,19.151],[11.475,16.956],[4.684,16.163]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":96,"s":[{"i":[[0.768,-4.443],[-4.443,-0.768],[-0.768,4.443],[4.443,0.768]],"o":[[-0.768,4.443],[4.443,0.768],[0.768,-4.443],[-4.443,-0.768]],"v":[[-8.044,-1.39],[-1.39,8.044],[8.044,1.39],[1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":128,"s":[{"i":[[0.768,-4.443],[-4.443,-0.768],[-0.768,4.443],[4.443,0.768]],"o":[[-0.768,4.443],[4.443,0.768],[0.768,-4.443],[-4.443,-0.768]],"v":[[-8.044,-1.39],[-1.39,8.044],[8.044,1.39],[1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[0.677,-0.825],[-4.428,0.387],[-0.677,0.825],[4.428,-0.387]],"o":[[-0.677,0.825],[4.428,-0.387],[0.677,-0.825],[-4.428,0.387]],"v":[[-4.559,18.359],[2.233,19.151],[11.475,16.956],[4.684,16.163]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0.768,-4.443],[-4.443,-0.768],[-0.768,4.443],[4.443,0.768]],"o":[[-0.768,4.443],[4.443,0.768],[0.768,-4.443],[-4.443,-0.768]],"v":[[-8.044,-1.39],[-1.39,8.044],[8.044,1.39],[1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":178,"s":[{"i":[[0.768,-4.443],[-4.443,-0.768],[-0.768,4.443],[4.443,0.768]],"o":[[-0.768,4.443],[4.443,0.768],[0.768,-4.443],[-4.443,-0.768]],"v":[[-8.044,-1.39],[-1.39,8.044],[8.044,1.39],[1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0.677,-0.825],[-4.428,0.387],[-0.677,0.825],[4.428,-0.387]],"o":[[-0.677,0.825],[4.428,-0.387],[0.677,-0.825],[-4.428,0.387]],"v":[[-4.559,18.359],[2.233,19.151],[11.475,16.956],[4.684,16.163]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":196,"s":[{"i":[[0.783,-0.725],[-4.439,-0.22],[-0.783,0.725],[4.439,0.22]],"o":[[-0.783,0.725],[4.439,0.22],[0.783,-0.725],[-4.439,-0.22]],"v":[[-4.792,11.216],[1.828,12.927],[11.284,12.012],[4.664,10.301]],"c":true}]},{"t":202,"s":[{"i":[[0.768,-4.443],[-4.443,-0.768],[-0.768,4.443],[4.443,0.768]],"o":[[-0.768,4.443],[4.443,0.768],[0.768,-4.443],[-4.443,-0.768]],"v":[[-8.044,-1.39],[-1.39,8.044],[8.044,1.39],[1.39,-8.044]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":84,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":90,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":96,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":128,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":134,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":140,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":178,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":184,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":196,"s":[0,0,0,1]},{"t":202,"s":[1,1,1,1]}]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"eye","parent":4,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":92,"s":[66.885,-49.27,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[51.584,-48.916,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":136,"s":[51.584,-48.916,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":150,"s":[73.565,-49.592,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":186,"s":[73.565,-49.592,0],"to":[0,0,0],"ti":[0,0,0]},{"t":212,"s":[66.885,-49.27,0]}]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":92,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":106,"s":[80,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":136,"s":[80,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":150,"s":[100,100,100]},{"i":{"x":[0.3,0.3,0.3],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":186,"s":[100,100,100]},{"t":212,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[{"i":[[-2.9,-14.385],[-12.613,2.543],[2.9,14.385],[12.613,-2.543]],"o":[[2.9,14.385],[12.613,-2.543],[-2.9,-14.385],[-12.613,2.543]],"v":[[-22.837,4.604],[5.251,26.046],[22.837,-4.604],[-5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[{"i":[[0.328,-1.751],[-12.613,2.543],[1.876,1.044],[12.613,-2.543]],"o":[[-0.59,3.146],[12.613,-2.543],[-1.858,-1.033],[-12.613,2.543]],"v":[[-22.695,6.615],[3.352,7.793],[24.513,-2.653],[2.167,3.644]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":96,"s":[{"i":[[-2.9,-14.385],[-12.613,2.543],[2.9,14.385],[12.613,-2.543]],"o":[[2.9,14.385],[12.613,-2.543],[-2.9,-14.385],[-12.613,2.543]],"v":[[-22.837,4.604],[5.251,26.046],[22.837,-4.604],[-5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":128,"s":[{"i":[[-2.9,-14.385],[-12.613,2.543],[2.9,14.385],[12.613,-2.543]],"o":[[2.9,14.385],[12.613,-2.543],[-2.9,-14.385],[-12.613,2.543]],"v":[[-22.837,4.604],[5.251,26.046],[22.837,-4.604],[-5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[0.328,-1.751],[-12.613,2.543],[1.876,1.044],[12.613,-2.543]],"o":[[-0.59,3.146],[12.613,-2.543],[-1.858,-1.033],[-12.613,2.543]],"v":[[-22.695,6.615],[3.352,7.793],[24.513,-2.653],[2.167,3.644]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-2.9,-14.385],[-12.613,2.543],[2.9,14.385],[12.613,-2.543]],"o":[[2.9,14.385],[12.613,-2.543],[-2.9,-14.385],[-12.613,2.543]],"v":[[-22.837,4.604],[5.251,26.046],[22.837,-4.604],[-5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":178,"s":[{"i":[[-2.9,-14.385],[-12.613,2.543],[2.9,14.385],[12.613,-2.543]],"o":[[2.9,14.385],[12.613,-2.543],[-2.9,-14.385],[-12.613,2.543]],"v":[[-22.837,4.604],[5.251,26.046],[22.837,-4.604],[-5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0.328,-1.751],[-12.613,2.543],[1.876,1.044],[12.613,-2.543]],"o":[[-0.59,3.146],[12.613,-2.543],[-1.858,-1.033],[-12.613,2.543]],"v":[[-22.695,6.615],[3.352,7.793],[24.513,-2.653],[2.167,3.644]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":196,"s":[{"i":[[0.72,-1.63],[-12.844,0.763],[1.588,1.444],[13.508,-0.923]],"o":[[-1.293,2.928],[12.803,-0.761],[-1.573,-1.43],[-12.836,0.877]],"v":[[-23.438,1.208],[1.047,2.449],[23.404,-2.719],[0.841,-1.861]],"c":true}]},{"t":202,"s":[{"i":[[-2.9,-14.385],[-12.613,2.543],[2.9,14.385],[12.613,-2.543]],"o":[[2.9,14.385],[12.613,-2.543],[-2.9,-14.385],[-12.613,2.543]],"v":[[-22.837,4.604],[5.251,26.046],[22.837,-4.604],[-5.251,-26.046]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[8]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":128,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":134,"s":[8]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":178,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":184,"s":[8]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":196,"s":[8]},{"t":202,"s":[0]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"eyebr","parent":11,"sr":1,"ks":{"p":{"a":0,"k":[-2.814,-58.554,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[-3.88,-4.065]],"o":[[4.779,0.417],[0,0]],"v":[[-2.884,25.451],[12.517,32.218]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0,0],[-3.585,-0.326]],"o":[[3.585,3.585],[0,0]],"v":[[-7.497,-4.726],[7.497,4.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[{"i":[[0,0],[-3.585,-0.326]],"o":[[3.585,3.585],[0,0]],"v":[[-7.497,-4.726],[7.497,4.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[{"i":[[0,0],[-3.585,-0.049]],"o":[[3.585,0.541],[0,0]],"v":[[-4.497,33.3],[10.497,34.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":96,"s":[{"i":[[0,0],[-3.585,-0.326]],"o":[[3.585,3.585],[0,0]],"v":[[-7.497,-4.726],[7.497,4.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":128,"s":[{"i":[[0,0],[-3.585,-0.326]],"o":[[3.585,3.585],[0,0]],"v":[[-7.497,-4.726],[7.497,4.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[0,0],[-3.585,-0.049]],"o":[[3.585,0.541],[0,0]],"v":[[-4.497,33.3],[10.497,34.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-3.585,-0.326]],"o":[[3.585,3.585],[0,0]],"v":[[-7.497,-4.726],[7.497,4.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":178,"s":[{"i":[[0,0],[-3.585,-0.326]],"o":[[3.585,3.585],[0,0]],"v":[[-7.497,-4.726],[7.497,4.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0,0],[-3.585,-0.049]],"o":[[3.585,0.541],[0,0]],"v":[[-4.497,33.3],[10.497,34.726]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":196,"s":[{"i":[[0,0],[-3.585,-0.049]],"o":[[3.585,0.541],[0,0]],"v":[[-4.497,33.3],[10.497,34.726]],"c":false}]},{"t":202,"s":[{"i":[[0,0],[-3.585,-0.326]],"o":[[3.585,3.585],[0,0]],"v":[[-7.497,-4.726],[7.497,4.726]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"eye_bl","parent":14,"sr":1,"ks":{"p":{"a":0,"k":[-5.603,-8.455,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[{"i":[[-0.768,-4.443],[4.443,-0.768],[0.768,4.443],[-4.443,0.768]],"o":[[0.768,4.443],[-4.443,0.768],[-0.768,-4.443],[4.443,-0.768]],"v":[[8.044,-1.39],[1.39,8.044],[-8.044,1.39],[-1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[{"i":[[-0.694,-0.715],[4.428,0.375],[0.694,0.715],[-4.428,-0.375]],"o":[[0.694,0.715],[-4.428,-0.375],[-0.694,-0.715],[4.428,0.375]],"v":[[13.043,22.967],[6.281,23.583],[-2.994,21.61],[3.768,20.993]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":96,"s":[{"i":[[-0.768,-4.443],[4.443,-0.768],[0.768,4.443],[-4.443,0.768]],"o":[[0.768,4.443],[-4.443,0.768],[-0.768,-4.443],[4.443,-0.768]],"v":[[8.044,-1.39],[1.39,8.044],[-8.044,1.39],[-1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":128,"s":[{"i":[[-0.768,-4.443],[4.443,-0.768],[0.768,4.443],[-4.443,0.768]],"o":[[0.768,4.443],[-4.443,0.768],[-0.768,-4.443],[4.443,-0.768]],"v":[[8.044,-1.39],[1.39,8.044],[-8.044,1.39],[-1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[-0.694,-0.715],[4.428,0.375],[0.694,0.715],[-4.428,-0.375]],"o":[[0.694,0.715],[-4.428,-0.375],[-0.694,-0.715],[4.428,0.375]],"v":[[13.043,22.967],[6.281,23.583],[-2.994,21.61],[3.768,20.993]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-0.768,-4.443],[4.443,-0.768],[0.768,4.443],[-4.443,0.768]],"o":[[0.768,4.443],[-4.443,0.768],[-0.768,-4.443],[4.443,-0.768]],"v":[[8.044,-1.39],[1.39,8.044],[-8.044,1.39],[-1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":178,"s":[{"i":[[-0.768,-4.443],[4.443,-0.768],[0.768,4.443],[-4.443,0.768]],"o":[[0.768,4.443],[-4.443,0.768],[-0.768,-4.443],[4.443,-0.768]],"v":[[8.044,-1.39],[1.39,8.044],[-8.044,1.39],[-1.39,-8.044]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[-0.694,-0.715],[4.428,0.375],[0.694,0.715],[-4.428,-0.375]],"o":[[0.694,0.715],[-4.428,-0.375],[-0.694,-0.715],[4.428,0.375]],"v":[[13.043,22.967],[6.281,23.583],[-2.994,21.61],[3.768,20.993]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":196,"s":[{"i":[[-0.807,-0.585],[4.427,-0.393],[0.807,0.585],[-4.427,0.393]],"o":[[0.807,0.585],[-4.427,0.393],[-0.807,-0.585],[4.427,-0.393]],"v":[[13.361,18.34],[6.806,20.111],[-2.67,19.762],[3.885,17.991]],"c":true}]},{"t":202,"s":[{"i":[[-0.768,-4.443],[4.443,-0.768],[0.768,4.443],[-4.443,0.768]],"o":[[0.768,4.443],[-4.443,0.768],[-0.768,-4.443],[4.443,-0.768]],"v":[[8.044,-1.39],[1.39,8.044],[-8.044,1.39],[-1.39,-8.044]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":84,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":90,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":96,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":128,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":134,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":140,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":178,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":184,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":196,"s":[0,0,0,1]},{"t":202,"s":[1,1,1,1]}]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"eye","parent":4,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":92,"s":[-68.757,-49.27,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[-79.169,-47.871,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":136,"s":[-79.169,-47.871,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":150,"s":[-56.825,-45.23,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":186,"s":[-56.825,-45.23,0],"to":[0,0,0],"ti":[0,0,0]},{"t":212,"s":[-68.757,-49.27,0]}]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":92,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":106,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":136,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":150,"s":[80,100,100]},{"i":{"x":[0.3,0.3,0.3],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":186,"s":[80,100,100]},{"t":212,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[{"i":[[2.9,-14.385],[12.613,2.543],[-2.9,14.385],[-12.613,-2.543]],"o":[[-2.9,14.385],[-12.613,-2.543],[2.9,-14.385],[12.613,2.543]],"v":[[22.837,4.604],[-5.251,26.046],[-22.837,-4.604],[5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[{"i":[[-1.173,-0.668],[13.941,0.738],[-1.066,0.879],[-14.526,-0.228]],"o":[[0.855,0.567],[-14.499,-0.768],[1.181,-0.974],[15.349,0.241]],"v":[[26.489,9.254],[1.547,17.027],[-21.84,9.877],[2.114,11.919]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":96,"s":[{"i":[[2.9,-14.385],[12.613,2.543],[-2.9,14.385],[-12.613,-2.543]],"o":[[-2.9,14.385],[-12.613,-2.543],[2.9,-14.385],[12.613,2.543]],"v":[[22.837,4.604],[-5.251,26.046],[-22.837,-4.604],[5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":128,"s":[{"i":[[2.9,-14.385],[12.613,2.543],[-2.9,14.385],[-12.613,-2.543]],"o":[[-2.9,14.385],[-12.613,-2.543],[2.9,-14.385],[12.613,2.543]],"v":[[22.837,4.604],[-5.251,26.046],[-22.837,-4.604],[5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[-1.173,-0.668],[13.941,0.738],[-1.066,0.879],[-14.526,-0.228]],"o":[[0.855,0.567],[-14.499,-0.768],[1.181,-0.974],[15.349,0.241]],"v":[[26.489,9.254],[1.547,17.027],[-21.84,9.877],[2.114,11.919]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[2.9,-14.385],[12.613,2.543],[-2.9,14.385],[-12.613,-2.543]],"o":[[-2.9,14.385],[-12.613,-2.543],[2.9,-14.385],[12.613,2.543]],"v":[[22.837,4.604],[-5.251,26.046],[-22.837,-4.604],[5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":178,"s":[{"i":[[2.9,-14.385],[12.613,2.543],[-2.9,14.385],[-12.613,-2.543]],"o":[[-2.9,14.385],[-12.613,-2.543],[2.9,-14.385],[12.613,2.543]],"v":[[22.837,4.604],[-5.251,26.046],[-22.837,-4.604],[5.251,-26.046]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[-1.173,-0.668],[13.941,0.738],[-1.066,0.879],[-14.526,-0.228]],"o":[[0.855,0.567],[-14.499,-0.768],[1.181,-0.974],[15.349,0.241]],"v":[[26.489,9.254],[1.547,17.027],[-21.84,9.877],[2.114,11.919]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":196,"s":[{"i":[[-1.22,-0.578],[13.956,-0.313],[-0.997,0.957],[-14.502,0.866]],"o":[[0.895,0.501],[-14.516,0.326],[1.104,-1.06],[15.324,-0.915]],"v":[[26.299,7.431],[0.816,12.526],[-21.847,11.691],[1.13,9.135]],"c":true}]},{"t":202,"s":[{"i":[[2.9,-14.385],[12.613,2.543],[-2.9,14.385],[-12.613,-2.543]],"o":[[-2.9,14.385],[-12.613,-2.543],[2.9,-14.385],[12.613,2.543]],"v":[[22.837,4.604],[-5.251,26.046],[-22.837,-4.604],[5.251,-26.046]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[8]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":128,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":134,"s":[8]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":178,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":184,"s":[8]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":196,"s":[8]},{"t":202,"s":[0]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"eyebr","parent":14,"sr":1,"ks":{"p":{"a":0,"k":[-6.516,-53.175,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[-5.211,-1.201]],"o":[[5.825,-5.46],[0,0]],"v":[[-7.013,30.453],[11.642,22.829]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0,0],[-2.608,2.934]],"o":[[8.801,-6.845],[0,0]],"v":[[-8.312,6.519],[8.312,-6.519]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[{"i":[[0,0],[-2.608,2.934]],"o":[[8.801,-6.845],[0,0]],"v":[[-8.312,6.519],[8.312,-6.519]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[{"i":[[0,0],[-2.608,0.339]],"o":[[8.801,-0.792],[0,0]],"v":[[-4.812,42.019],[11.812,40.511]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":96,"s":[{"i":[[0,0],[-2.608,2.934]],"o":[[8.801,-6.845],[0,0]],"v":[[-8.312,6.519],[8.312,-6.519]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":128,"s":[{"i":[[0,0],[-2.608,2.934]],"o":[[8.801,-6.845],[0,0]],"v":[[-8.312,6.519],[8.312,-6.519]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[0,0],[-2.608,0.339]],"o":[[8.801,-0.792],[0,0]],"v":[[-4.812,42.019],[11.812,40.511]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-2.608,2.934]],"o":[[8.801,-6.845],[0,0]],"v":[[-8.312,6.519],[8.312,-6.519]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":178,"s":[{"i":[[0,0],[-2.608,2.934]],"o":[[8.801,-6.845],[0,0]],"v":[[-8.312,6.519],[8.312,-6.519]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0,0],[-2.608,0.339]],"o":[[8.801,-0.792],[0,0]],"v":[[-4.812,42.019],[11.812,40.511]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":196,"s":[{"i":[[0,0],[-2.608,0.339]],"o":[[8.801,-0.792],[0,0]],"v":[[-4.812,42.019],[11.812,40.511]],"c":false}]},{"t":202,"s":[{"i":[[0,0],[-2.608,2.934]],"o":[[8.801,-6.845],[0,0]],"v":[[-8.312,6.519],[8.312,-6.519]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"head_bl","parent":18,"sr":1,"ks":{"p":{"a":0,"k":[108.248,-5.838,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-10.353]],"o":[[10.353,14.335],[0,0]],"v":[[-6.371,-24.29],[6.371,24.29]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.988235294819,0.933333337307,0.129411771894,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":216,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":228,"s":[5]},{"t":240,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":216,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":228,"s":[100]},{"t":240,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"head_bl","parent":18,"sr":1,"ks":{"p":{"a":0,"k":[-76.374,-39.35,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[7.802,-7.63],[3.918,-22.723]],"o":[[-9.941,5.192],[-17.455,17.071],[0,0]],"v":[[29.869,-40.695],[3.168,-21.261],[-29.869,40.695]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"d":[{"n":"d","nm":"dash","v":{"a":0,"k":73}},{"n":"g","nm":"gap","v":{"a":0,"k":20}},{"n":"o","nm":"offset","v":{"a":0,"k":0}}],"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[5]},{"t":240,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[100]},{"t":240,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"head","parent":28,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[-0.081]},{"t":74,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[-24.536,-43.019,0],"to":[0,0,0],"ti":[0,0,0]},{"t":74,"s":[-21.04,-46.185,0]}]},"a":{"a":0,"k":[16.675,97.867,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[7.055,29.915],[71.089,-16.765],[-14.987,-63.55],[-26.123,-12.949]],"o":[[17.827,-23.465],[-14.987,-63.55],[-71.089,16.765],[7.074,29.996],[0,0]],"v":[[111.229,68.451],[128.838,-13.461],[-29.62,-109.215],[-128.596,47.25],[-76.495,112.536]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"wing","parent":28,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[30.551]},{"t":74,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[78.089,-46.43,0],"to":[0,0,0],"ti":[0,0,0]},{"t":74,"s":[85.442,-36.572,0]}]},"a":{"a":0,"k":[-38.5,0,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[0,0],[-3.186,-10.891],[31.234,-1.969]],"o":[[33.604,-18.059],[3.186,10.891],[0,0]],"v":[[-62.791,-22.947],[33.991,-4.39],[-15.725,10.233]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":74,"s":[{"i":[[0,0],[-3.186,-10.891],[32.263,-10.878]],"o":[[30.709,-3.412],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[42.907,-7.444],[-34.866,26.7]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":92,"s":[{"i":[[0,0],[-3.186,-10.891],[32.263,-10.878]],"o":[[30.709,-3.412],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[42.907,-7.444],[-34.866,26.7]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":100,"s":[{"i":[[0,0],[-3.186,-10.891],[34.926,-8.623]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[5.907,-20.444],[-10.866,28.2]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":110,"s":[{"i":[[0,0],[-3.186,-10.891],[30.926,-7.123]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[36.407,-30.444],[1.634,28.2]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":118,"s":[{"i":[[0,0],[-3.186,-10.891],[34.926,-8.623]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[5.907,-20.444],[-10.866,28.2]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":138,"s":[{"i":[[0,0],[-3.186,-10.891],[34.926,-8.623]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[5.907,-20.444],[-10.866,28.2]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":148,"s":[{"i":[[0,0],[-3.186,-10.891],[30.926,-7.123]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-38.627,-34.871],[48.759,-6.32],[-2.868,38.495]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":156,"s":[{"i":[[0,0],[-3.186,-10.891],[34.926,-8.623]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[5.907,-20.444],[-10.866,28.2]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":166,"s":[{"i":[[0,0],[-3.186,-10.891],[30.926,-7.123]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-38.627,-34.871],[37.474,-10.05],[-2.868,38.495]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":174,"s":[{"i":[[0,0],[-3.186,-10.891],[34.926,-8.623]],"o":[[24.615,33.652],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[5.907,-20.444],[-10.866,28.2]],"c":false}]},{"t":206,"s":[{"i":[[0,0],[-3.186,-10.891],[32.263,-10.878]],"o":[[30.709,-3.412],[3.186,10.891],[0,0]],"v":[[-43.056,-26.074],[42.907,-7.444],[-34.866,26.7]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"wing_bl","parent":21,"sr":1,"ks":{"p":{"a":0,"k":[-18.164,4.659,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[0,0],[-7.962,3.64]],"o":[[10.236,-7.279],[0,0]],"v":[[7.853,-2.894],[36.676,-24.112]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":74,"s":[{"i":[[0,0],[-7.962,3.64]],"o":[[10.236,-7.279],[0,0]],"v":[[-16.037,10.236],[16.037,-10.236]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":92,"s":[{"i":[[0,0],[-7.962,3.64]],"o":[[10.236,-7.279],[0,0]],"v":[[-16.037,10.236],[16.037,-10.236]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":100,"s":[{"i":[[0,0],[-6.982,5.417]],"o":[[8.72,9.244],[0,0]],"v":[[-0.179,-9.033],[29.27,-5.606]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":110,"s":[{"i":[[0,0],[-11.698,3.051]],"o":[[9.552,1.392],[0,0]],"v":[[-13.278,-9.676],[17.485,-11.31]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":118,"s":[{"i":[[0,0],[-6.982,5.417]],"o":[[8.72,9.244],[0,0]],"v":[[-0.179,-9.033],[29.27,-5.606]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":138,"s":[{"i":[[0,0],[-6.982,5.417]],"o":[[8.72,9.244],[0,0]],"v":[[-0.179,-9.033],[29.27,-5.606]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":148,"s":[{"i":[[0,0],[-11.698,3.051]],"o":[[9.552,1.392],[0,0]],"v":[[-13.278,-9.676],[17.485,-11.31]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":156,"s":[{"i":[[0,0],[-6.982,5.417]],"o":[[8.72,9.244],[0,0]],"v":[[-0.179,-9.033],[29.27,-5.606]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":166,"s":[{"i":[[0,0],[-11.698,3.051]],"o":[[9.552,1.392],[0,0]],"v":[[-13.278,-9.676],[17.485,-11.31]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":174,"s":[{"i":[[0,0],[-6.982,5.417]],"o":[[8.72,9.244],[0,0]],"v":[[-0.179,-9.033],[29.27,-5.606]],"c":false}]},{"t":206,"s":[{"i":[[0,0],[-7.962,3.64]],"o":[[10.236,-7.279],[0,0]],"v":[[-16.037,10.236],[16.037,-10.236]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":216,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":228,"s":[5]},{"t":240,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":216,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":228,"s":[100]},{"t":240,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"wing","parent":28,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[-36.067]},{"t":74,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[-122.157,-8.399,0],"to":[0,0,0],"ti":[0,0,0]},{"t":74,"s":[-112.784,-35.476,0]}]},"a":{"a":0,"k":[30.5,-12,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[0,0],[-2.958,-13.61],[-32.973,12.882]],"o":[[-45.283,2.228],[2.958,13.61],[0,0]],"v":[[49.746,-37.599],[-29.776,18.921],[21.241,13.628]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":74,"s":[{"i":[[0,0],[-2.958,-13.61],[-32.973,12.882]],"o":[[-38.103,24.016],[2.958,13.61],[0,0]],"v":[[13.129,-32.598],[-54.179,26.243],[54.368,16.381]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":92,"s":[{"i":[[0,0],[-2.958,-13.61],[-32.973,12.882]],"o":[[-38.103,24.016],[2.958,13.61],[0,0]],"v":[[13.129,-32.598],[-54.179,26.243],[54.368,16.381]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":100,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-1.344,54.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-26.679,-12.757],[54.368,16.381]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":110,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-6.844,30.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-43.179,-9.757],[54.368,16.381]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":118,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-1.344,54.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-26.679,-12.757],[54.368,16.381]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":138,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-1.344,54.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-26.679,-12.757],[54.368,16.381]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":148,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-6.844,30.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-43.179,-9.757],[54.368,16.381]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":156,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-1.344,54.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-26.679,-12.757],[54.368,16.381]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":166,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-6.844,30.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-43.179,-9.757],[54.368,16.381]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":174,"s":[{"i":[[0,0],[3.066,-13.586],[-57.583,27.6]],"o":[[-1.344,54.579],[-6.035,26.739],[0,0]],"v":[[13.129,-32.598],[-26.679,-12.757],[54.368,16.381]],"c":false}]},{"t":206,"s":[{"i":[[0,0],[-2.958,-13.61],[-32.973,12.882]],"o":[[-38.103,24.016],[2.958,13.61],[0,0]],"v":[[13.129,-32.598],[-54.179,26.243],[54.368,16.381]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"O_bl4","parent":25,"sr":1,"ks":{"p":{"a":0,"k":[-30.789,17.913,0]},"a":{"a":0,"k":[225.211,273.913,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.677,2.747]],"o":[[2.871,-2.545],[0,0]],"v":[[-4.163,3.971],[4.163,-3.971]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[355.926,378.368]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.539,15.159]],"o":[[8.642,-12.85],[0,0]],"v":[[-9.983,21.103],[9.983,-21.103]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[387.942,331.3]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-9.945,17.23]],"o":[[4.477,-19.951],[0,0]],"v":[[-10.94,28.009],[10.94,-28.009]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[63.436,193.496]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":82.133,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":92.268,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":102.4,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":112.533,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":122.666,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132.801,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142.934,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":153.066,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":163.199,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":173.334,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":183.467,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":193.6,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":203.732,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":213.867,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":224,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":234.133,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":244.266,"s":[0]},{"t":254.400390625,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":82.133,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":92.268,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":102.4,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":112.533,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":122.666,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132.801,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142.934,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":153.066,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":163.199,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":173.334,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":183.467,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":193.6,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":203.732,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":213.867,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":224,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":234.133,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":244.266,"s":[95]},{"t":254.400390625,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":72,"op":300,"st":0,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"O_bl3","parent":25,"sr":1,"ks":{"p":{"a":0,"k":[-16.641,-12.754,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,86.122]],"o":[[86.123,0],[0,0]],"v":[[8.904,178.402],[165.093,22.215]],"c":false}},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,29.563],[-110.621,0],[-31.544,-69.527]],"o":[[-11.531,-25.293],[0,-110.621],[81.186,0],[0,0]],"v":[[-173.753,105.162],[-191.713,22.215],[8.904,-178.402],[191.713,-60.4]],"c":false}},"nm":"Path 2","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":72,"op":300,"st":0,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"O_sh 2","parent":25,"sr":1,"ks":{"o":{"a":0,"k":33},"p":{"a":0,"k":[14.477,31.675,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-86.123]],"o":[[-86.123,0],[0,0]],"v":[[-22.214,-178.402],[-178.402,-22.214]],"c":false}},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-31.026],[110.62,0],[34.692,28.642]],"o":[[12.629,26.251],[0,110.62],[-48.397,0],[0,0]],"v":[[158.694,-108.895],[178.402,-22.214],[-22.214,178.402],[-149.752,132.534]],"c":false}},"nm":"Path 2","hd":false},{"ty":"st","c":{"a":0,"k":[0.639215707779,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":72,"op":300,"st":0,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"O 2","parent":32,"sr":1,"ks":{},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[82.394,0],[0,-82.394],[-82.394,0],[0,82.394]],"o":[[-82.394,0],[0,82.394],[82.394,0],[0,-82.394]],"v":[[-7.737,-139.727],[-156.925,9.461],[-7.737,158.649],[141.451,9.461]],"c":true}},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-114.664],[114.664,0],[0,114.664],[-114.664,0]],"o":[[0,114.664],[-114.664,0],[0,-114.664],[114.664,0]],"v":[[199.88,9.461],[-7.737,217.078],[-215.354,9.461],[-7.737,-198.156]],"c":true}},"nm":"Path 2","hd":false},{"ty":"st","c":{"a":0,"k":[0.639215707779,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":7},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.800000011921,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":72,"op":300,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"body_bl","parent":28,"sr":1,"ks":{"p":{"a":0,"k":[13.403,71.866,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[0,0],[-12.996,10.203]],"o":[[22.355,-3.168],[0,0]],"v":[[0.585,-6.873],[82.893,-37.54]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":74,"s":[{"i":[[0,0],[-14.3,8.279]],"o":[[22.578,0],[0,0]],"v":[[-42.899,9.408],[42.899,-9.408]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":94,"s":[{"i":[[0,0],[-14.3,8.279]],"o":[[22.578,0],[0,0]],"v":[[-42.899,9.408],[42.899,-9.408]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":108,"s":[{"i":[[0,0],[-14.3,8.279]],"o":[[22.578,0],[0,0]],"v":[[-47.294,25.746],[38.503,6.93]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":118,"s":[{"i":[[0,0],[-14.3,8.279]],"o":[[22.578,0],[0,0]],"v":[[-42.899,9.408],[42.899,-9.408]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":142,"s":[{"i":[[0,0],[-14.3,8.279]],"o":[[22.578,0],[0,0]],"v":[[-42.899,9.408],[42.899,-9.408]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":158,"s":[{"i":[[0,0],[-14.3,8.279]],"o":[[22.578,0],[0,0]],"v":[[-23.208,22.695],[62.589,3.879]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":166,"s":[{"i":[[0,0],[-16.794,12.189]],"o":[[26.059,-8.878],[0,0]],"v":[[-19.971,26.91],[61.956,-9.689]],"c":false}]},{"t":204,"s":[{"i":[[0,0],[-14.3,8.279]],"o":[[22.578,0],[0,0]],"v":[[-42.899,9.408],[42.899,-9.408]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.988235294819,0.933333337307,0.129411771894,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":72,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":120,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[0]},{"t":240,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":72,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":120,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[95]},{"t":240,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":27,"ty":3,"nm":"NULL CONTROL","sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":0,"k":[255.148,296.54,0]},"a":{"a":0,"k":[60,60,0]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[75,75,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":72,"s":[105,105,100]},{"t":88,"s":[100,100,100]}]}},"ao":0,"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"body","parent":27,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":60,"s":[10.154]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":74,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":92,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":106,"s":[4.619]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":116,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":138,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":152,"s":[-3.668]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":178,"s":[-3.668]},{"t":210,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[59.148,100.54,0],"to":[0,0,0],"ti":[0,0,0]},{"t":74,"s":[60.148,51.54,0]}]},"a":{"a":0,"k":[-4.687,2.752,0]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":68,"s":[110,90,100]},{"t":76,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":60,"s":[{"i":[[0,0],[-15.556,-53.369],[15.033,63.171],[28.502,8.651]],"o":[[-27.016,8.344],[17.508,60.067],[-14.305,-60.113],[0,0]],"v":[[-105.574,-57.937],[-130.991,60.125],[127.469,10.691],[59.762,-82.547]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":74,"s":[{"i":[[0,0],[-34.956,-43.224],[33.715,79.992],[29.009,6.756]],"o":[[-26.408,10.105],[40.579,50.177],[-18.496,-43.883],[0,0]],"v":[[-99.606,-49.459],[-120.972,79.715],[133.703,-3.121],[22.062,-99.289]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":94,"s":[{"i":[[0,0],[-34.956,-43.224],[33.715,79.992],[29.009,6.756]],"o":[[-26.408,10.105],[40.579,50.177],[-18.496,-43.883],[0,0]],"v":[[-99.606,-49.459],[-120.972,79.715],[133.703,-3.121],[22.062,-99.289]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":108,"s":[{"i":[[0,0],[-19.531,-52.045],[-6.786,86.541],[29.009,6.756]],"o":[[-26.408,10.105],[23.865,63.592],[7.085,-90.358],[0,0]],"v":[[-99.606,-49.459],[-127.819,82.188],[130.216,19.168],[22.062,-99.289]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":118,"s":[{"i":[[0,0],[-34.956,-43.224],[33.715,79.992],[29.009,6.756]],"o":[[-26.408,10.105],[40.579,50.177],[-18.496,-43.883],[0,0]],"v":[[-99.606,-49.459],[-120.972,79.715],[133.703,-3.121],[22.062,-99.289]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":142,"s":[{"i":[[0,0],[-34.956,-43.224],[33.715,79.992],[29.009,6.756]],"o":[[-26.408,10.105],[40.579,50.177],[-18.496,-43.883],[0,0]],"v":[[-99.606,-49.459],[-120.972,79.715],[133.703,-3.121],[22.062,-99.289]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":158,"s":[{"i":[[0,0],[-19.531,-52.045],[-6.786,86.541],[29.009,6.756]],"o":[[-26.408,10.105],[23.865,63.592],[7.085,-90.358],[0,0]],"v":[[-99.606,-49.459],[-137.819,68.688],[137.216,33.169],[22.062,-99.289]],"c":false}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":166,"s":[{"i":[[0,0],[-35.72,-42.595],[33.715,79.992],[29.009,6.756]],"o":[[-26.408,10.105],[56.989,67.958],[-18.496,-43.883],[0,0]],"v":[[-99.606,-49.459],[-103.972,94.715],[134.703,-15.621],[22.062,-99.289]],"c":false}]},{"t":204,"s":[{"i":[[0,0],[-34.956,-43.224],[33.715,79.992],[29.009,6.756]],"o":[[-26.408,10.105],[40.579,50.177],[-18.496,-43.883],[0,0]],"v":[[-99.606,-49.459],[-120.972,79.715],[133.703,-3.121],[22.062,-99.289]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":"O_bl2","parent":32,"sr":1,"ks":{"p":{"a":0,"k":[-30.789,17.913,0]},"a":{"a":0,"k":[225.211,273.913,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.677,2.747]],"o":[[2.871,-2.545],[0,0]],"v":[[-4.163,3.971],[4.163,-3.971]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[355.926,378.368]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.539,15.159]],"o":[[8.642,-12.85],[0,0]],"v":[[-9.983,21.103],[9.983,-21.103]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[387.942,331.3]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-9.945,17.23]],"o":[[4.477,-19.951],[0,0]],"v":[[-10.94,28.009],[10.94,-28.009]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[63.436,193.496]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false}],"ip":0,"op":72,"st":0,"bm":0},{"ddd":0,"ind":30,"ty":4,"nm":"O_bl1","parent":32,"sr":1,"ks":{"p":{"a":0,"k":[-16.641,-12.754,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,86.122]],"o":[[86.123,0],[0,0]],"v":[[8.904,178.402],[165.093,22.215]],"c":false}},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,29.563],[-110.621,0],[-31.544,-69.527]],"o":[[-11.531,-25.293],[0,-110.621],[81.186,0],[0,0]],"v":[[-173.753,105.162],[-191.713,22.215],[8.904,-178.402],[191.713,-60.4]],"c":false}},"nm":"Path 2","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":72,"st":0,"bm":0},{"ddd":0,"ind":31,"ty":4,"nm":"O_sh","parent":32,"sr":1,"ks":{"o":{"a":0,"k":33},"p":{"a":0,"k":[14.477,31.675,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-86.123]],"o":[[-86.123,0],[0,0]],"v":[[-22.214,-178.402],[-178.402,-22.214]],"c":false}},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-31.026],[110.62,0],[34.692,28.642]],"o":[[12.629,26.251],[0,110.62],[-48.397,0],[0,0]],"v":[[158.694,-108.895],[178.402,-22.214],[-22.214,178.402],[-149.752,132.534]],"c":false}},"nm":"Path 2","hd":false},{"ty":"st","c":{"a":0,"k":[0.639215707779,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":72,"st":0,"bm":0},{"ddd":0,"ind":32,"ty":4,"nm":"O","parent":27,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.04],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[60]},{"t":72,"s":[0]}]},"p":{"a":0,"k":[60.852,19.46,0]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0]},"t":60,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":72,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":86,"s":[94,94,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":94,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":100,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":110,"s":[108,95,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":118,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":138,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":148,"s":[108,95,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":156,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":166,"s":[108,95,100]},{"t":174,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[82.394,0],[0,-82.394],[-82.394,0],[0,82.394]],"o":[[-82.394,0],[0,82.394],[82.394,0],[0,-82.394]],"v":[[-7.737,-139.727],[-156.925,9.461],[-7.737,158.649],[141.451,9.461]],"c":true}},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-114.664],[114.664,0],[0,114.664],[-114.664,0]],"o":[[0,114.664],[-114.664,0],[0,-114.664],[114.664,0]],"v":[[199.88,9.461],[-7.737,217.078],[-215.354,9.461],[-7.737,-198.156]],"c":true}},"nm":"Path 2","hd":false},{"ty":"st","c":{"a":0,"k":[0.639215707779,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":7},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.800000011921,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":72,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"_051_GHSTBST","refId":"comp_0","sr":1,"ks":{"p":{"a":0,"k":[256,256,0]},"a":{"a":0,"k":[256,256,0]}},"ao":0,"w":512,"h":512,"ip":0,"op":180,"st":-60,"bm":0}]}
\ No newline at end of file
diff --git a/Telegram/Resources/animations/swipe_action/archive.tgs b/Telegram/Resources/animations/swipe_action/archive.tgs
new file mode 100644
index 0000000000..73e049e69c
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/archive.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/delete.tgs b/Telegram/Resources/animations/swipe_action/delete.tgs
new file mode 100644
index 0000000000..daa3a01626
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/delete.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/disabled.tgs b/Telegram/Resources/animations/swipe_action/disabled.tgs
new file mode 100644
index 0000000000..a4fb31cb25
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/disabled.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/mute.tgs b/Telegram/Resources/animations/swipe_action/mute.tgs
new file mode 100644
index 0000000000..97d7bbf68c
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/mute.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/pin.tgs b/Telegram/Resources/animations/swipe_action/pin.tgs
new file mode 100644
index 0000000000..5fbeedbc4f
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/pin.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/read.tgs b/Telegram/Resources/animations/swipe_action/read.tgs
new file mode 100644
index 0000000000..59b258677c
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/read.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/unarchive.tgs b/Telegram/Resources/animations/swipe_action/unarchive.tgs
new file mode 100644
index 0000000000..f8a4f2108f
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/unarchive.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/unmute.tgs b/Telegram/Resources/animations/swipe_action/unmute.tgs
new file mode 100644
index 0000000000..563749f53f
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/unmute.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/unpin.tgs b/Telegram/Resources/animations/swipe_action/unpin.tgs
new file mode 100644
index 0000000000..8e96e36ec9
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/unpin.tgs differ
diff --git a/Telegram/Resources/animations/swipe_action/unread.tgs b/Telegram/Resources/animations/swipe_action/unread.tgs
new file mode 100644
index 0000000000..97ce96a05f
Binary files /dev/null and b/Telegram/Resources/animations/swipe_action/unread.tgs differ
diff --git a/Telegram/Resources/icons/chat/input_gift.png b/Telegram/Resources/icons/chat/input_gift.png
new file mode 100644
index 0000000000..c1f42e5e84
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_gift.png differ
diff --git a/Telegram/Resources/icons/chat/input_gift@2x.png b/Telegram/Resources/icons/chat/input_gift@2x.png
new file mode 100644
index 0000000000..79bacc11a5
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_gift@2x.png differ
diff --git a/Telegram/Resources/icons/chat/input_gift@3x.png b/Telegram/Resources/icons/chat/input_gift@3x.png
new file mode 100644
index 0000000000..83f17c0b99
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_gift@3x.png differ
diff --git a/Telegram/Resources/icons/menu/hourglass.png b/Telegram/Resources/icons/menu/hourglass.png
new file mode 100644
index 0000000000..e7389fb11a
Binary files /dev/null and b/Telegram/Resources/icons/menu/hourglass.png differ
diff --git a/Telegram/Resources/icons/menu/hourglass@2x.png b/Telegram/Resources/icons/menu/hourglass@2x.png
new file mode 100644
index 0000000000..69a579183a
Binary files /dev/null and b/Telegram/Resources/icons/menu/hourglass@2x.png differ
diff --git a/Telegram/Resources/icons/menu/hourglass@3x.png b/Telegram/Resources/icons/menu/hourglass@3x.png
new file mode 100644
index 0000000000..0fcfcfab9a
Binary files /dev/null and b/Telegram/Resources/icons/menu/hourglass@3x.png differ
diff --git a/Telegram/Resources/icons/settings/mini_gift.png b/Telegram/Resources/icons/settings/mini_gift.png
new file mode 100644
index 0000000000..6e1f566065
Binary files /dev/null and b/Telegram/Resources/icons/settings/mini_gift.png differ
diff --git a/Telegram/Resources/icons/settings/mini_gift@2x.png b/Telegram/Resources/icons/settings/mini_gift@2x.png
new file mode 100644
index 0000000000..7a5e301e1a
Binary files /dev/null and b/Telegram/Resources/icons/settings/mini_gift@2x.png differ
diff --git a/Telegram/Resources/icons/settings/mini_gift@3x.png b/Telegram/Resources/icons/settings/mini_gift@3x.png
new file mode 100644
index 0000000000..d34d1b6dea
Binary files /dev/null and b/Telegram/Resources/icons/settings/mini_gift@3x.png differ
diff --git a/Telegram/Resources/icons/tray_monochrome_attention.svg b/Telegram/Resources/icons/tray_monochrome_attention.svg
new file mode 100644
index 0000000000..95b8c2cfaf
--- /dev/null
+++ b/Telegram/Resources/icons/tray_monochrome_attention.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/Telegram/Resources/icons/tray_monochrome_mute.svg b/Telegram/Resources/icons/tray_monochrome_mute.svg
new file mode 100644
index 0000000000..448f6990b2
--- /dev/null
+++ b/Telegram/Resources/icons/tray_monochrome_mute.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index dfff5dd622..8f3ca87072 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -681,6 +681,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_shortcuts_archive_chat" = "Archive chat";
"lng_shortcuts_media_fullscreen" = "Toggle video fullscreen";
"lng_shortcuts_show_chat_menu" = "Show chat menu";
+"lng_shortcuts_show_chat_preview" = "Show chat preview";
"lng_settings_chat_reactions_title" = "Quick Reaction";
"lng_settings_chat_reactions_subtitle" = "Choose your favorite reaction";
@@ -1179,6 +1180,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_restart_now" = "Restart";
"lng_settings_restart_later" = "Later";
+"lng_settings_quick_dialog_action_title" = "Chat list quick action";
+"lng_settings_quick_dialog_action_about" = "Choose the action you want to perform when you middle-click or swipe left in the chat list.";
+"lng_settings_quick_dialog_action_both" = "Swipe left and Middle-click";
+"lng_settings_quick_dialog_action_swipe" = "Swipe left";
+"lng_settings_quick_dialog_action_mute" = "Mute";
+"lng_settings_quick_dialog_action_unmute" = "Unmute";
+"lng_settings_quick_dialog_action_pin" = "Pin";
+"lng_settings_quick_dialog_action_unpin" = "Unpin";
+"lng_settings_quick_dialog_action_read" = "Read";
+"lng_settings_quick_dialog_action_unread" = "Unread";
+"lng_settings_quick_dialog_action_archive" = "Archive";
+"lng_settings_quick_dialog_action_unarchive" = "Unarchive";
+"lng_settings_quick_dialog_action_delete" = "Delete";
+"lng_settings_quick_dialog_action_disabled" = "Change folder";
+
+"lng_settings_generic_subscribe" = "Subscribe to {link} to use this setting.";
+"lng_settings_generic_subscribe_link" = "Telegram Premium";
+
"lng_sessions_header" = "This device";
"lng_sessions_other_header" = "Active Devices";
"lng_sessions_other_desc" = "You can log in to Telegram from other mobile, tablet and desktop devices, using the same phone number. All your data will be instantly synchronized.";
@@ -1294,6 +1313,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_gifts_always_title" = "Always allow";
"lng_edit_privacy_gifts_never_title" = "Never allow";
+"lng_edit_privacy_gifts_types" = "Accepted Gift Types";
+"lng_edit_privacy_gifts_premium" = "Premium Subscriptions";
+"lng_edit_privacy_gifts_unlimited" = "Unlimited";
+"lng_edit_privacy_gifts_limited" = "Limited-Edition";
+"lng_edit_privacy_gifts_unique" = "Unique";
+"lng_edit_privacy_gifts_types_about" = "Choose the types of gifts that you accept.";
+"lng_edit_privacy_gifts_show_icon" = "Show Gift Icon in Chats";
+"lng_edit_privacy_gifts_show_icon_about" = "Display the {emoji}Gift icon in the message input field for both participants in all chats.";
+"lng_edit_privacy_gifts_restricted" = "This user doesn't accept gifts.";
+
"lng_edit_privacy_calls_title" = "Calls";
"lng_edit_privacy_calls_header" = "Who can call me";
"lng_edit_privacy_calls_always_empty" = "Always allow";
@@ -2173,6 +2202,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_paid_message_some#other" = "send {count} messages";
"lng_action_paid_message_got#one" = "You received {count} Star from {name}";
"lng_action_paid_message_got#other" = "You received {count} Stars from {name}";
+"lng_action_paid_message_refund#one" = "{from} refunded {count} Star to you";
+"lng_action_paid_message_refund#other" = "{from} refunded {count} Stars to you";
+"lng_action_paid_message_refund_self#one" = "You refunded {count} Star to {name}";
+"lng_action_paid_message_refund_self#other" = "You refunded {count} Stars to {name}";
+"lng_action_message_price_free" = "Messages are now free in this group.";
+"lng_action_message_price_paid#one" = "Messages now cost {count} Star each in this group.";
+"lng_action_message_price_paid#other" = "Messages now cost {count} Stars each in this group.";
"lng_you_paid_stars#one" = "You paid {count} Star.";
"lng_you_paid_stars#other" = "You paid {count} Stars.";
@@ -2906,8 +2942,29 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_chatbots_include_button" = "Select Chats";
"lng_chatbots_exclude_about" = "Select chats or entire chat categories which the bot will not have access to.";
"lng_chatbots_permissions_title" = "Bot permissions";
+
+"lng_chatbots_manage_messages" = "Manage Messages";
+"lng_chatbots_read" = "Read Messages";
"lng_chatbots_reply" = "Reply to Messages";
-"lng_chatbots_reply_about" = "The bot can only reply on your behalf in chats that were active during the last 24h.";
+"lng_chatbots_mark_as_read" = "Mark Messages as Read";
+"lng_chatbots_delete_sent" = "Delete Sent Messages";
+"lng_chatbots_delete_received" = "Delete Received Messages";
+
+"lng_chatbots_manage_profile" = "Manage Profile";
+"lng_chatbots_edit_name" = "Edit Name";
+"lng_chatbots_edit_bio" = "Edit Bio";
+"lng_chatbots_edit_userpic" = "Edit Profile Picture";
+"lng_chatbots_edit_username" = "Edit Username";
+
+"lng_chatbots_manage_gifts" = "Manage Gifts and Stars";
+"lng_chatbots_view_gifts" = "View Gifts";
+"lng_chatbots_sell_gifts" = "Sell Gifts";
+"lng_chatbots_gift_settings" = "Change Gift Settings";
+"lng_chatbots_transfer_gifts" = "Transfer and Upgrade Gifts";
+"lng_chatbots_transfer_stars" = "Transfer Stars";
+
+"lng_chatbots_manage_stories" = "Manage Stories";
+
"lng_chatbots_remove" = "Remove Bot";
"lng_chatbots_not_found" = "Chatbot not found.";
"lng_chatbots_not_supported" = "This bot doesn't support Telegram Business yet.";
@@ -3342,6 +3399,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_stars_limited" = "limited";
"lng_gift_stars_sold_out" = "sold out";
"lng_gift_stars_tabs_all" = "All Gifts";
+"lng_gift_stars_tabs_my" = "My Gifts";
"lng_gift_stars_tabs_limited" = "Limited";
"lng_gift_stars_tabs_in_stock" = "In Stock";
"lng_gift_send_title" = "Send a Gift";
@@ -3371,7 +3429,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_limited_of_one" = "unique";
"lng_gift_limited_of_count" = "1 of {amount}";
"lng_gift_collectible_tag" = "gift";
-"lng_gift_price_unique" = "Unique";
"lng_gift_view_unpack" = "Unpack";
"lng_gift_anonymous_hint" = "Only you can see the sender's name.";
"lng_gift_anonymous_hint_channel" = "Only admins of this channel can see the sender's name.";
@@ -3428,7 +3485,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_display_done_channel" = "The gift is now shown in channel's Gifts.";
"lng_gift_display_done_hide" = "The gift is now hidden from your profile page.";
"lng_gift_display_done_hide_channel" = "The gift is now hidden from channel's Gifts.";
+"lng_gift_pinned_done_title" = "{gift} pinned";
"lng_gift_pinned_done" = "The gift will always be shown on top.";
+"lng_gift_pinned_done_replaced" = "replacing {gift}";
"lng_gift_got_stars#one" = "You got **{count} Star** for this gift.";
"lng_gift_got_stars#other" = "You got **{count} Stars** for this gift.";
"lng_gift_channel_got#one" = "Channel got **{count} Star** for this gift.";
@@ -3501,6 +3560,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_wear_subscribe" = "Subscribe to {link} to wear collectibles.";
"lng_gift_wear_start_toast" = "You put on {name}";
"lng_gift_wear_end_toast" = "You took off {name}";
+"lng_gift_many_pinned_title" = "Too Many Pinned Gifts";
+"lng_gift_many_pinned_choose" = "Select a gift to unpin below";
"lng_accounts_limit_title" = "Limit Reached";
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";
@@ -4331,6 +4392,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_search_filter_private" = "Private chats";
"lng_search_filter_group" = "Group chats";
"lng_search_filter_channel" = "Channels";
+"lng_search_sponsored_button" = "Ad â‹®";
"lng_media_save_progress" = "{ready} of {total} {mb}";
"lng_mediaview_save_as" = "Save As...";
@@ -5745,6 +5807,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sponsored_revenued_info1_title" = "Respect Your Privacy";
"lng_sponsored_revenued_info1_description" = "Ads on Telegram do not use your personal information and are based on the channel in which you see them.";
"lng_sponsored_revenued_info1_bot_description" = "Ads on Telegram do not use your personal information and are based on the mini app in which you see them.";
+"lng_sponsored_revenued_info1_search_description" = "Ads on Telegram do not use your personal information and are based on the search query you entered.";
"lng_sponsored_revenued_info2_title" = "Help the Channel Creator";
"lng_sponsored_revenued_info2_bot_title" = "Help the Bot Developer";
"lng_sponsored_revenued_info2_description" = "50% of the revenue from Telegram Ads goes to the owner of the channel where they are displayed.";
@@ -5753,9 +5816,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sponsored_revenued_info3_description#one" = "You can turn off ads by subscribing to {link}, and Level {count} channels can remove them for their subscribers.";
"lng_sponsored_revenued_info3_description#other" = "You can turn off ads by subscribing to {link}, and Level {count} channels can remove them for their subscribers.";
"lng_sponsored_revenued_info3_bot_description" = "You can turn off ads in mini apps by subscribing to {link}.";
+"lng_sponsored_revenued_info3_search_description" = "You can turn off ads by subscribing to Telegram Premium. {link}";
+"lng_sponsored_revenued_info3_search_link" = "Subscribe {arrow}";
"lng_sponsored_revenued_footer_title" = "Can I Launch an Ad?";
"lng_sponsored_revenued_footer_description" = "Anyone can create an ad to display in this channel — with minimal budgets. Check out the **Telegram Ad Platform** for details. {link}";
"lng_sponsored_revenued_footer_bot_description" = "Anyone can create an ad to display in this bot — with minimal budgets. Check out the **Telegram Ad Platform** for details. {link}";
+"lng_sponsored_revenued_footer_search_description" = "Anyone can create an ad to display in search results for any query. Check out the **Telegram Ad Platform** for details. {link}";
"lng_sponsored_top_bar_hide" = "remove";
"lng_telegram_features_url" = "https://t.me/TelegramTips";
@@ -6241,6 +6307,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_qr_box_transparent_background" = "Transparent Background";
"lng_qr_box_font_size" = "Font size";
+"lng_frozen_bar_title" = "Your account is frozen!";
+"lng_frozen_bar_text" = "Click to view details {arrow}";
+"lng_frozen_restrict_title" = "Your account is frozen";
+"lng_frozen_restrict_text" = "Click to view details";
+"lng_frozen_title" = "Your Account is Frozen";
+"lng_frozen_subtitle1" = "Violation of Terms";
+"lng_frozen_text1" = "Your account was frozen for breaking Telegram's Terms and Conditions.";
+"lng_frozen_subtitle2" = "Read-Only Mode";
+"lng_frozen_text2" = "You can access your account but can't send messages or take actions.";
+"lng_frozen_subtitle3" = "Appeal Before Deactivation";
+"lng_frozen_text3" = "Appeal via {link} before {date}, or your account will be deleted.";
+"lng_frozen_appeal_button" = "Submit an Appeal";
+
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose Default Program...";
diff --git a/Telegram/Resources/qrc/telegram/animations.qrc b/Telegram/Resources/qrc/telegram/animations.qrc
index e66d847b6a..5feeeacbc6 100644
--- a/Telegram/Resources/qrc/telegram/animations.qrc
+++ b/Telegram/Resources/qrc/telegram/animations.qrc
@@ -30,6 +30,7 @@
../../animations/noresults.tgs
../../animations/hello_status.tgs
../../animations/starref_link.tgs
+ ../../animations/media_forbidden.tgs
../../animations/dice/dice_idle.tgs
../../animations/dice/dart_idle.tgs
@@ -49,5 +50,16 @@
../../animations/star_reaction/effect1.tgs
../../animations/star_reaction/effect2.tgs
../../animations/star_reaction/effect3.tgs
+
+ ../../animations/swipe_action/archive.tgs
+ ../../animations/swipe_action/unarchive.tgs
+ ../../animations/swipe_action/delete.tgs
+ ../../animations/swipe_action/disabled.tgs
+ ../../animations/swipe_action/mute.tgs
+ ../../animations/swipe_action/unmute.tgs
+ ../../animations/swipe_action/pin.tgs
+ ../../animations/swipe_action/unpin.tgs
+ ../../animations/swipe_action/read.tgs
+ ../../animations/swipe_action/unread.tgs
diff --git a/Telegram/Resources/qrc/telegram/telegram.qrc b/Telegram/Resources/qrc/telegram/telegram.qrc
index 7ca5f84b6f..8fcea19be9 100644
--- a/Telegram/Resources/qrc/telegram/telegram.qrc
+++ b/Telegram/Resources/qrc/telegram/telegram.qrc
@@ -24,6 +24,8 @@
../../icons/settings/star.svg
../../icons/settings/starmini.svg
../../icons/tray_monochrome.svg
+ ../../icons/tray_monochrome_attention.svg
+ ../../icons/tray_monochrome_mute.svg
../../art/topic_icons/blue.svg
../../art/topic_icons/yellow.svg
../../art/topic_icons/violet.svg
diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml
index 990e326bf2..8fa9ad8dc6 100644
--- a/Telegram/Resources/uwp/AppX/AppxManifest.xml
+++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml
@@ -10,7 +10,7 @@
+ Version="5.13.1.0" />
Telegram Desktop
Telegram Messenger LLP
diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc
index 26296ddc66..e0136007f9 100644
--- a/Telegram/Resources/winrc/Telegram.rc
+++ b/Telegram/Resources/winrc/Telegram.rc
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,12,3,0
- PRODUCTVERSION 5,12,3,0
+ FILEVERSION 5,13,1,0
+ PRODUCTVERSION 5,13,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop"
- VALUE "FileVersion", "5.12.3.0"
+ VALUE "FileVersion", "5.13.1.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "5.12.3.0"
+ VALUE "ProductVersion", "5.13.1.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc
index a52f9c8416..cb637e054d 100644
--- a/Telegram/Resources/winrc/Updater.rc
+++ b/Telegram/Resources/winrc/Updater.rc
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,12,3,0
- PRODUCTVERSION 5,12,3,0
+ FILEVERSION 5,13,1,0
+ PRODUCTVERSION 5,13,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater"
- VALUE "FileVersion", "5.12.3.0"
+ VALUE "FileVersion", "5.13.1.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "5.12.3.0"
+ VALUE "ProductVersion", "5.13.1.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/SourceFiles/api/api_confirm_phone.cpp b/Telegram/SourceFiles/api/api_confirm_phone.cpp
index 3a42a793df..a3b41fefc9 100644
--- a/Telegram/SourceFiles/api/api_confirm_phone.cpp
+++ b/Telegram/SourceFiles/api/api_confirm_phone.cpp
@@ -150,6 +150,9 @@ void ConfirmPhone::resolve(
}, [](const MTPDauth_sentCodeSuccess &) {
LOG(("API Error: Unexpected auth.sentCodeSuccess "
"(Api::ConfirmPhone)."));
+ }, [](const MTPDauth_sentCodePaymentRequired &) {
+ LOG(("API Error: Unexpected auth.sentCodePaymentRequired "
+ "(Api::ConfirmPhone)."));
});
}).fail([=](const MTP::Error &error) {
_sendRequestId = 0;
diff --git a/Telegram/SourceFiles/api/api_global_privacy.cpp b/Telegram/SourceFiles/api/api_global_privacy.cpp
index 90c56ae4e5..2a2def3c5a 100644
--- a/Telegram/SourceFiles/api/api_global_privacy.cpp
+++ b/Telegram/SourceFiles/api/api_global_privacy.cpp
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_global_privacy.h"
#include "apiwrap.h"
+#include "data/data_user.h"
#include "main/main_session.h"
#include "main/main_app_config.h"
@@ -115,7 +116,8 @@ void GlobalPrivacy::updateHideReadTime(bool hide) {
unarchiveOnNewMessageCurrent(),
hide,
newRequirePremiumCurrent(),
- newChargeStarsCurrent());
+ newChargeStarsCurrent(),
+ disallowedGiftTypesCurrent());
}
bool GlobalPrivacy::hideReadTimeCurrent() const {
@@ -150,7 +152,27 @@ void GlobalPrivacy::updateMessagesPrivacy(
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
requirePremium,
- chargeStars);
+ chargeStars,
+ disallowedGiftTypesCurrent());
+}
+
+DisallowedGiftTypes GlobalPrivacy::disallowedGiftTypesCurrent() const {
+ return _disallowedGiftTypes.current();
+}
+
+auto GlobalPrivacy::disallowedGiftTypes() const
+ -> rpl::producer {
+ return _disallowedGiftTypes.value();
+}
+
+void GlobalPrivacy::updateDisallowedGiftTypes(DisallowedGiftTypes types) {
+ update(
+ archiveAndMuteCurrent(),
+ unarchiveOnNewMessageCurrent(),
+ hideReadTimeCurrent(),
+ newRequirePremiumCurrent(),
+ newChargeStarsCurrent(),
+ types);
}
void GlobalPrivacy::loadPaidReactionShownPeer() {
@@ -182,7 +204,8 @@ void GlobalPrivacy::updateArchiveAndMute(bool value) {
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
newRequirePremiumCurrent(),
- newChargeStarsCurrent());
+ newChargeStarsCurrent(),
+ disallowedGiftTypesCurrent());
}
void GlobalPrivacy::updateUnarchiveOnNewMessage(
@@ -192,7 +215,8 @@ void GlobalPrivacy::updateUnarchiveOnNewMessage(
value,
hideReadTimeCurrent(),
newRequirePremiumCurrent(),
- newChargeStarsCurrent());
+ newChargeStarsCurrent(),
+ disallowedGiftTypesCurrent());
}
void GlobalPrivacy::update(
@@ -200,12 +224,16 @@ void GlobalPrivacy::update(
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium,
- int newChargeStars) {
+ int newChargeStars,
+ DisallowedGiftTypes disallowedGiftTypes) {
using Flag = MTPDglobalPrivacySettings::Flag;
+ using DisallowedFlag = MTPDdisallowedGiftsSettings::Flag;
_api.request(_requestId).cancel();
const auto newRequirePremiumAllowed = _session->premium()
|| _session->appConfig().newRequirePremiumFree();
+ const auto showGiftIcon
+ = (disallowedGiftTypes & DisallowedGiftType::SendHide);
const auto flags = Flag()
| (archiveAndMute
? Flag::f_archive_and_mute_new_noncontact_peers
@@ -220,14 +248,35 @@ void GlobalPrivacy::update(
| ((newRequirePremium && newRequirePremiumAllowed)
? Flag::f_new_noncontact_peers_require_premium
: Flag())
- | Flag::f_noncontact_peers_paid_stars;
+ | Flag::f_noncontact_peers_paid_stars
+ | (showGiftIcon ? Flag::f_display_gifts_button : Flag())
+ | Flag::f_disallowed_gifts;
+ const auto disallowedFlags = DisallowedFlag()
+ | ((disallowedGiftTypes & DisallowedGiftType::Premium)
+ ? DisallowedFlag::f_disallow_premium_gifts
+ : DisallowedFlag())
+ | ((disallowedGiftTypes & DisallowedGiftType::Unlimited)
+ ? DisallowedFlag::f_disallow_unlimited_stargifts
+ : DisallowedFlag())
+ | ((disallowedGiftTypes & DisallowedGiftType::Limited)
+ ? DisallowedFlag::f_disallow_limited_stargifts
+ : DisallowedFlag())
+ | ((disallowedGiftTypes & DisallowedGiftType::Unique)
+ ? DisallowedFlag::f_disallow_unique_stargifts
+ : DisallowedFlag());
+ const auto typesWas = _disallowedGiftTypes.current();
+ const auto typesChanged = (typesWas != disallowedGiftTypes);
_requestId = _api.request(MTPaccount_SetGlobalPrivacySettings(
MTP_globalPrivacySettings(
MTP_flags(flags),
- MTP_long(newChargeStars))
+ MTP_long(newChargeStars),
+ MTP_disallowedGiftsSettings(MTP_flags(disallowedFlags)))
)).done([=](const MTPGlobalPrivacySettings &result) {
_requestId = 0;
apply(result);
+ if (typesChanged) {
+ _session->user()->updateFullForced();
+ }
}).fail([=](const MTP::Error &error) {
_requestId = 0;
if (error.type() == u"PREMIUM_ACCOUNT_REQUIRED"_q) {
@@ -236,7 +285,8 @@ void GlobalPrivacy::update(
unarchiveOnNewMessage,
hideReadTime,
false,
- 0);
+ 0,
+ DisallowedGiftTypes());
}
}).send();
_archiveAndMute = archiveAndMute;
@@ -244,6 +294,7 @@ void GlobalPrivacy::update(
_hideReadTime = hideReadTime;
_newRequirePremium = newRequirePremium;
_newChargeStars = newChargeStars;
+ _disallowedGiftTypes = disallowedGiftTypes;
}
void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &settings) {
@@ -257,6 +308,29 @@ void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &settings) {
_hideReadTime = data.is_hide_read_marks();
_newRequirePremium = data.is_new_noncontact_peers_require_premium();
_newChargeStars = data.vnoncontact_peers_paid_stars().value_or_empty();
+ if (const auto gifts = data.vdisallowed_gifts()) {
+ const auto &disallow = gifts->data();
+ _disallowedGiftTypes = DisallowedGiftType()
+ | (disallow.is_disallow_unlimited_stargifts()
+ ? DisallowedGiftType::Unlimited
+ : DisallowedGiftType())
+ | (disallow.is_disallow_limited_stargifts()
+ ? DisallowedGiftType::Limited
+ : DisallowedGiftType())
+ | (disallow.is_disallow_unique_stargifts()
+ ? DisallowedGiftType::Unique
+ : DisallowedGiftType())
+ | (disallow.is_disallow_premium_gifts()
+ ? DisallowedGiftType::Premium
+ : DisallowedGiftType())
+ | (data.is_display_gifts_button()
+ ? DisallowedGiftType::SendHide
+ : DisallowedGiftType());
+ } else {
+ _disallowedGiftTypes = data.is_display_gifts_button()
+ ? DisallowedGiftType::SendHide
+ : DisallowedGiftType();
+ }
}
} // namespace Api
diff --git a/Telegram/SourceFiles/api/api_global_privacy.h b/Telegram/SourceFiles/api/api_global_privacy.h
index 6b0fc064b3..7346f2ff00 100644
--- a/Telegram/SourceFiles/api/api_global_privacy.h
+++ b/Telegram/SourceFiles/api/api_global_privacy.h
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
+#include "base/flags.h"
#include "mtproto/sender.h"
class ApiWrap;
@@ -23,6 +24,17 @@ enum class UnarchiveOnNewMessage {
AnyUnmuted,
};
+enum class DisallowedGiftType : uchar {
+ Limited = 0x01,
+ Unlimited = 0x02,
+ Unique = 0x04,
+ Premium = 0x08,
+ SendHide = 0x10,
+};
+inline constexpr bool is_flag_type(DisallowedGiftType) { return true; }
+
+using DisallowedGiftTypes = base::flags;
+
[[nodiscard]] PeerId ParsePaidReactionShownPeer(
not_null session,
const MTPPaidReactionPrivacy &value);
@@ -57,6 +69,11 @@ public:
void updateMessagesPrivacy(bool requirePremium, int chargeStars);
+ [[nodiscard]] DisallowedGiftTypes disallowedGiftTypesCurrent() const;
+ [[nodiscard]] auto disallowedGiftTypes() const
+ -> rpl::producer;
+ void updateDisallowedGiftTypes(DisallowedGiftTypes types);
+
void loadPaidReactionShownPeer();
void updatePaidReactionShownPeer(PeerId shownPeer);
[[nodiscard]] PeerId paidReactionShownPeerCurrent() const;
@@ -70,7 +87,8 @@ private:
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium,
- int newChargeStars);
+ int newChargeStars,
+ DisallowedGiftTypes disallowedGiftTypes);
const not_null _session;
MTP::Sender _api;
@@ -82,6 +100,7 @@ private:
rpl::variable _hideReadTime = false;
rpl::variable _newRequirePremium = false;
rpl::variable _newChargeStars = 0;
+ rpl::variable _disallowedGiftTypes;
rpl::variable _paidReactionShownPeer = false;
std::vector> _callbacks;
bool _paidReactionShownPeerLoaded = false;
diff --git a/Telegram/SourceFiles/api/api_peer_search.cpp b/Telegram/SourceFiles/api/api_peer_search.cpp
new file mode 100644
index 0000000000..789334681e
--- /dev/null
+++ b/Telegram/SourceFiles/api/api_peer_search.cpp
@@ -0,0 +1,170 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#include "api/api_peer_search.h"
+
+#include "api/api_single_message_search.h"
+#include "apiwrap.h"
+#include "data/data_session.h"
+#include "dialogs/ui/chat_search_in.h" // IsHashOrCashtagSearchQuery
+#include "main/main_session.h"
+
+namespace Api {
+namespace {
+
+constexpr auto kMinSponsoredQueryLength = 4;
+
+} // namespace
+
+PeerSearch::PeerSearch(not_null session, Type type)
+: _session(session)
+, _type(type) {
+}
+
+PeerSearch::~PeerSearch() {
+ clear();
+}
+
+void PeerSearch::request(
+ const QString &query,
+ Fn callback,
+ RequestType type) {
+ using namespace Dialogs;
+ _query = Api::ConvertPeerSearchQuery(query);
+ _callback = callback;
+ if (_query.isEmpty()
+ || IsHashOrCashtagSearchQuery(_query) != HashOrCashtag::None) {
+ finish(PeerSearchResult{});
+ return;
+ }
+ auto &cache = _cache[_query];
+ if (cache.peersReady && cache.sponsoredReady) {
+ finish(cache.result);
+ return;
+ } else if (type == RequestType::CacheOnly) {
+ _callback = nullptr;
+ return;
+ } else if (cache.requested) {
+ return;
+ }
+ cache.requested = true;
+ cache.result.query = _query;
+ if (_query.size() < kMinSponsoredQueryLength) {
+ cache.sponsoredReady = true;
+ } else if (_type == Type::WithSponsored) {
+ requestSponsored();
+ }
+ requestPeers();
+}
+
+void PeerSearch::requestPeers() {
+ const auto requestId = _session->api().request(MTPcontacts_Search(
+ MTP_string(_query),
+ MTP_int(SearchPeopleLimit)
+ )).done([=](const MTPcontacts_Found &result, mtpRequestId requestId) {
+ const auto &data = result.data();
+ _session->data().processUsers(data.vusers());
+ _session->data().processChats(data.vchats());
+ auto parsed = PeerSearchResult();
+ parsed.my.reserve(data.vmy_results().v.size());
+ for (const auto &id : data.vmy_results().v) {
+ const auto peerId = peerFromMTP(id);
+ parsed.my.push_back(_session->data().peer(peerId));
+ }
+ parsed.peers.reserve(data.vresults().v.size());
+ for (const auto &id : data.vresults().v) {
+ const auto peerId = peerFromMTP(id);
+ parsed.peers.push_back(_session->data().peer(peerId));
+ }
+ finishPeers(requestId, std::move(parsed));
+ }).fail([=](const MTP::Error &error, mtpRequestId requestId) {
+ finishPeers(requestId, PeerSearchResult{});
+ }).send();
+ _peerRequests.emplace(requestId, _query);
+}
+
+void PeerSearch::requestSponsored() {
+ const auto requestId = _session->api().request(
+ MTPcontacts_GetSponsoredPeers(MTP_string(_query))
+ ).done([=](
+ const MTPcontacts_SponsoredPeers &result,
+ mtpRequestId requestId) {
+ result.match([&](const MTPDcontacts_sponsoredPeersEmpty &) {
+ finishSponsored(requestId, PeerSearchResult{});
+ }, [&](const MTPDcontacts_sponsoredPeers &data) {
+ _session->data().processUsers(data.vusers());
+ _session->data().processChats(data.vchats());
+ auto parsed = PeerSearchResult();
+ parsed.sponsored.reserve(data.vpeers().v.size());
+ for (const auto &peer : data.vpeers().v) {
+ const auto &data = peer.data();
+ const auto peerId = peerFromMTP(data.vpeer());
+ parsed.sponsored.push_back({
+ .peer = _session->data().peer(peerId),
+ .randomId = data.vrandom_id().v,
+ .sponsorInfo = TextWithEntities::Simple(
+ qs(data.vsponsor_info().value_or_empty())),
+ .additionalInfo = TextWithEntities::Simple(
+ qs(data.vadditional_info().value_or_empty())),
+ });
+ }
+ finishSponsored(requestId, std::move(parsed));
+ });
+ }).fail([=](const MTP::Error &error, mtpRequestId requestId) {
+ finishSponsored(requestId, PeerSearchResult{});
+ }).send();
+ _sponsoredRequests.emplace(requestId, _query);
+}
+
+void PeerSearch::finishPeers(
+ mtpRequestId requestId,
+ PeerSearchResult result) {
+ const auto query = _peerRequests.take(requestId);
+ Assert(query.has_value());
+
+ auto &cache = _cache[*query];
+ cache.peersReady = true;
+ cache.result.my = std::move(result.my);
+ cache.result.peers = std::move(result.peers);
+ if (cache.sponsoredReady && _query == *query) {
+ finish(cache.result);
+ }
+}
+
+void PeerSearch::finishSponsored(
+ mtpRequestId requestId,
+ PeerSearchResult result) {
+ const auto query = _sponsoredRequests.take(requestId);
+ Assert(query.has_value());
+
+ auto &cache = _cache[*query];
+ cache.sponsoredReady = true;
+ cache.result.sponsored = std::move(result.sponsored);
+ if (cache.peersReady && _query == *query) {
+ finish(cache.result);
+ }
+}
+
+void PeerSearch::finish(PeerSearchResult result) {
+ if (const auto onstack = base::take(_callback)) {
+ onstack(std::move(result));
+ }
+}
+
+void PeerSearch::clear() {
+ _query = QString();
+ _callback = nullptr;
+ _cache.clear();
+ for (const auto &[requestId, query] : base::take(_peerRequests)) {
+ _session->api().request(requestId).cancel();
+ }
+ for (const auto &[requestId, query] : base::take(_sponsoredRequests)) {
+ _session->api().request(requestId).cancel();
+ }
+}
+
+} // namespace Api
diff --git a/Telegram/SourceFiles/api/api_peer_search.h b/Telegram/SourceFiles/api/api_peer_search.h
new file mode 100644
index 0000000000..c706429521
--- /dev/null
+++ b/Telegram/SourceFiles/api/api_peer_search.h
@@ -0,0 +1,76 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#pragma once
+
+namespace Main {
+class Session;
+} // namespace Main
+
+namespace Api {
+
+struct SponsoredSearchResult {
+ not_null peer;
+ QByteArray randomId;
+ TextWithEntities sponsorInfo;
+ TextWithEntities additionalInfo;
+};
+
+struct PeerSearchResult {
+ QString query;
+ std::vector> my;
+ std::vector> peers;
+ std::vector sponsored;
+};
+
+class PeerSearch final {
+public:
+ enum class Type {
+ WithSponsored,
+ JustPeers,
+ };
+ PeerSearch(not_null session, Type type);
+ ~PeerSearch();
+
+ enum class RequestType {
+ CacheOnly,
+ CacheOrRemote,
+ };
+ void request(
+ const QString &query,
+ Fn callback,
+ RequestType type = RequestType::CacheOrRemote);
+ void clear();
+
+private:
+ struct CacheEntry {
+ PeerSearchResult result;
+ bool requested = false;
+ bool peersReady = false;
+ bool sponsoredReady = false;
+ };
+
+ void requestPeers();
+ void requestSponsored();
+
+ void finish(PeerSearchResult result);
+ void finishPeers(mtpRequestId requestId, PeerSearchResult result);
+ void finishSponsored(mtpRequestId requestId, PeerSearchResult result);
+
+ const not_null _session;
+ const Type _type;
+
+ QString _query;
+ Fn _callback;
+
+ base::flat_map _cache;
+ base::flat_map _peerRequests;
+ base::flat_map _sponsoredRequests;
+
+};
+
+} // namespace Api
diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp
index d7dbcd37f1..be3ead5afc 100644
--- a/Telegram/SourceFiles/api/api_premium.cpp
+++ b/Telegram/SourceFiles/api/api_premium.cpp
@@ -816,6 +816,7 @@ std::optional FromTL(
.lastSaleDate = data.vlast_sale_date().value_or_empty(),
.upgradable = data.vupgrade_stars().has_value(),
.birthday = data.is_birthday(),
+ .soldOut = data.is_sold_out(),
});
}, [&](const MTPDstarGiftUnique &data) {
const auto total = data.vavailability_total().v;
@@ -882,6 +883,7 @@ std::optional FromTL(
unique->exportAt = data.vcan_export_at().value_or_empty();
}
using Id = Data::SavedStarGiftId;
+ const auto hasUnique = parsed->unique != nullptr;
return Data::SavedStarGift{
.info = std::move(*parsed),
.manageId = (to->isUser()
@@ -904,7 +906,7 @@ std::optional FromTL(
.date = data.vdate().v,
.upgradable = data.is_can_upgrade(),
.anonymous = data.is_name_hidden(),
- .pinned = data.is_pinned_to_top(),
+ .pinned = data.is_pinned_to_top() && hasUnique,
.hidden = data.is_unsaved(),
.mine = to->isSelf(),
};
diff --git a/Telegram/SourceFiles/boxes/choose_filter_box.cpp b/Telegram/SourceFiles/boxes/choose_filter_box.cpp
index 93164126bd..6630c0428b 100644
--- a/Telegram/SourceFiles/boxes/choose_filter_box.cpp
+++ b/Telegram/SourceFiles/boxes/choose_filter_box.cpp
@@ -295,6 +295,7 @@ void FillChooseFilterMenu(
contains ? &st::mediaPlayerMenuCheck : nullptr);
item->setMarkedText(title.text, QString(), Core::TextContext({
.session = &history->session(),
+ .repaint = [raw = item.get()] { raw->update(); },
.customEmojiLoopLimit = title.isStatic ? -1 : 0,
}));
diff --git a/Telegram/SourceFiles/boxes/delete_messages_box.cpp b/Telegram/SourceFiles/boxes/delete_messages_box.cpp
index 247cad699a..d880ab5860 100644
--- a/Telegram/SourceFiles/boxes/delete_messages_box.cpp
+++ b/Telegram/SourceFiles/boxes/delete_messages_box.cpp
@@ -271,7 +271,8 @@ void DeleteMessagesBox::prepare() {
appendDetails({
tr::lng_delete_for_me_chat_hint(tr::now, lt_count, count)
});
- } else if (!peer->isSelf()) {
+ } else if (!peer->isSelf()
+ && (!peer->isUser() || !peer->asUser()->isInaccessible())) {
if (const auto user = peer->asUser(); user && user->isBot()) {
_revokeForBot = true;
}
diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp
index 5c74632618..c3c92325a0 100644
--- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp
+++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp
@@ -1054,7 +1054,7 @@ void EditMessagesPrivacyBox(
tr::now,
lt_count,
always)
- : QString();
+ : tr::lng_edit_privacy_exceptions_add(tr::now);
});
const auto exceptions = Settings::AddButtonWithLabel(
diff --git a/Telegram/SourceFiles/boxes/peers/add_bot_to_chat_box.cpp b/Telegram/SourceFiles/boxes/peers/add_bot_to_chat_box.cpp
index 14e00151b4..e3cf2a2dd5 100644
--- a/Telegram/SourceFiles/boxes/peers/add_bot_to_chat_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/add_bot_to_chat_box.cpp
@@ -111,6 +111,9 @@ void AddBotToGroupBoxController::Start(
Scope scope,
const QString &token,
ChatAdminRights requestedRights) {
+ if (controller->showFrozenError()) {
+ return;
+ }
auto initBox = [=](not_null box) {
box->addButton(tr::lng_cancel(), [box] { box->closeBox(); });
};
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
index c630f603be..31f22a4f24 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/admin_log/history_admin_log_filter.h"
#include "core/ui_integration.h"
#include "data/stickers/data_custom_emoji.h"
+#include "data/business/data_business_chatbots.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_session.h"
@@ -63,6 +64,11 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
return std::vector>{};
}
+[[nodiscard]] auto Dependencies(Data::ChatbotsPermissions) {
+ using Flag = Data::ChatbotsPermission;
+ return std::vector>{};
+}
+
[[nodiscard]] auto NestedRestrictionLabelsList(
Data::RestrictionsSetOptions options)
-> std::vector> {
@@ -680,7 +686,7 @@ template
checkView->setChecked(false, anim::type::instant);
} else if (locked.has_value()) {
if (checked != toggled) {
- if (!state->toast) {
+ if (!state->toast && !locked->isEmpty()) {
state->toast = Ui::Toast::Show(container, {
.text = { *locked },
.duration = kForceDisableTooltipDuration,
@@ -1490,3 +1496,20 @@ EditFlagsControl CreateEditAdminLogFilter(
return result;
}
+
+EditFlagsControl CreateEditChatbotPermissions(
+ QWidget *parent,
+ Data::ChatbotsPermissions flags) {
+ auto widget = object_ptr(parent);
+ auto descriptor = Data::ChatbotsPermissionsLabels();
+ descriptor.disabledMessages.emplace(
+ Data::ChatbotsPermission::ViewMessages,
+ QString());
+ auto result = CreateEditFlags(
+ widget.data(),
+ flags | Data::ChatbotsPermission::ViewMessages,
+ std::move(descriptor));
+ result.widget = std::move(widget);
+
+ return result;
+}
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h
index 6c4863b7bf..018b5523dc 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h
@@ -27,6 +27,11 @@ enum Flag : uint32;
using Flags = base::flags;
} // namespace PowerSaving
+namespace Data {
+enum class ChatbotsPermission;
+using ChatbotsPermissions = base::flags;
+} // namespace Data
+
template
class object_ptr;
@@ -120,3 +125,8 @@ using AdminRightLabel = EditFlagsLabel;
AdminLog::FilterValue::Flags flags,
bool isChannel
) -> EditFlagsControl;
+
+[[nodiscard]] auto CreateEditChatbotPermissions(
+ QWidget *parent,
+ Data::ChatbotsPermissions flags
+) -> EditFlagsControl;
diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp
index bc15e90593..f02ea735c8 100644
--- a/Telegram/SourceFiles/boxes/star_gift_box.cpp
+++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "api/api_credits.h"
+#include "api/api_global_privacy.h"
#include "api/api_premium.h"
#include "base/event_filter.h"
#include "base/random.h"
@@ -20,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_controllers.h"
#include "boxes/premium_preview_box.h"
#include "boxes/send_credits_box.h"
+#include "boxes/transfer_gift_box.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "chat_helpers/message_field.h"
#include "chat_helpers/stickers_gift_box_pack.h"
@@ -101,8 +103,10 @@ namespace Ui {
namespace {
constexpr auto kPriceTabAll = 0;
-constexpr auto kPriceTabLimited = -2;
constexpr auto kPriceTabInStock = -1;
+constexpr auto kPriceTabLimited = -2;
+constexpr auto kPriceTabMy = -3;
+constexpr auto kMyGiftsPerPage = 50;
constexpr auto kGiftMessageLimit = 255;
constexpr auto kSentToastDuration = 3 * crl::time(1000);
constexpr auto kSwitchUpgradeCoverInterval = 3 * crl::time(1000);
@@ -118,6 +122,11 @@ struct PremiumGiftsDescriptor {
std::shared_ptr api;
};
+struct MyGiftsDescriptor {
+ std::vector list;
+ QString offset;
+};
+
struct GiftsDescriptor {
std::vector list;
std::shared_ptr api;
@@ -360,6 +369,30 @@ auto GenerateGiftMedia(
return Images::Round(std::move(result), mask, RectPart::FullTop);
}
+struct VisibleRange {
+ int top = 0;
+ int bottom = 0;
+
+ friend inline bool operator==(VisibleRange, VisibleRange) = default;
+};
+class WidgetWithRange final : public RpWidget {
+public:
+ using RpWidget::RpWidget;
+
+ [[nodiscard]] rpl::producer visibleRange() const {
+ return _visibleRange.value();
+ }
+private:
+ void visibleTopBottomUpdated(
+ int visibleTop,
+ int visibleBottom) override {
+ _visibleRange = VisibleRange{ visibleTop, visibleBottom };
+ }
+
+ rpl::variable _visibleRange;
+
+};
+
void PrepareImage(
QImage &image,
not_null emoji,
@@ -673,7 +706,7 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
}
ranges::sort(list, ranges::less(), &GiftTypePremium::months);
auto &map = Map[session];
- if (map.last.list != list) {
+ if (map.last.list != list || list.empty()) {
map.last = PremiumGiftsDescriptor{
std::move(list),
api,
@@ -686,6 +719,24 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
};
}
+[[nodiscard]] bool AllowedToSend(
+ const GiftTypeStars &gift,
+ not_null peer) {
+ using Type = Api::DisallowedGiftType;
+ const auto user = peer->asUser();
+ if (!user || user->isSelf()) {
+ return true;
+ }
+ const auto disallowedTypes = user ? user->disallowedGiftTypes() : Type();
+ const auto allowLimited = !(disallowedTypes & Type::Limited);
+ const auto allowUnlimited = !(disallowedTypes & Type::Unlimited);
+ const auto allowUnique = !(disallowedTypes & Type::Unique);
+ if (!gift.info.limitedCount) {
+ return allowUnlimited;
+ }
+ return allowLimited || (gift.info.starsToUpgrade && allowUnique);
+}
+
[[nodiscard]] rpl::producer> GiftsStars(
not_null session,
not_null peer) {
@@ -694,6 +745,12 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
};
static auto Map = base::flat_map, Session>();
+ const auto filtered = [=](std::vector list) {
+ list.erase(ranges::remove_if(list, [&](const GiftTypeStars &gift) {
+ return !AllowedToSend(gift, peer);
+ }), end(list));
+ return list;
+ };
return [=](auto consumer) {
auto lifetime = rpl::lifetime();
@@ -703,7 +760,7 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
session->lifetime().add([=] { Map.remove(session); });
}
if (!i->second.last.empty()) {
- consumer.put_next_copy(i->second.last);
+ consumer.put_next(filtered(i->second.last));
}
using namespace Api;
@@ -718,25 +775,14 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
for (auto &gift : gifts) {
list.push_back({ .info = gift });
}
- ranges::sort(list, [](
- const GiftTypeStars &a,
- const GiftTypeStars &b) {
- if (!a.info.limitedCount && !b.info.limitedCount) {
- return a.info.stars <= b.info.stars;
- } else if (!a.info.limitedCount) {
- return true;
- } else if (!b.info.limitedCount) {
- return false;
- } else if (a.info.limitedLeft != b.info.limitedLeft) {
- return a.info.limitedLeft > b.info.limitedLeft;
- }
- return a.info.stars <= b.info.stars;
+ ranges::stable_sort(list, [](const auto &a, const auto &b) {
+ return a.info.soldOut < b.info.soldOut;
});
auto &map = Map[session];
- if (map.last != list) {
+ if (map.last != list || list.empty()) {
map.last = list;
- consumer.put_next_copy(list);
+ consumer.put_next(filtered(std::move(list)));
}
}, lifetime);
@@ -744,6 +790,48 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
};
}
+[[nodiscard]] rpl::producer UniqueGiftsSlice(
+ not_null session,
+ QString offset = QString()) {
+ return [=](auto consumer) {
+ using Flag = MTPpayments_GetSavedStarGifts::Flag;
+ const auto user = session->user();
+ const auto requestId = session->api().request(
+ MTPpayments_GetSavedStarGifts(
+ MTP_flags(Flag::f_exclude_limited | Flag::f_exclude_unlimited),
+ user->input,
+ MTP_string(offset),
+ MTP_int(kMyGiftsPerPage)
+ )).done([=](const MTPpayments_SavedStarGifts &result) {
+ auto gifts = MyGiftsDescriptor();
+ const auto &data = result.data();
+ if (const auto next = data.vnext_offset()) {
+ gifts.offset = qs(*next);
+ }
+
+ const auto owner = &session->data();
+ owner->processUsers(data.vusers());
+ owner->processChats(data.vchats());
+
+ gifts.list.reserve(data.vgifts().v.size());
+ for (const auto &gift : data.vgifts().v) {
+ if (auto parsed = Api::FromTL(user, gift)) {
+ gifts.list.push_back(std::move(*parsed));
+ }
+ }
+ consumer.put_next(std::move(gifts));
+ consumer.put_done();
+ }).fail([=] {
+ consumer.put_next({});
+ consumer.put_done();
+ }).send();
+
+ auto lifetime = rpl::lifetime();
+ lifetime.add([=] { session->api().request(requestId).cancel(); });
+ return lifetime;
+ };
+}
+
[[nodiscard]] Text::String TabTextForPrice(
not_null session,
int price) {
@@ -752,6 +840,8 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
};
if (price == kPriceTabAll) {
return simple(tr::lng_gift_stars_tabs_all(tr::now));
+ } else if (price == kPriceTabMy) {
+ return simple(tr::lng_gift_stars_tabs_my(tr::now));
} else if (price == kPriceTabLimited) {
return simple(tr::lng_gift_stars_tabs_limited(tr::now));
} else if (price == kPriceTabInStock) {
@@ -774,7 +864,8 @@ struct GiftPriceTabs {
[[nodiscard]] GiftPriceTabs MakeGiftsPriceTabs(
not_null window,
not_null peer,
- rpl::producer> gifts) {
+ rpl::producer> gifts,
+ bool hasMyUnique) {
auto widget = object_ptr((QWidget*)nullptr);
const auto raw = widget.data();
@@ -798,6 +889,13 @@ struct GiftPriceTabs {
int pressed = -1;
int active = -1;
};
+ const auto user = peer->asUser();
+ const auto disallowed = user
+ ? user->disallowedGiftTypes()
+ : Api::DisallowedGiftType();
+ if (disallowed & Api::DisallowedGiftType::Unique) {
+ hasMyUnique = false;
+ }
const auto state = raw->lifetime().make_state();
const auto scroll = [=] {
return QPoint(int(base::SafeRound(state->scroll)), 0);
@@ -805,25 +903,14 @@ struct GiftPriceTabs {
state->prices = std::move(
gifts
- ) | rpl::map([](const std::vector &gifts) {
+ ) | rpl::map([=](const std::vector &gifts) {
auto result = std::vector();
result.push_back(kPriceTabAll);
- auto special = 1;
- auto same = true;
- auto sameKey = 0;
auto hasNonSoldOut = false;
auto hasSoldOut = false;
auto hasLimited = false;
+ auto hasNonLimited = false;
for (const auto &gift : gifts) {
- if (same) {
- const auto key = gift.info.stars
- * (gift.info.limitedCount ? -1 : 1);
- if (!sameKey) {
- sameKey = key;
- } else if (sameKey != key) {
- same = false;
- }
- }
if (IsSoldOut(gift.info)) {
hasSoldOut = true;
} else {
@@ -831,19 +918,21 @@ struct GiftPriceTabs {
}
if (gift.info.limitedCount) {
hasLimited = true;
+ } else {
+ hasNonLimited = true;
}
if (!ranges::contains(result, gift.info.stars)) {
result.push_back(gift.info.stars);
}
}
- if (same) {
- return std::vector();
+ if (hasMyUnique && !gifts.empty()) {
+ result.push_back(kPriceTabMy);
}
if (hasSoldOut && hasNonSoldOut) {
- result.insert(begin(result) + (special++), kPriceTabInStock);
+ result.push_back(kPriceTabInStock);
}
- if (hasLimited) {
- result.insert(begin(result) + (special++), kPriceTabLimited);
+ if (hasLimited && hasNonLimited) {
+ result.push_back(kPriceTabLimited);
}
ranges::sort(begin(result) + 1, end(result));
return result;
@@ -1446,6 +1535,13 @@ void SendGiftBox(
const auto limited = stars
&& (stars->info.limitedCount > stars->info.limitedLeft)
&& (stars->info.limitedLeft > 0);
+ const auto costToUpgrade = stars ? stars->info.starsToUpgrade : 0;
+ const auto user = peer->asUser();
+ const auto disallowed = user
+ ? user->disallowedGiftTypes()
+ : Api::DisallowedGiftTypes();
+ const auto disallowLimited = !peer->isSelf()
+ && (disallowed & Api::DisallowedGiftType::Limited);
box->setStyle(limited ? st::giftLimitedBox : st::giftBox);
box->setWidth(st::boxWideWidth);
box->setTitle(tr::lng_gift_send_title());
@@ -1465,6 +1561,7 @@ void SendGiftBox(
state->details = GiftDetails{
.descriptor = descriptor,
.randomId = base::RandomValue(),
+ .upgraded = disallowLimited && (costToUpgrade > 0),
};
peer->updateFull();
state->messageAllowed = peer->session().changes().peerFlagsValue(
@@ -1563,13 +1660,13 @@ void SendGiftBox(
session,
{ .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow });
if (stars) {
- const auto cost = stars->info.starsToUpgrade;
- if (cost > 0 && !peer->isSelf()) {
+ if (costToUpgrade > 0 && !peer->isSelf() && !disallowLimited) {
const auto id = stars->info.id;
const auto showing = std::make_shared();
AddDivider(container);
AddSkip(container);
- AddUpgradeButton(container, session, cost, peer, [=](bool on) {
+ AddUpgradeButton(container, session, costToUpgrade, peer, [=](
+ bool on) {
auto now = state->details.current();
now.upgraded = on;
state->details = std::move(now);
@@ -1583,7 +1680,7 @@ void SendGiftBox(
.stargiftId = id,
.ready = [=](bool) { *showing = false; },
.peer = peer,
- .cost = int(cost),
+ .cost = int(costToUpgrade),
});
});
} else {
@@ -1726,17 +1823,24 @@ void SendGiftBox(
[[nodiscard]] object_ptr MakeGiftsList(
not_null window,
not_null peer,
- rpl::producer gifts) {
- auto result = object_ptr((QWidget*)nullptr);
+ rpl::producer gifts,
+ Fn loadMore) {
+ auto result = object_ptr((QWidget*)nullptr);
const auto raw = result.data();
struct State {
Delegate delegate;
+ std::vector order;
+ std::vector validated;
+ std::vector list;
std::vector> buttons;
+ std::shared_ptr api;
+ rpl::variable visibleRange;
bool sending = false;
+ int perRow = 1;
};
const auto state = raw->lifetime().make_state(State{
- .delegate = Delegate(window, GiftButtonMode::Full),
+ .delegate = Delegate(&window->session(), GiftButtonMode::Full),
});
const auto single = state->delegate.buttonSize();
const auto shadow = st::defaultDropdownMenu.wrap.shadow;
@@ -1745,74 +1849,165 @@ void SendGiftBox(
auto &packs = window->session().giftBoxStickersPacks();
packs.updated() | rpl::start_with_next([=] {
for (const auto &button : state->buttons) {
- button->update();
+ if (const auto raw = button.get()) {
+ raw->update();
+ }
}
}, raw->lifetime());
+ const auto rebuild = [=] {
+ const auto width = st::boxWideWidth;
+ const auto padding = st::giftBoxPadding;
+ const auto available = width - padding.left() - padding.right();
+ const auto range = state->visibleRange.current();
+ const auto count = int(state->list.size());
+
+ auto &buttons = state->buttons;
+ if (buttons.size() < count) {
+ buttons.resize(count);
+ }
+ auto &validated = state->validated;
+ validated.resize(count);
+
+ auto x = padding.left();
+ auto y = padding.top();
+ const auto perRow = state->perRow;
+ const auto singlew = single.width() + st::giftBoxGiftSkip.x();
+ const auto singleh = single.height() + st::giftBoxGiftSkip.y();
+ const auto rowFrom = std::max(range.top - y, 0) / singleh;
+ const auto rowTill = (std::max(range.bottom - y + st::giftBoxGiftSkip.y(), 0) + singleh - 1)
+ / singleh;
+ Assert(rowTill >= rowFrom);
+ const auto first = rowFrom * perRow;
+ const auto last = std::min(rowTill * perRow, count);
+ auto checkedFrom = 0;
+ auto checkedTill = int(buttons.size());
+ const auto ensureButton = [&](int index) {
+ auto &button = buttons[index];
+ if (!button) {
+ validated[index] = false;
+ for (; checkedFrom != first; ++checkedFrom) {
+ if (buttons[checkedFrom]) {
+ button = std::move(buttons[checkedFrom]);
+ break;
+ }
+ }
+ }
+ if (!button) {
+ for (; checkedTill != last; ) {
+ --checkedTill;
+ if (buttons[checkedTill]) {
+ button = std::move(buttons[checkedTill]);
+ break;
+ }
+ }
+ }
+ if (!button) {
+ button = std::make_unique(
+ raw,
+ &state->delegate);
+ }
+ if (validated[index]) {
+ return;
+ }
+ button->show();
+ validated[index] = true;
+ const auto &descriptor = state->list[state->order[index]];
+ button->setDescriptor(descriptor, GiftButton::Mode::Full);
+ button->setClickedCallback([=] {
+ const auto star = std::get_if(&descriptor);
+ if (star && star->info.unique) {
+ const auto done = [=] {
+ window->session().credits().load(true);
+ window->showPeerHistory(peer);
+ };
+ ShowTransferToBox(
+ window,
+ peer,
+ star->info.unique,
+ star->transferId,
+ done);
+ } else if (star && IsSoldOut(star->info)) {
+ window->show(Box(SoldOutBox, window, *star));
+ } else {
+ window->show(Box(
+ SendGiftBox,
+ window,
+ peer,
+ state->api,
+ descriptor));
+ }
+ });
+ button->setGeometry(QRect(QPoint(x, y), single), extend);
+ };
+ y += rowFrom * singleh;
+ for (auto row = rowFrom; row != rowTill; ++row) {
+ for (auto col = 0; col != perRow; ++col) {
+ const auto index = row * perRow + col;
+ if (index >= count) {
+ break;
+ }
+ const auto last = !((col + 1) % perRow);
+ if (last) {
+ x = padding.left() + available - single.width();
+ }
+ ensureButton(index);
+ if (last) {
+ x = padding.left();
+ y += singleh;
+ } else {
+ x += singlew;
+ }
+ }
+ }
+ const auto till = std::min(int(buttons.size()), rowTill * perRow);
+ for (auto i = count; i < till; ++i) {
+ if (const auto button = buttons[i].get()) {
+ button->hide();
+ }
+ }
+
+ const auto page = range.bottom - range.top;
+ if (loadMore && page > 0 && range.bottom + page > raw->height()) {
+ loadMore();
+ }
+ };
+
+ state->visibleRange = raw->visibleRange();
+ state->visibleRange.value(
+ ) | rpl::start_with_next(rebuild, raw->lifetime());
+
std::move(
gifts
) | rpl::start_with_next([=](const GiftsDescriptor &gifts) {
const auto width = st::boxWideWidth;
const auto padding = st::giftBoxPadding;
const auto available = width - padding.left() - padding.right();
- const auto perRow = available / single.width();
- const auto count = int(gifts.list.size());
+ state->perRow = available / single.width();
+ state->list = std::move(gifts.list);
+ state->api = gifts.api;
- auto order = ranges::views::ints
+ const auto count = int(state->list.size());
+ state->order = ranges::views::ints
| ranges::views::take(count)
| ranges::to_vector;
+ state->validated.clear();
if (SortForBirthday(peer)) {
- ranges::stable_partition(order, [&](int i) {
- const auto &gift = gifts.list[i];
+ ranges::stable_partition(state->order, [&](int i) {
+ const auto &gift = state->list[i];
const auto stars = std::get_if(&gift);
- return stars && stars->info.birthday;
+ return stars && stars->info.birthday && !stars->info.unique;
});
}
- auto x = padding.left();
- auto y = padding.top();
- state->buttons.resize(count);
- for (auto &button : state->buttons) {
- if (!button) {
- button = std::make_unique(raw, &state->delegate);
- button->show();
- }
- }
- const auto api = gifts.api;
- for (auto i = 0; i != count; ++i) {
- const auto button = state->buttons[i].get();
- const auto &descriptor = gifts.list[order[i]];
- button->setDescriptor(descriptor, GiftButton::Mode::Full);
-
- const auto last = !((i + 1) % perRow);
- if (last) {
- x = padding.left() + available - single.width();
- }
- button->setGeometry(QRect(QPoint(x, y), single), extend);
- if (last) {
- x = padding.left();
- y += single.height() + st::giftBoxGiftSkip.y();
- } else {
- x += single.width() + st::giftBoxGiftSkip.x();
- }
-
- button->setClickedCallback([=] {
- const auto star = std::get_if(&descriptor);
- if (star && IsSoldOut(star->info)) {
- window->show(Box(SoldOutBox, window, *star));
- } else {
- window->show(
- Box(SendGiftBox, window, peer, api, descriptor));
- }
- });
- }
- if (count % perRow) {
- y += padding.bottom() + single.height();
- } else {
- y += padding.bottom() - st::giftBoxGiftSkip.y();
- }
- raw->resize(raw->width(), count ? y : 0);
+ const auto rows = (count + state->perRow - 1) / state->perRow;
+ const auto height = padding.top()
+ + (rows * single.height())
+ + ((rows - 1) * st::giftBoxGiftSkip.y())
+ + padding.bottom();
+ raw->resize(raw->width(), height);
+ rebuild();
}, raw->lifetime());
return result;
@@ -1876,42 +2071,83 @@ void AddBlock(
gifts.list | ranges::to>,
gifts.api,
};
- }));
+ }), nullptr);
result->lifetime().add([state = std::move(state)] {});
return result;
}
[[nodiscard]] object_ptr MakeStarsGifts(
not_null window,
- not_null peer) {
+ not_null peer,
+ MyGiftsDescriptor my) {
auto result = object_ptr((QWidget*)nullptr);
struct State {
rpl::variable> gifts;
rpl::variable priceTab = kPriceTabAll;
+ rpl::event_stream<> myUpdated;
+ MyGiftsDescriptor my;
+ rpl::lifetime myLoading;
};
const auto state = result->lifetime().make_state();
+ state->my = std::move(my);
state->gifts = GiftsStars(&window->session(), peer);
- auto tabs = MakeGiftsPriceTabs(window, peer, state->gifts.value());
+ auto tabs = MakeGiftsPriceTabs(
+ window,
+ peer,
+ state->gifts.value(),
+ !state->my.list.empty());
state->priceTab = std::move(tabs.priceTab);
result->add(std::move(tabs.widget));
result->add(MakeGiftsList(window, peer, rpl::combine(
state->gifts.value(),
- state->priceTab.value()
- ) | rpl::map([=](std::vector &&gifts, int price) {
- gifts.erase(ranges::remove_if(gifts, [&](const GiftTypeStars &gift) {
- return (price == kPriceTabLimited)
- ? (!gift.info.limitedCount)
- : (price == kPriceTabInStock)
- ? IsSoldOut(gift.info)
- : (price && gift.info.stars != price);
- }), end(gifts));
+ state->priceTab.value(),
+ rpl::single(rpl::empty) | rpl::then(state->myUpdated.events())
+ ) | rpl::map([=](std::vector &&gifts, int price, auto) {
+ if (price == kPriceTabMy) {
+ gifts.clear();
+ for (const auto &gift : state->my.list) {
+ gifts.push_back({
+ .transferId = gift.manageId,
+ .info = gift.info,
+ .mine = true,
+ });
+ }
+ } else {
+ const auto pred = [&](const GiftTypeStars &gift) {
+ return (price == kPriceTabLimited)
+ ? (!gift.info.limitedCount)
+ : (price == kPriceTabInStock)
+ ? IsSoldOut(gift.info)
+ : (price && gift.info.stars != price);
+ };
+ gifts.erase(ranges::remove_if(gifts, pred), end(gifts));
+ }
return GiftsDescriptor{
gifts | ranges::to>(),
};
- })));
+ }), [=] {
+ if (state->priceTab.current() == kPriceTabMy
+ && !state->my.offset.isEmpty()
+ && !state->myLoading) {
+ state->myLoading = UniqueGiftsSlice(
+ &peer->session(),
+ state->my.offset
+ ) | rpl::start_with_next([=](MyGiftsDescriptor &&descriptor) {
+ state->myLoading.destroy();
+ state->my.offset = descriptor.list.empty()
+ ? QString()
+ : descriptor.offset;
+ state->my.list.insert(
+ end(state->my.list),
+ std::make_move_iterator(begin(descriptor.list)),
+ std::make_move_iterator(end(descriptor.list)));
+ state->myUpdated.fire({});
+ });
+ }
+ }));
return result;
}
@@ -1919,7 +2155,8 @@ void AddBlock(
void GiftBox(
not_null box,
not_null window,
- not_null peer) {
+ not_null peer,
+ MyGiftsDescriptor my) {
box->setWidth(st::boxWideWidth);
box->setStyle(st::creditsGiftBox);
box->setNoContentMargin(true);
@@ -1935,6 +2172,24 @@ void GiftBox(
AddSkip(content, st::defaultVerticalListSkip * 5);
+ // Check disallowed gift types
+ const auto user = peer->asUser();
+ using Type = Api::DisallowedGiftType;
+ const auto disallowedTypes = user
+ ? user->disallowedGiftTypes()
+ : Type::Premium;
+ const auto premiumDisallowed = peer->isSelf()
+ || (disallowedTypes & Type::Premium);
+ const auto limitedDisallowed = !peer->isSelf()
+ && (disallowedTypes & Type::Limited);
+ const auto unlimitedDisallowed = !peer->isSelf()
+ && (disallowedTypes & Type::Unlimited);
+ const auto uniqueDisallowed = !peer->isSelf()
+ && (disallowedTypes & Type::Unique);
+ const auto allStarsDisallowed = limitedDisallowed
+ && unlimitedDisallowed
+ && uniqueDisallowed;
+
content->add(
object_ptr>(
content,
@@ -1956,11 +2211,12 @@ void GiftBox(
window->showSettings(Settings::CreditsId());
return false;
};
- if (peer->isUser() && !peer->isSelf()) {
+ if (peer->isUser() && !peer->isSelf() && !premiumDisallowed) {
const auto premiumClickHandlerFilter = [=](const auto &...) {
Settings::ShowPremium(window, u"gift_send"_q);
return false;
};
+
AddBlock(content, window, {
.subtitle = tr::lng_gift_premium_subtitle(),
.about = tr::lng_gift_premium_about(
@@ -1973,28 +2229,32 @@ void GiftBox(
.content = MakePremiumGifts(window, peer),
});
}
- AddBlock(content, window, {
- .subtitle = (peer->isSelf()
- ? tr::lng_gift_self_title()
- : peer->isBroadcast()
- ? tr::lng_gift_channel_title()
- : tr::lng_gift_stars_subtitle()),
- .about = (peer->isSelf()
- ? tr::lng_gift_self_about(Text::WithEntities)
- : peer->isBroadcast()
- ? tr::lng_gift_channel_about(
- lt_name,
- rpl::single(Text::Bold(peer->name())),
- Text::WithEntities)
- : tr::lng_gift_stars_about(
- lt_name,
- rpl::single(Text::Bold(peer->shortName())),
- lt_link,
- tr::lng_gift_stars_link() | Text::ToLink(),
- Text::WithEntities)),
- .aboutFilter = starsClickHandlerFilter,
- .content = MakeStarsGifts(window, peer),
- });
+
+ // Only add star gifts if at least one type is allowed
+ if (!allStarsDisallowed) {
+ AddBlock(content, window, {
+ .subtitle = (peer->isSelf()
+ ? tr::lng_gift_self_title()
+ : peer->isBroadcast()
+ ? tr::lng_gift_channel_title()
+ : tr::lng_gift_stars_subtitle()),
+ .about = (peer->isSelf()
+ ? tr::lng_gift_self_about(Text::WithEntities)
+ : peer->isBroadcast()
+ ? tr::lng_gift_channel_about(
+ lt_name,
+ rpl::single(Text::Bold(peer->name())),
+ Text::WithEntities)
+ : tr::lng_gift_stars_about(
+ lt_name,
+ rpl::single(Text::Bold(peer->shortName())),
+ lt_link,
+ tr::lng_gift_stars_link() | Text::ToLink(),
+ Text::WithEntities)),
+ .aboutFilter = starsClickHandlerFilter,
+ .content = MakeStarsGifts(window, peer, std::move(my)),
+ });
+ }
}
struct SelfOption {
@@ -2184,11 +2444,31 @@ void ChooseStarGiftRecipient(
void ShowStarGiftBox(
not_null controller,
not_null peer) {
+ if (controller->showFrozenError()) {
+ return;
+ }
+
struct Session {
PeerData *peer = nullptr;
+ MyGiftsDescriptor my;
bool premiumGiftsReady = false;
bool starsGiftsReady = false;
+ bool fullReady = false;
+ bool myReady = false;
+
+ bool hasPremium = false;
+ bool hasUpgradable = false;
+ bool hasLimited = false;
+ bool hasUnlimited = false;
+
rpl::lifetime lifetime;
+
+ [[nodiscard]] bool ready() const {
+ return premiumGiftsReady
+ && starsGiftsReady
+ && fullReady
+ && myReady;
+ }
};
static auto Map = base::flat_map, Session>();
@@ -2203,46 +2483,91 @@ void ShowStarGiftBox(
i->second = Session{ .peer = peer };
const auto weak = base::make_weak(controller);
- const auto show = [=] {
- Map[session] = Session();
+ const auto checkReady = [=] {
+ auto &entry = Map[session];
+ if (!entry.ready()) {
+ return;
+ }
+ auto was = std::move(entry);
+ entry = Session();
if (const auto strong = weak.get()) {
- strong->show(Box(GiftBox, strong, peer));
+ if (const auto user = peer->asUser()) {
+ using Type = Api::DisallowedGiftType;
+ const auto disallowedTypes = user->disallowedGiftTypes();
+ const auto premium = (disallowedTypes & Type::Premium)
+ || peer->isSelf();
+ const auto limited = (disallowedTypes & Type::Limited);
+ const auto unlimited = (disallowedTypes & Type::Unlimited);
+ const auto unique = (disallowedTypes & Type::Unique);
+ if ((unique || (!was.hasUpgradable && was.my.list.empty()))
+ && (premium || !was.hasPremium)
+ && (limited || !was.hasLimited)
+ && (unlimited || !was.hasUnlimited)) {
+ strong->showToast(
+ tr::lng_edit_privacy_gifts_restricted(tr::now));
+ return;
+ }
+ }
+ strong->show(Box(GiftBox, strong, peer, std::move(was.my)));
}
};
- base::timer_once(
- kGiftsPreloadTimeout
- ) | rpl::start_with_next(show, i->second.lifetime);
-
const auto user = peer->asUser();
if (user && !user->isSelf()) {
GiftsPremium(
session,
peer
) | rpl::start_with_next([=](PremiumGiftsDescriptor &&gifts) {
- if (!gifts.list.empty()) {
- auto &entry = Map[session];
- entry.premiumGiftsReady = true;
- if (entry.starsGiftsReady) {
- show();
- }
- }
+ auto &entry = Map[session];
+ entry.premiumGiftsReady = true;
+ entry.hasPremium = !gifts.list.empty();
+ checkReady();
}, i->second.lifetime);
} else {
+ i->second.hasPremium = false;
i->second.premiumGiftsReady = true;
}
+ if (peer->isFullLoaded()) {
+ i->second.fullReady = true;
+ } else {
+ peer->updateFull();
+ peer->session().changes().peerUpdates(
+ peer,
+ Data::PeerUpdate::Flag::FullInfo
+ ) | rpl::take(1) | rpl::start_with_next([=] {
+ auto &entry = Map[session];
+ entry.fullReady = true;
+ checkReady();
+ }, i->second.lifetime);
+ }
+
GiftsStars(
session,
peer
) | rpl::start_with_next([=](std::vector &&gifts) {
- if (!gifts.empty()) {
- auto &entry = Map[session];
- entry.starsGiftsReady = true;
- if (entry.premiumGiftsReady) {
- show();
+ auto &entry = Map[session];
+ entry.starsGiftsReady = true;
+ for (const auto &gift : gifts) {
+ if (gift.info.limitedCount) {
+ entry.hasLimited = true;
+ if (gift.info.starsToUpgrade) {
+ entry.hasUpgradable = true;
+ }
+ } else {
+ entry.hasUnlimited = true;
}
}
+ checkReady();
+ }, i->second.lifetime);
+
+ UniqueGiftsSlice(
+ session
+ ) | rpl::start_with_next([=](MyGiftsDescriptor &&gifts) {
+ auto &entry = Map[session];
+ entry.my = std::move(gifts);
+ entry.myReady = true;
+ checkReady();
}, i->second.lifetime);
}
diff --git a/Telegram/SourceFiles/boxes/transfer_gift_box.cpp b/Telegram/SourceFiles/boxes/transfer_gift_box.cpp
index 8d297bb27f..f0f52c1855 100644
--- a/Telegram/SourceFiles/boxes/transfer_gift_box.cpp
+++ b/Telegram/SourceFiles/boxes/transfer_gift_box.cpp
@@ -463,6 +463,8 @@ void TransferGift(
std::move(formDone));
}
+} // namespace
+
void ShowTransferToBox(
not_null controller,
not_null peer,
@@ -539,8 +541,6 @@ void ShowTransferToBox(
}));
}
-} // namespace
-
void ShowTransferGiftBox(
not_null window,
std::shared_ptr gift,
diff --git a/Telegram/SourceFiles/boxes/transfer_gift_box.h b/Telegram/SourceFiles/boxes/transfer_gift_box.h
index e058e88c3c..5cb051a892 100644
--- a/Telegram/SourceFiles/boxes/transfer_gift_box.h
+++ b/Telegram/SourceFiles/boxes/transfer_gift_box.h
@@ -16,6 +16,13 @@ struct UniqueGift;
class SavedStarGiftId;
} // namespace Data
+void ShowTransferToBox(
+ not_null controller,
+ not_null peer,
+ std::shared_ptr gift,
+ Data::SavedStarGiftId savedId,
+ Fn closeParentBox);
+
void ShowTransferGiftBox(
not_null window,
std::shared_ptr gift,
diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp
index 673216650d..e5af06c171 100644
--- a/Telegram/SourceFiles/calls/calls_panel.cpp
+++ b/Telegram/SourceFiles/calls/calls_panel.cpp
@@ -715,18 +715,21 @@ void Panel::createRemoteLowBattery() {
}, _remoteLowBattery->lifetime());
constexpr auto kBatterySize = QSize(29, 13);
+ const auto scaledBatterySize = QSize(
+ style::ConvertScale(kBatterySize.width()),
+ style::ConvertScale(kBatterySize.height()));
const auto icon = [&] {
auto svg = QSvgRenderer(
BatterySvg(kBatterySize, st::videoPlayIconFg->c));
auto image = QImage(
- kBatterySize * style::DevicePixelRatio(),
+ scaledBatterySize * style::DevicePixelRatio(),
QImage::Format_ARGB32_Premultiplied);
image.setDevicePixelRatio(style::DevicePixelRatio());
image.fill(Qt::transparent);
{
auto p = QPainter(&image);
- svg.render(&p, Rect(kBatterySize));
+ svg.render(&p, Rect(scaledBatterySize));
}
return image;
}();
@@ -745,7 +748,7 @@ void Panel::createRemoteLowBattery() {
p.drawImage(
st::callTooltipMutedIconPosition.x(),
- (r.height() - kBatterySize.height()) / 2,
+ (r.height() - scaledBatterySize.height()) / 2,
icon);
}, _remoteLowBattery->lifetime());
diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style
index b5f24927da..1660c27585 100644
--- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style
+++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style
@@ -1131,6 +1131,10 @@ historyScheduledToggle: IconButton(historyAttach) {
{ "chat/input_scheduled_dot", attentionButtonFg }
};
}
+historyGiftToUser: IconButton(historyAttach) {
+ icon: icon {{ "chat/input_gift", historyComposeIconFg }};
+ iconOver: icon {{ "chat/input_gift", historyComposeIconFgOver }};
+}
historyAttachEmojiInner: IconButton(historyAttach) {
icon: icon {{ "chat/input_smile_face", historyComposeIconFg }};
@@ -1566,3 +1570,27 @@ processingVideoView: RoundButton(defaultActiveButton) {
textBgOver: transparent;
ripple: emptyRippleAnimation;
}
+
+frozenBarTitle: FlatLabel(defaultFlatLabel) {
+ style: semiboldTextStyle;
+ textFg: attentionButtonFg;
+}
+frozenRestrictionTitle: FlatLabel(frozenBarTitle) {
+ align: align(top);
+}
+frozenBarSubtitle: FlatLabel(defaultFlatLabel) {
+ textFg: windowSubTextFg;
+}
+frozenRestrictionSubtitle: FlatLabel(frozenBarSubtitle) {
+ align: align(top);
+}
+frozenInfoBox: Box(defaultBox) {
+ buttonPadding: margins(16px, 11px, 16px, 16px);
+ buttonHeight: 42px;
+ button: RoundButton(defaultActiveButton) {
+ height: 42px;
+ textTop: 12px;
+ style: semiboldTextStyle;
+ }
+ shadowIgnoreTopSkip: true;
+}
diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp
index de43168a3a..bc7f46d696 100644
--- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp
+++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp
@@ -1265,7 +1265,7 @@ void EmojiListWidget::fillEmojiStatusMenu(
int section,
int index) {
const auto chosen = lookupCustomEmoji(index, section);
- if (!chosen || chosen.collectible) {
+ if (!chosen) {
return;
}
const auto selectWith = [=](TimeId scheduled) {
diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp
index a352674552..61d27c3408 100644
--- a/Telegram/SourceFiles/chat_helpers/message_field.cpp
+++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp
@@ -11,38 +11,48 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h" // History::session
#include "history/history_item.h" // HistoryItem::originalText
#include "history/history_item_helpers.h" // DropDisallowedCustomEmoji
+#include "base/unixtime.h"
#include "base/qthelp_regex.h"
#include "base/qthelp_url.h"
#include "base/event_filter.h"
#include "ui/chat/chat_style.h"
#include "ui/layers/generic_box.h"
+#include "ui/basic_click_handlers.h"
#include "ui/rect.h"
#include "core/shortcuts.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "core/ui_integration.h"
+#include "lottie/lottie_icon.h"
+#include "info/profile/info_profile_icon.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
+#include "ui/widgets/shadow.h"
#include "ui/power_saving.h"
+#include "ui/vertical_list.h"
#include "ui/ui_utility.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/data_document.h"
#include "data/stickers/data_custom_emoji.h"
#include "chat_helpers/emoji_suggestions_widget.h"
+#include "history/view/controls/compose_controls_common.h"
#include "window/window_session_controller.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "main/main_session.h"
+#include "settings/settings_common.h"
#include "settings/settings_premium.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_credits.h"
+#include "styles/style_dialogs.h"
+#include "styles/style_menu_icons.h"
#include "styles/style_settings.h"
#include "base/qt/qt_common_adapters.h"
@@ -1187,10 +1197,10 @@ base::unique_qptr CreateDisabledFieldView(
return result;
}
-base::unique_qptr TextErrorSendRestriction(
+std::unique_ptr TextErrorSendRestriction(
QWidget *parent,
const QString &text) {
- auto result = base::make_unique_q(parent);
+ auto result = std::make_unique(parent);
const auto raw = result.get();
const auto label = CreateChild(
result.get(),
@@ -1215,11 +1225,11 @@ base::unique_qptr TextErrorSendRestriction(
return result;
}
-base::unique_qptr PremiumRequiredSendRestriction(
+std::unique_ptr PremiumRequiredSendRestriction(
QWidget *parent,
not_null user,
not_null controller) {
- auto result = base::make_unique_q(parent);
+ auto result = std::make_unique(parent);
const auto raw = result.get();
const auto label = CreateChild(
result.get(),
@@ -1254,6 +1264,102 @@ base::unique_qptr PremiumRequiredSendRestriction(
return result;
}
+std::unique_ptr BoostsToLiftWriteRestriction(
+ not_null parent,
+ std::shared_ptr show,
+ not_null peer,
+ int boosts) {
+ auto result = std::make_unique(
+ parent,
+ tr::lng_restricted_boost_group(tr::now),
+ st::historyComposeButton);
+ result->setClickedCallback([=] {
+ const auto window = show->resolveWindow();
+ window->resolveBoostState(peer->asChannel(), boosts);
+ });
+ return result;
+}
+
+std::unique_ptr FrozenWriteRestriction(
+ not_null parent,
+ std::shared_ptr show,
+ FrozenWriteRestrictionType type,
+ FreezeInfoStyleOverride st) {
+ using namespace Ui;
+
+ auto result = std::make_unique(
+ parent,
+ QString(),
+ st::historyComposeButton);
+ const auto raw = result.get();
+
+ const auto bar = (type == FrozenWriteRestrictionType::DialogsList);
+ const auto title = CreateChild(
+ raw,
+ (bar ? tr::lng_frozen_bar_title : tr::lng_frozen_restrict_title)(
+ tr::now),
+ bar ? st::frozenBarTitle : st::frozenRestrictionTitle);
+ title->setAttribute(Qt::WA_TransparentForMouseEvents);
+ title->show();
+ const auto subtitle = CreateChild(
+ raw,
+ (bar
+ ? tr::lng_frozen_bar_text(
+ lt_arrow,
+ rpl::single(Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
+ Ui::Text::WithEntities)
+ : tr::lng_frozen_restrict_text(Ui::Text::WithEntities)),
+ bar ? st::frozenBarSubtitle : st::frozenRestrictionSubtitle);
+ subtitle->setAttribute(Qt::WA_TransparentForMouseEvents);
+ subtitle->show();
+
+ const auto shadow = bar ? CreateChild(raw) : nullptr;
+ const auto icon = bar ? CreateChild(raw) : nullptr;
+ if (icon) {
+ icon->paintRequest() | rpl::start_with_next([=] {
+ auto p = QPainter(icon);
+ st::menuIconDisableAttention.paintInCenter(p, icon->rect());
+ }, icon->lifetime());
+ icon->show();
+ }
+
+ raw->sizeValue() | rpl::start_with_next([=](QSize size) {
+ if (bar) {
+ const auto toggle = [&](auto &&widget, bool shown) {
+ if (widget->isHidden() == shown) {
+ widget->setVisible(shown);
+ }
+ };
+ const auto small = 2 * st::defaultDialogRow.photoSize;
+ const auto shown = (size.width() > small);
+ toggle(icon, !shown);
+ toggle(title, shown);
+ toggle(subtitle, shown);
+ icon->setGeometry(0, 0, size.width(), size.height());
+ }
+ const auto skip = bar
+ ? st::defaultDialogRow.padding.left()
+ : 2 * st::normalFont->spacew;
+ const auto available = size.width() - skip * 2;
+ title->resizeToWidth(available);
+ subtitle->resizeToWidth(available);
+ const auto height = title->height() + subtitle->height();
+ const auto top = (size.height() - height) / 2;
+ title->moveToLeft(skip, top, size.width());
+ subtitle->moveToLeft(skip, top + title->height(), size.width());
+
+ const auto line = st::lineWidth;
+ if (shadow) {
+ shadow->setGeometry(0, size.height() - line, size.width(), line);
+ }
+ }, title->lifetime());
+
+ raw->setClickedCallback([=] {
+ show->show(Box(FrozenInfoBox, &show->session(), st));
+ });
+ return result;
+}
+
void SelectTextInFieldWithMargins(
not_null field,
const TextSelection &selection) {
@@ -1301,3 +1407,101 @@ rpl::producer PaidSendButtonText(
return PaidSendButtonText(tr::now, count);
});
}
+
+void FrozenInfoBox(
+ not_null box,
+ not_null session,
+ FreezeInfoStyleOverride st) {
+ box->setWidth(st::boxWideWidth);
+ box->setStyle(st::frozenInfoBox);
+ box->setNoContentMargin(true);
+ box->addTopButton(st::boxTitleClose, [=] {
+ box->closeBox();
+ });
+
+ const auto info = session->frozen();
+ const auto content = box->verticalLayout();
+ auto icon = Settings::CreateLottieIcon(
+ content,
+ {
+ .name = u"media_forbidden"_q,
+ .sizeOverride = {
+ st::changePhoneIconSize,
+ st::changePhoneIconSize,
+ },
+ },
+ st::settingLocalPasscodeIconPadding);
+ content->add(std::move(icon.widget));
+ box->setShowFinishedCallback([animate = std::move(icon.animate)] {
+ animate(anim::repeat::once);
+ });
+
+ Ui::AddSkip(content);
+
+ const auto infoRow = [&](
+ rpl::producer title,
+ rpl::producer text,
+ not_null icon) {
+ auto raw = content->add(
+ object_ptr(content));
+ raw->add(
+ object_ptr(
+ raw,
+ std::move(title) | Ui::Text::ToBold(),
+ st.infoTitle ? *st.infoTitle : st::defaultFlatLabel),
+ st::settingsPremiumRowTitlePadding);
+ raw->add(
+ object_ptr(
+ raw,
+ std::move(text),
+ st.infoAbout ? *st.infoAbout : st::upgradeGiftSubtext),
+ st::settingsPremiumRowAboutPadding);
+ object_ptr(
+ raw,
+ *icon,
+ st::starrefInfoIconPosition);
+ };
+
+ content->add(
+ object_ptr(
+ content,
+ tr::lng_frozen_title(),
+ st.title ? *st.title : st::uniqueGiftTitle),
+ st::settingsPremiumRowTitlePadding);
+
+ Ui::AddSkip(content, st::defaultVerticalListSkip * 3);
+
+ infoRow(
+ tr::lng_frozen_subtitle1(),
+ tr::lng_frozen_text1(Ui::Text::WithEntities),
+ st.violationIcon ? st.violationIcon : &st::menuIconBlock);
+ infoRow(
+ tr::lng_frozen_subtitle2(),
+ tr::lng_frozen_text2(Ui::Text::WithEntities),
+ st.readOnlyIcon ? st.readOnlyIcon : &st::menuIconLock);
+ infoRow(
+ tr::lng_frozen_subtitle3(),
+ tr::lng_frozen_text3(
+ lt_link,
+ rpl::single(Ui::Text::Link(u"@SpamBot"_q, info.appealUrl)),
+ lt_date,
+ rpl::single(TextWithEntities{
+ langDayOfMonthFull(
+ base::unixtime::parse(info.until).date()),
+ }),
+ Ui::Text::WithEntities),
+ st.appealIcon ? st.appealIcon : &st::menuIconHourglass);
+
+ const auto button = box->addButton(
+ tr::lng_frozen_appeal_button(),
+ [url = info.appealUrl] { UrlClickHandler::Open(url); });
+ const auto buttonPadding = st::frozenInfoBox.buttonPadding;
+ const auto buttonWidth = st::boxWideWidth
+ - buttonPadding.left()
+ - buttonPadding.right();
+ button->widthValue() | rpl::filter([=] {
+ return (button->widthNoMargins() != buttonWidth);
+ }) | rpl::start_with_next([=] {
+ button->resizeToWidth(buttonWidth);
+ }, button->lifetime());
+}
diff --git a/Telegram/SourceFiles/chat_helpers/message_field.h b/Telegram/SourceFiles/chat_helpers/message_field.h
index 7d97d93321..4d7ef52b48 100644
--- a/Telegram/SourceFiles/chat_helpers/message_field.h
+++ b/Telegram/SourceFiles/chat_helpers/message_field.h
@@ -37,7 +37,12 @@ enum class PauseReason;
class Show;
} // namespace ChatHelpers
+namespace HistoryView::Controls {
+struct WriteRestriction;
+} // namespace HistoryView::Controls
+
namespace Ui {
+class GenericBox;
class PopupMenu;
class Show;
} // namespace Ui
@@ -162,13 +167,41 @@ private:
[[nodiscard]] base::unique_qptr CreateDisabledFieldView(
QWidget *parent,
not_null peer);
-[[nodiscard]] base::unique_qptr TextErrorSendRestriction(
+[[nodiscard]] std::unique_ptr TextErrorSendRestriction(
QWidget *parent,
const QString &text);
-[[nodiscard]] base::unique_qptr PremiumRequiredSendRestriction(
+[[nodiscard]] std::unique_ptr PremiumRequiredSendRestriction(
QWidget *parent,
not_null user,
not_null controller);
+[[nodiscard]] auto BoostsToLiftWriteRestriction(
+ not_null parent,
+ std::shared_ptr show,
+ not_null peer,
+ int boosts)
+-> std::unique_ptr;
+
+struct FreezeInfoStyleOverride {
+ const style::Box *box = nullptr;
+ const style::FlatLabel *title = nullptr;
+ const style::FlatLabel *subtitle = nullptr;
+ const style::icon *violationIcon = nullptr;
+ const style::icon *readOnlyIcon = nullptr;
+ const style::icon *appealIcon = nullptr;
+ const style::FlatLabel *infoTitle = nullptr;
+ const style::FlatLabel *infoAbout = nullptr;
+};
+[[nodiscard]] FreezeInfoStyleOverride DarkFreezeInfoStyle();
+
+enum class FrozenWriteRestrictionType {
+ MessageField,
+ DialogsList,
+};
+[[nodiscard]] std::unique_ptr FrozenWriteRestriction(
+ not_null parent,
+ std::shared_ptr show,
+ FrozenWriteRestrictionType type,
+ FreezeInfoStyleOverride st = {});
void SelectTextInFieldWithMargins(
not_null field,
@@ -178,3 +211,8 @@ void SelectTextInFieldWithMargins(
[[nodiscard]] rpl::producer PaidSendButtonText(
rpl::producer stars,
rpl::producer fallback = nullptr);
+
+void FrozenInfoBox(
+ not_null box,
+ not_null session,
+ FreezeInfoStyleOverride st);
diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp
index bca5ae7ebc..33ec7ef78d 100644
--- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp
+++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_list_widget.h"
#include "chat_helpers/gifs_list_widget.h"
#include "menu/menu_send.h"
+#include "ui/controls/swipe_handler.h"
#include "ui/controls/tabbed_search.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/buttons.h"
@@ -522,7 +523,6 @@ TabbedSelector::TabbedSelector(
if (hasEmojiTab()) {
emoji()->refreshEmoji();
}
- //setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_OpaquePaintEvent, false);
showAll();
hide();
@@ -530,6 +530,60 @@ TabbedSelector::TabbedSelector(
TabbedSelector::~TabbedSelector() = default;
+void TabbedSelector::reinstallSwipe(not_null widget) {
+ _swipeLifetime.destroy();
+
+ auto update = [=](Ui::Controls::SwipeContextData data) {
+ if (data.translation != 0) {
+ if (!_swipeBackData.callback) {
+ _swipeBackData = Ui::Controls::SetupSwipeBack(
+ this,
+ [=]() -> std::pair {
+ return {
+ st::historyForwardChooseBg->c,
+ st::historyForwardChooseFg->c,
+ };
+ },
+ data.translation < 0);
+ }
+ _swipeBackData.callback(data);
+ return;
+ } else if (_swipeBackData.lifetime) {
+ _swipeBackData = {};
+ }
+ };
+
+ auto init = [=](int, Qt::LayoutDirection direction) {
+ if (!_tabsSlider) {
+ return Ui::Controls::SwipeHandlerFinishData();
+ }
+ const auto activeSection = _tabsSlider->activeSection();
+ const auto isToLeft = direction == Qt::RightToLeft;
+ if ((isToLeft && activeSection > 0)
+ || (!isToLeft && activeSection < _tabs.size() - 1)) {
+ return Ui::Controls::DefaultSwipeBackHandlerFinishData([=] {
+ if (_tabsSlider
+ && _tabsSlider->activeSection() == activeSection) {
+ _swipeBackData = {};
+ _tabsSlider->setActiveSection(isToLeft
+ ? activeSection - 1
+ : activeSection + 1);
+ }
+ });
+ }
+ return Ui::Controls::SwipeHandlerFinishData();
+ };
+
+ Ui::Controls::SetupSwipeHandler({
+ .widget = widget,
+ .scroll = _scroll.data(),
+ .update = std::move(update),
+ .init = std::move(init),
+ .dontStart = nullptr,
+ .onLifetime = &_swipeLifetime,
+ });
+}
+
const style::EmojiPan &TabbedSelector::st() const {
return _st;
}
@@ -1302,6 +1356,10 @@ void TabbedSelector::setWidgetToScrollArea() {
inner->moveToLeft(0, 0);
inner->show();
+ if (_tabs.size() > 1) {
+ reinstallSwipe(inner);
+ }
+
_scroll->disableScroll(false);
scrollToY(currentTab()->getScrollTop());
handleScroll();
diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h
index ad8821d846..47e8c4b649 100644
--- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h
+++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h
@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_common.h"
#include "chat_helpers/compose/compose_features.h"
#include "ui/rp_widget.h"
+#include "ui/controls/swipe_handler_data.h"
#include "ui/effects/animations.h"
#include "ui/effects/message_sending_animation_common.h"
#include "ui/effects/panel_animation.h"
@@ -287,12 +288,16 @@ private:
not_null gifs() const;
not_null masks() const;
+ void reinstallSwipe(not_null widget);
+
const style::EmojiPan &_st;
const ComposeFeatures _features;
const std::shared_ptr _show;
const PauseReason _level = {};
const Fn _customTextColor;
+ Ui::Controls::SwipeBackResult _swipeBackData;
+
Mode _mode = Mode::Full;
int _roundRadius = 0;
int _footerTop = 0;
@@ -329,6 +334,8 @@ private:
rpl::event_stream<> _showRequests;
rpl::event_stream<> _slideFinished;
+ rpl::lifetime _swipeLifetime;
+
};
class TabbedSelector::Inner : public Ui::RpWidget {
diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp
index e3ceadc853..c8134da03f 100644
--- a/Telegram/SourceFiles/core/application.cpp
+++ b/Telegram/SourceFiles/core/application.cpp
@@ -93,6 +93,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include
#include
+#include
+
// AyuGram includes
#include "ayu/ayu_infra.h"
#include "ayu/features/streamer_mode/streamer_mode.h"
diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp
index f655093ef7..1db0a3a47b 100644
--- a/Telegram/SourceFiles/core/core_settings.cpp
+++ b/Telegram/SourceFiles/core/core_settings.cpp
@@ -244,7 +244,7 @@ QByteArray Settings::serialize() const {
+ Serialize::stringSize(_customFontFamily)
+ sizeof(qint32) * 3
+ Serialize::bytearraySize(_tonsiteStorageToken)
- + sizeof(qint32) * 7;
+ + sizeof(qint32) * 8;
auto result = QByteArray();
result.reserve(size);
@@ -405,7 +405,8 @@ QByteArray Settings::serialize() const {
<< qint32(_recordVideoMessages ? 1 : 0)
<< SerializeVideoQuality(_videoQuality)
<< qint32(_ivZoom.current())
- << qint32(_systemDarkModeEnabled.current() ? 1 : 0);
+ << qint32(_systemDarkModeEnabled.current() ? 1 : 0)
+ << qint32(_quickDialogAction);
}
Ensures(result.size() == size);
@@ -536,6 +537,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 recordVideoMessages = _recordVideoMessages ? 1 : 0;
quint32 videoQuality = SerializeVideoQuality(_videoQuality);
quint32 chatFiltersHorizontal = _chatFiltersHorizontal.current() ? 1 : 0;
+ quint32 quickDialogAction = quint32(_quickDialogAction);
stream >> themesAccentColors;
if (!stream.atEnd()) {
@@ -864,6 +866,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) {
stream >> systemDarkModeEnabled;
}
+ if (!stream.atEnd()) {
+ stream >> quickDialogAction;
+ }
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
@@ -1086,6 +1091,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
_recordVideoMessages = (recordVideoMessages == 1);
_videoQuality = DeserializeVideoQuality(videoQuality);
_chatFiltersHorizontal = (chatFiltersHorizontal == 1);
+ _quickDialogAction = Dialogs::Ui::QuickDialogAction(quickDialogAction);
}
QString Settings::getSoundPath(const QString &key) const {
@@ -1477,6 +1483,7 @@ void Settings::resetOnLastLogout() {
_recordVideoMessages = false;
_videoQuality = {};
_chatFiltersHorizontal = false;
+ _quickDialogAction = Dialogs::Ui::QuickDialogAction::Disabled;
_recentEmojiPreload.clear();
_recentEmoji.clear();
@@ -1664,4 +1671,12 @@ void Settings::setChatFiltersHorizontal(bool value) {
_chatFiltersHorizontal = value;
}
+Dialogs::Ui::QuickDialogAction Settings::quickDialogAction() const {
+ return _quickDialogAction;
+}
+
+void Settings::setQuickDialogAction(Dialogs::Ui::QuickDialogAction action) {
+ _quickDialogAction = action;
+}
+
} // namespace Core
diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h
index 4f4711b234..f8dc8a188c 100644
--- a/Telegram/SourceFiles/core/core_settings.h
+++ b/Telegram/SourceFiles/core/core_settings.h
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/core_settings_proxy.h"
#include "media/media_common.h"
+#include "dialogs/ui/dialogs_quick_action.h"
#include "window/themes/window_themes_embedded.h"
#include "ui/chat/attach/attach_send_files_way.h"
#include "base/flags.h"
@@ -952,6 +953,9 @@ public:
[[nodiscard]] static PlaybackSpeed DeserializePlaybackSpeed(
qint32 speed);
+ [[nodiscard]] Dialogs::Ui::QuickDialogAction quickDialogAction() const;
+ void setQuickDialogAction(Dialogs::Ui::QuickDialogAction);
+
void resetOnLastLogout();
private:
@@ -1092,6 +1096,9 @@ private:
bool _recordVideoMessages = false;
+ Dialogs::Ui::QuickDialogAction _quickDialogAction
+ = Dialogs::Ui::QuickDialogAction::Disabled;
+
QByteArray _photoEditorBrush;
};
diff --git a/Telegram/SourceFiles/core/launcher.cpp b/Telegram/SourceFiles/core/launcher.cpp
index 5334eb97ef..538f78dd25 100644
--- a/Telegram/SourceFiles/core/launcher.cpp
+++ b/Telegram/SourceFiles/core/launcher.cpp
@@ -504,6 +504,22 @@ uint64 Launcher::installationTag() const {
return InstallationTag;
}
+QByteArray Launcher::instanceHash() const {
+ static const auto Result = [&] {
+ QByteArray h(32, 0);
+ if (customWorkingDir()) {
+ const auto d = QFile::encodeName(
+ QDir(cWorkingDir()).absolutePath());
+ hashMd5Hex(d.constData(), d.size(), h.data());
+ } else {
+ const auto f = QFile::encodeName(cExeDir() + cExeName());
+ hashMd5Hex(f.constData(), f.size(), h.data());
+ }
+ return h;
+ }();
+ return Result;
+}
+
void Launcher::processArguments() {
enum class KeyFormat {
NoValues,
diff --git a/Telegram/SourceFiles/core/launcher.h b/Telegram/SourceFiles/core/launcher.h
index ea5b1c97f3..e4de3c31d2 100644
--- a/Telegram/SourceFiles/core/launcher.h
+++ b/Telegram/SourceFiles/core/launcher.h
@@ -33,6 +33,7 @@ public:
bool customWorkingDir() const;
uint64 installationTag() const;
+ QByteArray instanceHash() const;
bool checkPortableVersionFolder();
bool validateCustomWorkingDir();
diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp
index fbb5fbfb0a..0c8899cf7a 100644
--- a/Telegram/SourceFiles/core/local_url_handlers.cpp
+++ b/Telegram/SourceFiles/core/local_url_handlers.cpp
@@ -306,6 +306,42 @@ void ShowLanguagesBox(Window::SessionController *controller) {
Guard = LanguageBox::Show(controller);
}
+void ShowPhonePrivacyBox(Window::SessionController *controller) {
+ static auto Guard = base::binary_guard();
+ auto guard = base::binary_guard();
+
+ using Privacy = Api::UserPrivacy;
+ const auto key = Privacy::Key::PhoneNumber;
+ controller->session().api().userPrivacy().reload(key);
+
+ const auto weak = base::make_weak(controller);
+ auto shared = std::make_shared(
+ guard.make_guard());
+ auto lifetime = std::make_shared();
+ controller->session().api().userPrivacy().value(
+ key
+ ) | rpl::take(
+ 1
+ ) | rpl::start_with_next([=](const Privacy::Rule &value) mutable {
+ using namespace ::Settings;
+ const auto show = shared->alive();
+ if (lifetime) {
+ base::take(lifetime)->destroy();
+ }
+ if (show) {
+ if (const auto controller = weak.get()) {
+ controller->show(Box(
+ controller,
+ std::make_unique(
+ controller),
+ value));
+ }
+ }
+ }, *lifetime);
+
+ Guard = std::move(guard);
+}
+
bool SetLanguage(
Window::SessionController *controller,
const Match &match,
@@ -722,6 +758,9 @@ bool ResolveSettings(
if (section == u"language"_q) {
ShowLanguagesBox(controller);
return {};
+ } else if (section == u"phone_privacy"_q) {
+ ShowPhonePrivacyBox(controller);
+ return {};
} else if (section == u"devices"_q) {
return ::Settings::Sessions::Id();
} else if (section == u"folders"_q) {
@@ -876,6 +915,8 @@ bool ShowEditBirthday(
const QVariant &context) {
if (!controller) {
return false;
+ } else if (controller->showFrozenError()) {
+ return true;
}
const auto user = controller->session().user();
const auto save = [=](Data::Birthday result) {
@@ -932,6 +973,8 @@ bool ShowEditPersonalChannel(
const QVariant &context) {
if (!controller) {
return false;
+ } else if (controller->showFrozenError()) {
+ return true;
}
auto listController = std::make_unique(
@@ -1466,7 +1509,7 @@ const std::vector &LocalUrlHandlers() {
ResolvePrivatePost
},
{
- u"^settings(/language|/devices|/folders|/privacy|/themes|/change_number|/auto_delete|/information|/edit_profile)?$"_q,
+ u"^settings(/language|/devices|/folders|/privacy|/themes|/change_number|/auto_delete|/information|/edit_profile|/phone_privacy)?$"_q,
ResolveSettings
},
{
diff --git a/Telegram/SourceFiles/core/shortcuts.cpp b/Telegram/SourceFiles/core/shortcuts.cpp
index 667ab43aed..9a3a09a444 100644
--- a/Telegram/SourceFiles/core/shortcuts.cpp
+++ b/Telegram/SourceFiles/core/shortcuts.cpp
@@ -110,6 +110,7 @@ const auto CommandByName = base::flat_map{
{ u"read_chat"_q , Command::ReadChat },
{ u"show_chat_menu"_q , Command::ShowChatMenu },
+ { u"show_chat_preview"_q , Command::ShowChatPreview },
// Shortcuts that have no default values.
{ u"message"_q , Command::JustSendMessage },
@@ -506,6 +507,7 @@ void Manager::fillDefaults() {
set(u"ctrl+r"_q, Command::ReadChat);
set(u"ctrl+\\"_q, Command::ShowChatMenu);
+ set(u"ctrl+]"_q, Command::ShowChatPreview);
_defaults = keysCurrents();
}
diff --git a/Telegram/SourceFiles/core/shortcuts.h b/Telegram/SourceFiles/core/shortcuts.h
index 70c8eb63af..7be77d4eca 100644
--- a/Telegram/SourceFiles/core/shortcuts.h
+++ b/Telegram/SourceFiles/core/shortcuts.h
@@ -72,6 +72,7 @@ enum class Command {
MediaViewerFullscreen,
ShowChatMenu,
+ ShowChatPreview,
SupportReloadTemplates,
SupportToggleMuted,
diff --git a/Telegram/SourceFiles/core/utils.h b/Telegram/SourceFiles/core/utils.h
index 325f6ccc43..9d8a3ee622 100644
--- a/Telegram/SourceFiles/core/utils.h
+++ b/Telegram/SourceFiles/core/utils.h
@@ -21,10 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include
#include
-#if __has_include()
-#include
-#endif
-
#define qsl(s) QStringLiteral(s)
namespace base {
@@ -34,15 +30,6 @@ inline bool in_range(Value &&value, From &&from, Till &&till) {
return (value >= from) && (value < till);
}
-#if __has_include()
-inline QString IconName() {
- static const auto Result = KSandbox::isFlatpak()
- ? qEnvironmentVariable("FLATPAK_ID")
- : u"telegram"_q;
- return Result;
-}
-#endif
-
inline bool CanReadDirectory(const QString &path) {
#ifndef Q_OS_MAC // directory_iterator since 10.15
std::error_code error;
diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h
index a2770d5708..2122ec9e8e 100644
--- a/Telegram/SourceFiles/core/version.h
+++ b/Telegram/SourceFiles/core/version.h
@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
constexpr auto AppNameOld = "AyuGram for Windows"_cs;
constexpr auto AppName = "AyuGram Desktop"_cs;
constexpr auto AppFile = "AyuGram"_cs;
-constexpr auto AppVersion = 5012003;
-constexpr auto AppVersionStr = "5.12.3";
+constexpr auto AppVersion = 5013001;
+constexpr auto AppVersionStr = "5.13.1";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
diff --git a/Telegram/SourceFiles/data/business/data_business_chatbots.cpp b/Telegram/SourceFiles/data/business/data_business_chatbots.cpp
index ca894acf55..126b7043bb 100644
--- a/Telegram/SourceFiles/data/business/data_business_chatbots.cpp
+++ b/Telegram/SourceFiles/data/business/data_business_chatbots.cpp
@@ -8,10 +8,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/business/data_business_chatbots.h"
#include "apiwrap.h"
+#include "boxes/peers/edit_peer_permissions_box.h"
#include "data/business/data_business_common.h"
#include "data/business/data_business_info.h"
#include "data/data_session.h"
#include "data/data_user.h"
+#include "lang/lang_keys.h"
#include "main/main_session.h"
namespace Data {
@@ -41,7 +43,7 @@ void Chatbots::preload() {
_settings = ChatbotsSettings{
.bot = _owner->session().data().user(botId),
.recipients = FromMTP(_owner, bot.vrecipients()),
- .repliesAllowed = bot.is_can_reply(),
+ .permissions = FromMTP(bot.vrights()),
};
} else {
_settings.force_assign(ChatbotsSettings());
@@ -81,11 +83,8 @@ void Chatbots::save(
using Flag = MTPaccount_UpdateConnectedBot::Flag;
const auto api = &_owner->session().api();
api->request(MTPaccount_UpdateConnectedBot(
- MTP_flags(!settings.bot
- ? Flag::f_deleted
- : settings.repliesAllowed
- ? Flag::f_can_reply
- : Flag()),
+ MTP_flags(!settings.bot ? Flag::f_deleted : Flag::f_rights),
+ ToMTP(settings.permissions),
(settings.bot ? settings.bot : was.bot)->inputUser,
ForBotsToMTP(settings.recipients)
)).done([=](const MTPUpdates &result) {
@@ -180,4 +179,39 @@ void Chatbots::reload() {
preload();
}
+EditFlagsDescriptor ChatbotsPermissionsLabels() {
+ using Flag = ChatbotsPermission;
+
+ using PermissionLabel = EditFlagsLabel;
+ auto messages = std::vector{
+ { Flag::ViewMessages, tr::lng_chatbots_read(tr::now) },
+ { Flag::ReplyToMessages, tr::lng_chatbots_reply(tr::now) },
+ { Flag::MarkAsRead, tr::lng_chatbots_mark_as_read(tr::now) },
+ { Flag::DeleteSent, tr::lng_chatbots_delete_sent(tr::now) },
+ { Flag::DeleteReceived, tr::lng_chatbots_delete_received(tr::now) },
+ };
+ auto manage = std::vector{
+ { Flag::EditName, tr::lng_chatbots_edit_name(tr::now) },
+ { Flag::EditBio, tr::lng_chatbots_edit_bio(tr::now) },
+ { Flag::EditUserpic, tr::lng_chatbots_edit_userpic(tr::now) },
+ { Flag::EditUsername, tr::lng_chatbots_edit_username(tr::now) },
+ };
+ auto gifts = std::vector{
+ { Flag::ViewGifts, tr::lng_chatbots_view_gifts(tr::now) },
+ { Flag::SellGifts, tr::lng_chatbots_sell_gifts(tr::now) },
+ { Flag::GiftSettings, tr::lng_chatbots_gift_settings(tr::now) },
+ { Flag::TransferGifts, tr::lng_chatbots_transfer_gifts(tr::now) },
+ { Flag::TransferStars, tr::lng_chatbots_transfer_stars(tr::now) },
+ };
+ auto stories = std::vector{
+ { Flag::ManageStories, tr::lng_chatbots_manage_stories(tr::now) },
+ };
+ return { .labels = {
+ { tr::lng_chatbots_manage_messages(), std::move(messages) },
+ { tr::lng_chatbots_manage_profile(), std::move(manage) },
+ { tr::lng_chatbots_manage_gifts(), std::move(gifts) },
+ { std::nullopt, std::move(stories) },
+ }, .st = nullptr };
+}
+
} // namespace Data
diff --git a/Telegram/SourceFiles/data/business/data_business_chatbots.h b/Telegram/SourceFiles/data/business/data_business_chatbots.h
index 902cdd4206..97a034845e 100644
--- a/Telegram/SourceFiles/data/business/data_business_chatbots.h
+++ b/Telegram/SourceFiles/data/business/data_business_chatbots.h
@@ -11,6 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class UserData;
+template
+struct EditFlagsDescriptor;
+
namespace Data {
class Session;
@@ -18,7 +21,7 @@ class Session;
struct ChatbotsSettings {
UserData *bot = nullptr;
BusinessRecipients recipients;
- bool repliesAllowed = false;
+ ChatbotsPermissions permissions;
friend inline bool operator==(
const ChatbotsSettings &,
@@ -67,4 +70,7 @@ private:
};
+[[nodiscard]] auto ChatbotsPermissionsLabels()
+-> EditFlagsDescriptor;
+
} // namespace Data
diff --git a/Telegram/SourceFiles/data/business/data_business_common.cpp b/Telegram/SourceFiles/data/business/data_business_common.cpp
index 149a3ee136..dc6619f5e7 100644
--- a/Telegram/SourceFiles/data/business/data_business_common.cpp
+++ b/Telegram/SourceFiles/data/business/data_business_common.cpp
@@ -159,6 +159,47 @@ BusinessRecipients FromMTP(
return result;
}
+ChatbotsPermissions FromMTP(const MTPBusinessBotRights &rights) {
+ using Flag = ChatbotsPermission;
+ const auto &data = rights.data();
+
+ return Flag::ViewMessages
+ | (data.is_reply() ? Flag::ReplyToMessages : Flag())
+ | (data.is_read_messages() ? Flag::MarkAsRead : Flag())
+ | (data.is_delete_sent_messages() ? Flag::DeleteSent : Flag())
+ | (data.is_delete_received_messages() ? Flag::DeleteReceived : Flag())
+ | (data.is_edit_name() ? Flag::EditName : Flag())
+ | (data.is_edit_bio() ? Flag::EditBio : Flag())
+ | (data.is_edit_profile_photo() ? Flag::EditUserpic : Flag())
+ | (data.is_edit_username() ? Flag::EditUsername : Flag())
+ | (data.is_view_gifts() ? Flag::ViewGifts : Flag())
+ | (data.is_sell_gifts() ? Flag::SellGifts : Flag())
+ | (data.is_change_gift_settings() ? Flag::GiftSettings : Flag())
+ | (data.is_transfer_and_upgrade_gifts() ? Flag::TransferGifts : Flag())
+ | (data.is_transfer_stars() ? Flag::TransferStars : Flag())
+ | (data.is_manage_stories() ? Flag::ManageStories : Flag());
+}
+
+MTPBusinessBotRights ToMTP(ChatbotsPermissions rights) {
+ using Flag = MTPDbusinessBotRights::Flag;
+ using Right = ChatbotsPermission;
+ return MTP_businessBotRights(MTP_flags(Flag()
+ | ((rights & Right::ReplyToMessages) ? Flag::f_reply : Flag())
+ | ((rights & Right::MarkAsRead) ? Flag::f_read_messages : Flag())
+ | ((rights & Right::DeleteSent) ? Flag::f_delete_sent_messages : Flag())
+ | ((rights & Right::DeleteReceived) ? Flag::f_delete_received_messages : Flag())
+ | ((rights & Right::EditName) ? Flag::f_edit_name : Flag())
+ | ((rights & Right::EditBio) ? Flag::f_edit_bio : Flag())
+ | ((rights & Right::EditUserpic) ? Flag::f_edit_profile_photo : Flag())
+ | ((rights & Right::EditUsername) ? Flag::f_edit_username : Flag())
+ | ((rights & Right::ViewGifts) ? Flag::f_view_gifts : Flag())
+ | ((rights & Right::SellGifts) ? Flag::f_sell_gifts : Flag())
+ | ((rights & Right::GiftSettings) ? Flag::f_change_gift_settings : Flag())
+ | ((rights & Right::TransferGifts) ? Flag::f_transfer_and_upgrade_gifts : Flag())
+ | ((rights & Right::TransferStars) ? Flag::f_transfer_stars : Flag())
+ | ((rights & Right::ManageStories) ? Flag::f_manage_stories : Flag())));
+}
+
BusinessDetails FromMTP(
not_null owner,
const tl::conditional &hours,
diff --git a/Telegram/SourceFiles/data/business/data_business_common.h b/Telegram/SourceFiles/data/business/data_business_common.h
index 600d5ff79d..90ae82b074 100644
--- a/Telegram/SourceFiles/data/business/data_business_common.h
+++ b/Telegram/SourceFiles/data/business/data_business_common.h
@@ -57,6 +57,26 @@ enum class BusinessRecipientsType : uchar {
Bots,
};
+enum class ChatbotsPermission {
+ ViewMessages = 0x0001,
+ ReplyToMessages = 0x0002,
+ MarkAsRead = 0x0004,
+ DeleteSent = 0x0008,
+ DeleteReceived = 0x0010,
+ EditName = 0x0020,
+ EditBio = 0x0040,
+ EditUserpic = 0x0080,
+ EditUsername = 0x0100,
+ ViewGifts = 0x0200,
+ SellGifts = 0x0400,
+ GiftSettings = 0x0800,
+ TransferGifts = 0x1000,
+ TransferStars = 0x2000,
+ ManageStories = 0x4000,
+};
+inline constexpr bool is_flag_type(ChatbotsPermission) { return true; }
+using ChatbotsPermissions = base::flags;
+
[[nodiscard]] MTPInputBusinessRecipients ForMessagesToMTP(
const BusinessRecipients &data);
[[nodiscard]] MTPInputBusinessBotRecipients ForBotsToMTP(
@@ -67,6 +87,9 @@ enum class BusinessRecipientsType : uchar {
[[nodiscard]] BusinessRecipients FromMTP(
not_null owner,
const MTPBusinessBotRecipients &recipients);
+[[nodiscard]] ChatbotsPermissions FromMTP(
+ const MTPBusinessBotRights &rights);
+[[nodiscard]] MTPBusinessBotRights ToMTP(ChatbotsPermissions rights);
struct Timezone {
QString id;
diff --git a/Telegram/SourceFiles/data/components/sponsored_messages.cpp b/Telegram/SourceFiles/data/components/sponsored_messages.cpp
index c039247326..6fc7cbd5a1 100644
--- a/Telegram/SourceFiles/data/components/sponsored_messages.cpp
+++ b/Telegram/SourceFiles/data/components/sponsored_messages.cpp
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/components/sponsored_messages.h"
#include "api/api_text_entities.h"
+#include "api/api_peer_search.h" // SponsoredSearchResult
#include "apiwrap.h"
#include "core/click_handler_types.h"
#include "data/data_channel.h"
@@ -37,6 +38,19 @@ constexpr auto kRequestTimeLimit = 5 * 60 * crl::time(1000);
return (received > 0) && (received + kRequestTimeLimit > crl::now());
}
+template
+[[nodiscard]] std::vector Prepare(const Fields &fields) {
+ using InfoList = std::vector;
+ return (!fields.sponsorInfo.text.isEmpty()
+ && !fields.additionalInfo.text.isEmpty())
+ ? InfoList{ fields.sponsorInfo, fields.additionalInfo }
+ : !fields.sponsorInfo.text.isEmpty()
+ ? InfoList{ fields.sponsorInfo }
+ : !fields.additionalInfo.text.isEmpty()
+ ? InfoList{ fields.additionalInfo }
+ : InfoList{};
+}
+
} // namespace
SponsoredMessages::SponsoredMessages(not_null session)
@@ -523,17 +537,16 @@ void SponsoredMessages::view(const FullMsgId &fullId) {
if (!entryPtr) {
return;
}
- const auto randomId = entryPtr->sponsored.randomId;
+ view(entryPtr->sponsored.randomId);
+}
+
+void SponsoredMessages::view(const QByteArray &randomId) {
auto &request = _viewRequests[randomId];
if (request.requestId || TooEarlyForRequest(request.lastReceived)) {
return;
}
request.requestId = _session->api().request(
- MTPmessages_ViewSponsoredMessage(
- entryPtr->item
- ? entryPtr->item->history()->peer->input
- : _session->data().peer(fullId.peer)->input,
- MTP_bytes(randomId))
+ MTPmessages_ViewSponsoredMessage(MTP_bytes(randomId))
).done([=] {
auto &request = _viewRequests[randomId];
request.lastReceived = crl::now();
@@ -550,18 +563,8 @@ SponsoredMessages::Details SponsoredMessages::lookupDetails(
return {};
}
const auto &data = entryPtr->sponsored;
-
- using InfoList = std::vector;
- auto info = (!data.sponsorInfo.text.isEmpty()
- && !data.additionalInfo.text.isEmpty())
- ? InfoList{ data.sponsorInfo, data.additionalInfo }
- : !data.sponsorInfo.text.isEmpty()
- ? InfoList{ data.sponsorInfo }
- : !data.additionalInfo.text.isEmpty()
- ? InfoList{ data.additionalInfo }
- : InfoList{};
return {
- .info = std::move(info),
+ .info = Prepare(data),
.link = data.link,
.buttonText = data.from.buttonText,
.photoId = data.from.photoId,
@@ -574,6 +577,14 @@ SponsoredMessages::Details SponsoredMessages::lookupDetails(
};
}
+SponsoredMessages::Details SponsoredMessages::lookupDetails(
+ const Api::SponsoredSearchResult &data) const {
+ return {
+ .info = Prepare(data),
+ .canReport = true,
+ };
+}
+
void SponsoredMessages::clicked(
const FullMsgId &fullId,
bool isMedia,
@@ -582,22 +593,45 @@ void SponsoredMessages::clicked(
if (!entryPtr) {
return;
}
- const auto randomId = entryPtr->sponsored.randomId;
+ clicked(entryPtr->sponsored.randomId, isMedia, isFullscreen);
+}
+
+void SponsoredMessages::clicked(
+ const QByteArray &randomId,
+ bool isMedia,
+ bool isFullscreen) {
using Flag = MTPmessages_ClickSponsoredMessage::Flag;
_session->api().request(MTPmessages_ClickSponsoredMessage(
MTP_flags(Flag(0)
| (isMedia ? Flag::f_media : Flag(0))
| (isFullscreen ? Flag::f_fullscreen : Flag(0))),
- entryPtr->item
- ? entryPtr->item->history()->peer->input
- : _session->data().peer(fullId.peer)->input,
MTP_bytes(randomId)
)).send();
}
+SponsoredReportAction SponsoredMessages::createReportCallback(
+ const FullMsgId &fullId) {
+ const auto entry = find(fullId);
+ if (!entry) {
+ return { .callback = [=](const auto &...) {} };
+ }
+ const auto history = _session->data().history(fullId.peer);
+ const auto erase = [=] {
+ const auto it = _data.find(history);
+ if (it != end(_data)) {
+ auto &list = it->second.entries;
+ const auto proj = [&](const Entry &e) {
+ return e.itemFullId == fullId;
+ };
+ list.erase(ranges::remove_if(list, proj), end(list));
+ }
+ };
+ return createReportCallback(entry->sponsored.randomId, erase);
+}
-auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
--> Fn)> {
+SponsoredReportAction SponsoredMessages::createReportCallback(
+ const QByteArray &randomId,
+ Fn erase) {
using TLChoose = MTPDchannels_sponsoredMessageReportResultChooseOption;
using TLAdsHidden = MTPDchannels_sponsoredMessageReportResultAdsHidden;
using TLReported = MTPDchannels_sponsoredMessageReportResultReported;
@@ -613,25 +647,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
};
const auto state = std::make_shared();
- return [=](Result::Id optionId, Fn done) {
- const auto entry = find(fullId);
- if (!entry) {
- return;
- }
-
- const auto history = _session->data().history(fullId.peer);
-
- const auto erase = [=] {
- const auto it = _data.find(history);
- if (it != end(_data)) {
- auto &list = it->second.entries;
- const auto proj = [&](const Entry &e) {
- return e.itemFullId == fullId;
- };
- list.erase(ranges::remove_if(list, proj), end(list));
- }
- };
-
+ return { .callback = [=](Result::Id optionId, Fn done) {
if (optionId == Result::Id("-1")) {
erase();
return;
@@ -639,8 +655,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
state->requestId = _session->api().request(
MTPmessages_ReportSponsoredMessage(
- history->peer->input,
- MTP_bytes(entry->sponsored.randomId),
+ MTP_bytes(randomId),
MTP_bytes(optionId))
).done([=](
const MTPchannels_SponsoredMessageReportResult &result,
@@ -677,7 +692,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
done({ .error = error.type() });
}
}).send();
- };
+ } };
}
SponsoredMessages::State SponsoredMessages::state(
diff --git a/Telegram/SourceFiles/data/components/sponsored_messages.h b/Telegram/SourceFiles/data/components/sponsored_messages.h
index ebcefb9e20..6c875c081c 100644
--- a/Telegram/SourceFiles/data/components/sponsored_messages.h
+++ b/Telegram/SourceFiles/data/components/sponsored_messages.h
@@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class History;
+namespace Api {
+struct SponsoredSearchResult;
+} // namespace Api
+
namespace Main {
class Session;
} // namespace Main
@@ -69,6 +73,25 @@ struct SponsoredMessage {
TextWithEntities additionalInfo;
};
+struct SponsoredMessageDetails {
+ std::vector info;
+ QString link;
+ QString buttonText;
+ PhotoId photoId = PhotoId(0);
+ PhotoId mediaPhotoId = PhotoId(0);
+ DocumentId mediaDocumentId = DocumentId(0);
+ uint64 backgroundEmojiId = 0;
+ uint8 colorIndex : 6 = 0;
+ bool isLinkInternal = false;
+ bool canReport = false;
+};
+
+struct SponsoredReportAction {
+ Fn)> callback;
+};
+
class SponsoredMessages final {
public:
enum class AppendResult {
@@ -82,18 +105,7 @@ public:
InjectToMiddle,
AppendToTopBar,
};
- struct Details {
- std::vector info;
- QString link;
- QString buttonText;
- PhotoId photoId = PhotoId(0);
- PhotoId mediaPhotoId = PhotoId(0);
- DocumentId mediaDocumentId = DocumentId(0);
- uint64 backgroundEmojiId = 0;
- uint8 colorIndex : 6 = 0;
- bool isLinkInternal = false;
- bool canReport = false;
- };
+ using Details = SponsoredMessageDetails;
using RandomId = QByteArray;
explicit SponsoredMessages(not_null session);
~SponsoredMessages();
@@ -103,7 +115,13 @@ public:
void request(not_null history, Fn done);
void clearItems(not_null history);
[[nodiscard]] Details lookupDetails(const FullMsgId &fullId) const;
+ [[nodiscard]] Details lookupDetails(
+ const Api::SponsoredSearchResult &data) const;
void clicked(const FullMsgId &fullId, bool isMedia, bool isFullscreen);
+ void clicked(
+ const QByteArray &randomId,
+ bool isMedia,
+ bool isFullscreen);
[[nodiscard]] FullMsgId fillTopBar(
not_null history,
not_null widget);
@@ -117,11 +135,15 @@ public:
int fallbackWidth);
void view(const FullMsgId &fullId);
+ void view(const QByteArray &randomId);
[[nodiscard]] State state(not_null history) const;
- [[nodiscard]] auto createReportCallback(const FullMsgId &fullId)
- -> Fn)>;
+ [[nodiscard]] SponsoredReportAction createReportCallback(
+ const FullMsgId &fullId);
+ [[nodiscard]] SponsoredReportAction createReportCallback(
+ const QByteArray &randomId,
+ Fn erase);
void clear();
diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h
index f44ae72bbf..39a654d3c0 100644
--- a/Telegram/SourceFiles/data/data_changes.h
+++ b/Telegram/SourceFiles/data/data_changes.h
@@ -96,27 +96,28 @@ struct PeerUpdate {
PersonalChannel = (1ULL << 34),
StarRefProgram = (1ULL << 35),
PaysPerMessage = (1ULL << 36),
+ GiftSettings = (1ULL << 37),
// For chats and channels
- InviteLinks = (1ULL << 37),
- Members = (1ULL << 38),
- Admins = (1ULL << 39),
- BannedUsers = (1ULL << 40),
- Rights = (1ULL << 41),
- PendingRequests = (1ULL << 42),
- Reactions = (1ULL << 43),
+ InviteLinks = (1ULL << 38),
+ Members = (1ULL << 39),
+ Admins = (1ULL << 40),
+ BannedUsers = (1ULL << 41),
+ Rights = (1ULL << 42),
+ PendingRequests = (1ULL << 43),
+ Reactions = (1ULL << 44),
// For channels
- ChannelAmIn = (1ULL << 44),
- StickersSet = (1ULL << 45),
- EmojiSet = (1ULL << 46),
- ChannelLinkedChat = (1ULL << 47),
- ChannelLocation = (1ULL << 48),
- Slowmode = (1ULL << 49),
- GroupCall = (1ULL << 50),
+ ChannelAmIn = (1ULL << 45),
+ StickersSet = (1ULL << 46),
+ EmojiSet = (1ULL << 47),
+ ChannelLinkedChat = (1ULL << 48),
+ ChannelLocation = (1ULL << 49),
+ Slowmode = (1ULL << 50),
+ GroupCall = (1ULL << 51),
// For iteration
- LastUsedBit = (1ULL << 50),
+ LastUsedBit = (1ULL << 51),
};
using Flags = base::flags;
friend inline constexpr auto is_flag_type(Flag) { return true; }
diff --git a/Telegram/SourceFiles/data/data_chat_participant_status.cpp b/Telegram/SourceFiles/data/data_chat_participant_status.cpp
index 29b9cb451a..81b3330972 100644
--- a/Telegram/SourceFiles/data/data_chat_participant_status.cpp
+++ b/Telegram/SourceFiles/data/data_chat_participant_status.cpp
@@ -118,7 +118,10 @@ bool CanSendAnyOf(
not_null peer,
ChatRestrictions rights,
bool forbidInForums) {
- if (const auto user = peer->asUser()) {
+ if (peer->session().frozen()
+ && !peer->isFreezeAppealChat()) {
+ return false;
+ } else if (const auto user = peer->asUser()) {
if (user->isInaccessible()
|| user->isRepliesChat()
|| user->isVerifyCodes()) {
@@ -178,7 +181,13 @@ SendError RestrictionError(
not_null peer,
ChatRestriction restriction) {
using Flag = ChatRestriction;
- if (const auto restricted = peer->amRestricted(restriction)) {
+ if (peer->session().frozen()
+ && !peer->isFreezeAppealChat()) {
+ return SendError({
+ .text = tr::lng_frozen_restrict_title(tr::now),
+ .frozen = true,
+ });
+ } else if (const auto restricted = peer->amRestricted(restriction)) {
if (const auto user = peer->asUser()) {
if (user->requiresPremiumToWrite()
&& !user->session().premium()) {
diff --git a/Telegram/SourceFiles/data/data_chat_participant_status.h b/Telegram/SourceFiles/data/data_chat_participant_status.h
index bfa24fb869..b3db584a4e 100644
--- a/Telegram/SourceFiles/data/data_chat_participant_status.h
+++ b/Telegram/SourceFiles/data/data_chat_participant_status.h
@@ -191,16 +191,19 @@ struct SendError {
QString text;
int boostsToLift = 0;
bool premiumToLift = false;
+ bool frozen = false;
};
SendError(Args &&args)
: text(std::move(args.text))
, boostsToLift(args.boostsToLift)
- , premiumToLift(args.premiumToLift) {
+ , premiumToLift(args.premiumToLift)
+ , frozen(args.frozen) {
}
QString text;
int boostsToLift = 0;
bool premiumToLift = false;
+ bool frozen = false;
[[nodiscard]] SendError value_or(SendError other) const {
return *this ? *this : other;
diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp
index 02c1299872..97ef0e6d65 100644
--- a/Telegram/SourceFiles/data/data_media_types.cpp
+++ b/Telegram/SourceFiles/data/data_media_types.cpp
@@ -171,8 +171,19 @@ struct AlbumCounts {
}
template
-[[nodiscard]] uint64 CountCacheKey(not_null data, bool spoiler) {
- return (reinterpret_cast(data.get()) & ~1) | (spoiler ? 1 : 0);
+[[nodiscard]] uint64 CountCacheKey(
+ not_null data,
+ ImageRoundRadius radius,
+ bool spoiler) {
+ return (reinterpret_cast(data.get()) & ~3)
+ | ((radius == ImageRoundRadius::Ellipse) ? 2 : 0)
+ | (spoiler ? 1 : 0);
+}
+
+[[nodiscard]] uint64 SimpleCacheKey(ImageRoundRadius radius, bool spoiler) {
+ return uint64()
+ | ((radius == ImageRoundRadius::Ellipse) ? 2 : 0)
+ | (spoiler ? 1 : 0);
}
[[nodiscard]] ItemPreviewImage PreparePhotoPreviewImage(
@@ -181,7 +192,7 @@ template
ImageRoundRadius radius,
bool spoiler) {
const auto photo = media->owner();
- const auto counted = CountCacheKey(photo, spoiler);
+ const auto counted = CountCacheKey(photo, radius, spoiler);
if (const auto small = media->image(PhotoSize::Small)) {
return { PreparePreviewImage(small, radius, spoiler), counted };
} else if (const auto thumbnail = media->image(PhotoSize::Thumbnail)) {
@@ -191,15 +202,15 @@ template
}
const auto allowedToDownload = media->autoLoadThumbnailAllowed(
item->history()->peer);
- const auto spoilered = uint64(spoiler ? 1 : 0);
- const auto cacheKey = allowedToDownload ? spoilered : counted;
+ const auto simple = SimpleCacheKey(radius, spoiler);
+ const auto cacheKey = allowedToDownload ? simple : counted;
if (allowedToDownload) {
media->owner()->load(PhotoSize::Small, item->fullId());
}
if (const auto blurred = media->thumbnailInline()) {
return { PreparePreviewImage(blurred, radius, spoiler), cacheKey };
}
- return { QImage(), allowedToDownload ? spoilered : cacheKey };
+ return { QImage(), allowedToDownload ? simple : cacheKey };
}
[[nodiscard]] ItemPreviewImage PrepareFilePreviewImage(
@@ -210,7 +221,7 @@ template
Expects(media->owner()->hasThumbnail());
const auto document = media->owner();
- const auto readyCacheKey = CountCacheKey(document, spoiler);
+ const auto readyCacheKey = CountCacheKey(document, radius, spoiler);
if (const auto thumbnail = media->thumbnail()) {
return {
PreparePreviewImage(thumbnail, radius, spoiler),
@@ -218,11 +229,11 @@ template
};
}
document->loadThumbnail(item->fullId());
- const auto spoilered = uint64(spoiler ? 1 : 0);
+ const auto simple = SimpleCacheKey(radius, spoiler);
if (const auto blurred = media->thumbnailInline()) {
- return { PreparePreviewImage(blurred, radius, spoiler), spoilered };
+ return { PreparePreviewImage(blurred, radius, spoiler), simple };
}
- return { QImage(), spoilered };
+ return { QImage(), simple };
}
[[nodiscard]] QImage PutPlayIcon(QImage preview) {
@@ -274,13 +285,14 @@ template
[[nodiscard]] ItemPreviewImage FindCachedPreview(
const std::vector *existing,
not_null data,
+ ImageRoundRadius radius,
bool spoiler) {
if (!existing) {
return {};
}
const auto i = ranges::find(
*existing,
- CountCacheKey(data, spoiler),
+ CountCacheKey(data, radius, spoiler),
&ItemPreviewImage::cacheKey);
return (i != end(*existing)) ? *i : ItemPreviewImage();
}
@@ -856,13 +868,17 @@ ItemPreview MediaPhoto::toPreview(ToPreviewOptions options) const {
}
auto images = std::vector();
auto context = std::any();
- if (auto found = FindCachedPreview(options.existing, _photo, _spoiler)) {
+ const auto radius = _chat
+ ? ImageRoundRadius::Ellipse
+ : ImageRoundRadius::Small;
+ if (auto found = FindCachedPreview(
+ options.existing,
+ _photo,
+ radius,
+ _spoiler)) {
images.push_back(std::move(found));
} else {
const auto media = _photo->createMediaView();
- const auto radius = _chat
- ? ImageRoundRadius::Ellipse
- : ImageRoundRadius::Small;
if (auto prepared = PreparePhotoPreview(
parent(),
media,
@@ -1101,18 +1117,24 @@ ItemPreview MediaFile::toPreview(ToPreviewOptions options) const {
auto images = std::vector