Compare commits
227 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9194c68bd3 | ||
|
|
2dadc9bd7a | ||
|
|
180f83c528 | ||
|
|
dfa7cb1826 | ||
|
|
fdcb28f1a0 | ||
|
|
0e059ec788 | ||
|
|
c681f75ad3 | ||
|
|
9bf40c927e | ||
|
|
df2aeb0c58 | ||
|
|
2dec9c46a7 | ||
|
|
8f8100af3a | ||
|
|
65371ec1b8 | ||
|
|
647d6ae443 | ||
|
|
216692cd9b | ||
|
|
2e5930eb58 | ||
|
|
24b3b2a658 | ||
|
|
e1e286aa13 | ||
|
|
4081ceff22 | ||
|
|
7db57b72f1 | ||
|
|
9e0ca64e02 | ||
|
|
cc55e3b027 | ||
|
|
f78335aa67 | ||
|
|
f283aa033b | ||
|
|
7ff175a81e | ||
|
|
34d2e78308 | ||
|
|
9bd89121e8 | ||
|
|
2e0513a30f | ||
|
|
cf02a4cc31 | ||
|
|
5a1ec3c9e0 | ||
|
|
fa70bf9e0c | ||
|
|
9bd983bb9d | ||
|
|
1618daaeae | ||
|
|
ed4c3cccb2 | ||
|
|
90311dbf24 | ||
|
|
f7a354bfd1 | ||
|
|
a513b1c7b3 | ||
|
|
077e128e9a | ||
|
|
794ad7bda7 | ||
|
|
10906e2e16 | ||
|
|
a5e0b19b79 | ||
|
|
7c6bb132ce | ||
|
|
3ba210b6e4 | ||
|
|
faf090781d | ||
|
|
ab62b1591f | ||
|
|
397e1dde78 | ||
|
|
a935075782 | ||
|
|
588aabc6d7 | ||
|
|
ca47e4ebfd | ||
|
|
58b79ab112 | ||
|
|
cabf35f2b3 | ||
|
|
949104d879 | ||
|
|
101ec9a1c1 | ||
|
|
7cc38f8f6a | ||
|
|
9e73e22e13 | ||
|
|
4c6e1b2b1f | ||
|
|
3db913f15b | ||
|
|
bd1547cd5e | ||
|
|
c7e63ffef5 | ||
|
|
a69304fd25 | ||
|
|
e0c74c9546 | ||
|
|
2f816942b8 | ||
|
|
9fd8b040b7 | ||
|
|
f5a405e6f1 | ||
|
|
c79561e97f | ||
|
|
38a53687a0 | ||
|
|
94e43f8f8a | ||
|
|
7b4393ba48 | ||
|
|
56cb5ac9c6 | ||
|
|
76cafc5059 | ||
|
|
48bd693679 | ||
|
|
f32af6999b | ||
|
|
ac99784bf7 | ||
|
|
d94ef82327 | ||
|
|
06d4ea2975 | ||
|
|
b79ddb7a1c | ||
|
|
58a592ba47 | ||
|
|
9344504781 | ||
|
|
f7543e3261 | ||
|
|
0402b4f5f4 | ||
|
|
d5c5549c1a | ||
|
|
21d2f6a44f | ||
|
|
0ecef54e2b | ||
|
|
f6eccf85dc | ||
|
|
28f7dc73a5 | ||
|
|
8d43bdb084 | ||
|
|
8550099110 | ||
|
|
921c27c9b1 | ||
|
|
148c04fb41 | ||
|
|
eaf91bba58 | ||
|
|
da0d78135d | ||
|
|
f38fad2f92 | ||
|
|
73e550f432 | ||
|
|
8b96f7214e | ||
|
|
8202a1633b | ||
|
|
7013a0dfef | ||
|
|
0c43aabfec | ||
|
|
1a7353fb43 | ||
|
|
4d3e7ac30c | ||
|
|
7d342b9c6d | ||
|
|
e1709c11da | ||
|
|
6d3a6d20b5 | ||
|
|
91a6853f3c | ||
|
|
60d886a59a | ||
|
|
397797aac7 | ||
|
|
61461d0a87 | ||
|
|
0ae661edf0 | ||
|
|
fc6aa288c2 | ||
|
|
58dcba71a4 | ||
|
|
5ca3a81fe2 | ||
|
|
f316e3bd17 | ||
|
|
ebb10fb8ed | ||
|
|
d08dbb835f | ||
|
|
0d38106ed0 | ||
|
|
bca0e1e16c | ||
|
|
96d1fe336a | ||
|
|
305e15dd03 | ||
|
|
22287d4c03 | ||
|
|
341b44119f | ||
|
|
0798a0148a | ||
|
|
51c0df79fe | ||
|
|
42febdb240 | ||
|
|
5fe1175602 | ||
|
|
bf57a1506f | ||
|
|
7b496b3741 | ||
|
|
197cdc3928 | ||
|
|
8d14112c5a | ||
|
|
61659244b7 | ||
|
|
19023b4cc2 | ||
|
|
5dcf341aaa | ||
|
|
4993ff1921 | ||
|
|
d1536d0572 | ||
|
|
836fe119d9 | ||
|
|
0b3644b334 | ||
|
|
7357119b1a | ||
|
|
545915e481 | ||
|
|
6f90dc2374 | ||
|
|
91dcfff423 | ||
|
|
58b4798b79 | ||
|
|
843d63c221 | ||
|
|
3b864d63b9 | ||
|
|
2a51e2aa59 | ||
|
|
67f2daa43c | ||
|
|
c3db57a4fc | ||
|
|
885b82b437 | ||
|
|
6487d91722 | ||
|
|
5b4f70ff96 | ||
|
|
75fdd5315f | ||
|
|
8ee5c70708 | ||
|
|
b398444b91 | ||
|
|
9e6f2a5d2e | ||
|
|
7245319351 | ||
|
|
82912f4a0b | ||
|
|
1968ca07de | ||
|
|
8c04bed572 | ||
|
|
ae56c5266f | ||
|
|
0a9db8533b | ||
|
|
85e234938d | ||
|
|
816ee794e8 | ||
|
|
624f33c5e2 | ||
|
|
693c30d264 | ||
|
|
17e08f9291 | ||
|
|
cedf8a65e7 | ||
|
|
0a39e7e2b1 | ||
|
|
5c87b42135 | ||
|
|
e39b95175b | ||
|
|
1791b251ad | ||
|
|
507b7d7193 | ||
|
|
839e59075d | ||
|
|
4962fdf5ae | ||
|
|
fee8690ca6 | ||
|
|
25a718c54b | ||
|
|
401bc86f27 | ||
|
|
c3ad0ae129 | ||
|
|
8fe56b9a7d | ||
|
|
1b649299ff | ||
|
|
6ba57e713e | ||
|
|
758cf0388e | ||
|
|
9de95cee23 | ||
|
|
b35d2505a4 | ||
|
|
240ced395b | ||
|
|
9e8e49b8d9 | ||
|
|
b76bfe2008 | ||
|
|
3dd26dac6e | ||
|
|
04e587b999 | ||
|
|
adcecaa195 | ||
|
|
6fe0fe6fd6 | ||
|
|
7fdac9cd94 | ||
|
|
5c0a1bafe2 | ||
|
|
7d2d5c6100 | ||
|
|
513a9f8d45 | ||
|
|
330b4a0b00 | ||
|
|
8ae159dd66 | ||
|
|
2de96682db | ||
|
|
80273c57d0 | ||
|
|
fe3c33fb52 | ||
|
|
c9a26fd006 | ||
|
|
11d4c50202 | ||
|
|
7dd50fa931 | ||
|
|
5d0e89db5d | ||
|
|
d9785f6071 | ||
|
|
f3e65d400d | ||
|
|
85e6f55536 | ||
|
|
b6046d829f | ||
|
|
665a1acfd8 | ||
|
|
d51fd7b3ad | ||
|
|
b94099e25b | ||
|
|
5fc4f4ed36 | ||
|
|
d47a38dfcf | ||
|
|
f5353080e7 | ||
|
|
6fb980ca79 | ||
|
|
3f0b57ec11 | ||
|
|
f5dfeb0c50 | ||
|
|
139d4e72b5 | ||
|
|
2334ba1fe1 | ||
|
|
110e7c8074 | ||
|
|
f643446d1b | ||
|
|
a813793007 | ||
|
|
972fdb5c76 | ||
|
|
0e4b057220 | ||
|
|
6869cc7d04 | ||
|
|
68ddabea5c | ||
|
|
60c84bbf51 | ||
|
|
4c61f27826 | ||
|
|
3f3b9f3608 | ||
|
|
2eff766e88 | ||
|
|
8b54910538 | ||
|
|
66662e02a6 |
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -21,7 +21,7 @@ Tell us what happens instead
|
||||
|
||||
**Used theme**:
|
||||
|
||||
<details><summary>**Logs**:</summary>
|
||||
<details><summary><b>Logs</b>:</summary>
|
||||
Insert logs here (if necessary)
|
||||
|
||||
<!-- You can type `debugmode` in settings and then see ~/.TelegramDesktop/DebugLogs/log_...txt for log files.
|
||||
|
||||
@@ -28,14 +28,15 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
||||
* liblzma ([public domain](http://tukaani.org/xz/))
|
||||
* Google Breakpad ([License](https://chromium.googlesource.com/breakpad/breakpad/+/master/LICENSE))
|
||||
* Google Crashpad ([Apache License 2.0](https://chromium.googlesource.com/crashpad/crashpad/+/master/LICENSE))
|
||||
* GYP ([BSD license](https://github.com/bnoordhuis/gyp/blob/master/LICENSE))
|
||||
* GYP ([BSD License](https://github.com/bnoordhuis/gyp/blob/master/LICENSE))
|
||||
* Ninja ([Apache License 2.0](https://github.com/ninja-build/ninja/blob/master/COPYING))
|
||||
* OpenAL Soft ([LGPL](http://kcat.strangesoft.net/openal.html))
|
||||
* Opus codec ([BSD license](http://www.opus-codec.org/license/))
|
||||
* Opus codec ([BSD License](http://www.opus-codec.org/license/))
|
||||
* FFmpeg ([LGPL](https://www.ffmpeg.org/legal.html))
|
||||
* Guideline Support Library ([MIT License](https://github.com/Microsoft/GSL/blob/master/LICENSE))
|
||||
* Mapbox Variant ([BSD license](https://github.com/mapbox/variant/blob/master/LICENSE))
|
||||
* Mapbox Variant ([BSD License](https://github.com/mapbox/variant/blob/master/LICENSE))
|
||||
* Open Sans font ([Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html))
|
||||
* Emoji alpha codes ([MIT License](https://github.com/emojione/emojione/blob/master/extras/alpha-codes/LICENSE.md))
|
||||
|
||||
## Build instructions
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 3.2 MiB |
@@ -116,7 +116,7 @@ msgReplyBarPos: point(1px, 0px);
|
||||
msgReplyBarSize: size(2px, 36px);
|
||||
msgReplyBarSkip: 10px;
|
||||
msgServicePadding: margins(12px, 3px, 12px, 4px);
|
||||
msgServiceMargin: margins(10px, 10px, 80px, 2px);
|
||||
msgServiceMargin: margins(10px, 10px, 10px, 2px);
|
||||
|
||||
msgDateSpace: 12px;
|
||||
msgDateDelta: point(2px, 5px);
|
||||
@@ -239,7 +239,7 @@ dragPadding: margins(20px, 10px, 20px, 10px);
|
||||
dragHeight: 72px;
|
||||
|
||||
minPhotoSize: 100px;
|
||||
maxMediaSize: 420px;
|
||||
maxMediaSize: 430px;
|
||||
maxStickerSize: 256px;
|
||||
maxGifSize: 320px;
|
||||
maxSignatureSize: 144px;
|
||||
|
||||
@@ -93,8 +93,13 @@ placeholderFg: windowSubTextFg; // default input field placeholder when field is
|
||||
placeholderFgActive: #aaaaaa; // default input field placeholder when field is focused
|
||||
inputBorderFg: #e0e0e0; // default input field bottom border (like in code input field when you log in and field is not focused)
|
||||
filterInputBorderFg: #54c3f3; // default rounded input field border (like in chats list search field when field is focused)
|
||||
filterInputInactiveBg: windowBgOver; // default rounded input field background (like in chats list search field when field is inactive)
|
||||
checkboxFg: #b3b3b3; // default unchecked checkbox rounded rectangle (and also emoji category icons)
|
||||
filterInputActiveBg: windowBg; // default rounded input field active background (like in chats list search field when field is focused)
|
||||
filterInputInactiveBg: windowBgOver; // default rounded input field inactive background (like in chats list search field when field is inactive)
|
||||
checkboxFg: #b3b3b3; // default unchecked checkbox rounded rectangle
|
||||
|
||||
botKbBg: menuBgOver; // bot keyboard button background
|
||||
botKbDownBg: menuBgRipple; // bot keyboard button ripple effect
|
||||
botKbColor: windowBoldFgOver; // bot keyboard button text
|
||||
|
||||
sliderBgInactive: #e1eaef; // default slider not active bar (like in Settings when you choose interface scale or custom notifications count)
|
||||
sliderBgActive: windowBgActive; // default slider active bar (like in Settings when you choose interface scale or custom notifications count)
|
||||
@@ -232,8 +237,8 @@ dialogsUnreadBgActive: dialogsTextFgActive; // chat list unread badge background
|
||||
dialogsUnreadBgMutedActive: dialogsDraftFgActive; // chat list unread badge background for muted chat for current (active) chat
|
||||
dialogsUnreadFgActive: dialogsBgActive; // chat list unread badge text for current (active) chat
|
||||
|
||||
dialogsRippleBg: windowBgRipple;
|
||||
dialogsRippleBgActive: activeButtonBgRipple;
|
||||
dialogsRippleBg: windowBgRipple; // chat list background ripple effect
|
||||
dialogsRippleBgActive: activeButtonBgRipple; // chat list background ripple effect for current (active) chat
|
||||
|
||||
dialogsForwardBg: dialogsBgActive; // forwarding panel background (when forwarding messages in the smallest window size)
|
||||
dialogsForwardFg: dialogsNameFgActive; // forwarding panel text (when forwarding messages in the smallest window size)
|
||||
@@ -248,6 +253,8 @@ emojiPanBg: windowBg; // emoji panel background
|
||||
emojiPanCategories: #f7f7f7 | windowBg; // emoji panel categories background
|
||||
emojiPanHeaderFg: windowSubTextFg; // emoji panel section header text
|
||||
emojiPanHeaderBg: #fffffff2 | emojiPanBg; // emoji panel section header background
|
||||
emojiIconFg: checkboxFg; // emoji category icon
|
||||
emojiIconFgActive: windowBgActive; // active emoji category icon
|
||||
stickerPanDeleteBg: #000000cc; // delete X button background for custom sent stickers in stickers panel (legacy)
|
||||
stickerPanDeleteFg: windowFgActive; // delete X button icon for custom sent stickers in stickers panel (legacy)
|
||||
stickerPreviewBg: #ffffffb0; // sticker and GIF preview background (when you press and hold on a sticker)
|
||||
@@ -450,7 +457,9 @@ historyComposeButtonBgOver: windowBgOver; // unblock / join channel / mute chann
|
||||
historyComposeButtonBgRipple: windowBgRipple; // unblock / join channel / mute channel button ripple effect
|
||||
|
||||
// overview
|
||||
overviewCheckBg: #00000040; // shared files / links checkbox background for not selected rows when some rows are selected
|
||||
overviewCheckBg: #00000040; // shared media / files / links checkbox background for not selected rows when some rows are selected
|
||||
overviewCheckBgActive: windowBgActive; // shared media / files / links checkbox background for selected rows
|
||||
overviewCheckBorder: windowBg; // shared media round checkbox border
|
||||
overviewCheckFg: windowBg; // shared files / links checkbox icon for not selected rows when some rows are selected
|
||||
overviewCheckFgActive: windowBg; // shared files / links checkbox icon for selected rows
|
||||
overviewPhotoSelectOverlay: #40ace333; // shared photos / videos / links fill for selected rows
|
||||
@@ -459,7 +468,10 @@ overviewPhotoSelectOverlay: #40ace333; // shared photos / videos / links fill fo
|
||||
profileStatusFgOver: #7c99b2; // group members list in group profile user last seen text with mouse over
|
||||
profileVerifiedCheckBg: windowBgActive; // profile verified check icon background
|
||||
profileVerifiedCheckFg: windowFgActive; // profile verified check icon tick
|
||||
profileAdminStartFg: windowBgActive; // group members list admin star icon
|
||||
profileAdminStartFg: windowBgActive; // group members list creator star icon
|
||||
profileAdminStarFgOver: profileAdminStartFg; // group members list creator star icon with mouse over
|
||||
profileOtherAdminStarFg: windowSubTextFg; // group members list admin star icon
|
||||
profileOtherAdminStarFgOver: profileStatusFgOver; // group members list admin star icon with mouse over
|
||||
|
||||
// settings
|
||||
notificationsBoxMonitorFg: windowFg; // custom notifications settings box monitor color
|
||||
|
||||
15998
Telegram/Resources/emoji_autocomplete.json
Normal file
BIN
Telegram/Resources/icons/fast_share.png
Normal file
|
After Width: | Height: | Size: 330 B |
BIN
Telegram/Resources/icons/fast_share@2x.png
Normal file
|
After Width: | Height: | Size: 661 B |
BIN
Telegram/Resources/icons/menu_night_mode.png
Normal file
|
After Width: | Height: | Size: 489 B |
BIN
Telegram/Resources/icons/menu_night_mode@2x.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
@@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_menu_update" = "Update";
|
||||
"lng_menu_restart" = "Restart";
|
||||
"lng_menu_back" = "Back";
|
||||
"lng_menu_night_mode" = "Night mode";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Disable notifications";
|
||||
"lng_enable_notifications_from_tray" = "Enable notifications";
|
||||
@@ -88,7 +89,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_continue" = "Continue";
|
||||
"lng_close" = "Close";
|
||||
"lng_connecting" = "Connecting...";
|
||||
"lng_reconnecting" = "Reconnect {count:now|in # s|in # s}...";
|
||||
"lng_connecting_to_proxy" = "Connecting to proxy...";
|
||||
"lng_connecting_settings" = "Settings";
|
||||
"lng_reconnecting#one" = "Reconnect in {count} s...";
|
||||
"lng_reconnecting#other" = "Reconnect in {count} s...";
|
||||
"lng_reconnecting_try_now" = "Try now";
|
||||
|
||||
"lng_status_service_notifications" = "service notifications";
|
||||
@@ -102,8 +106,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_last_month" = "last seen within a month";
|
||||
"lng_status_invisible" = "invisible";
|
||||
"lng_status_lastseen_now" = "last seen just now";
|
||||
"lng_status_lastseen_minutes" = "last seen {count:_not_used_|# minute|# minutes} ago";
|
||||
"lng_status_lastseen_hours" = "last seen {count:_not_used_|# hour|# hours} ago";
|
||||
"lng_status_lastseen_minutes#one" = "last seen {count} minute ago";
|
||||
"lng_status_lastseen_minutes#other" = "last seen {count} minutes ago";
|
||||
"lng_status_lastseen_hours#one" = "last seen {count} hour ago";
|
||||
"lng_status_lastseen_hours#other" = "last seen {count} hours ago";
|
||||
"lng_status_lastseen_today" = "last seen today at {time}";
|
||||
"lng_status_lastseen_yesterday" = "last seen yesterday at {time}";
|
||||
"lng_status_lastseen_date" = "last seen {date}";
|
||||
@@ -112,24 +118,43 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_connecting" = "connecting...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "group is inaccessible";
|
||||
"lng_chat_status_members" = "{count:no members|# member|# members}";
|
||||
"lng_chat_status_members_online" = "{count:_not_used_|# member|# members}, {count_online:_not_used_|# online|# online}";
|
||||
"lng_chat_status_no_members" = "no members";
|
||||
"lng_chat_status_members#one" = "{count} member";
|
||||
"lng_chat_status_members#other" = "{count} members";
|
||||
"lng_chat_status_online#one" = "{count} online";
|
||||
"lng_chat_status_online#other" = "{count} online";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
|
||||
"lng_channel_status" = "channel";
|
||||
"lng_group_status" = "group";
|
||||
|
||||
"lng_channel_members_link" = "{count:_not_used_|# member|# members}";
|
||||
"lng_channel_admins_link" = "{count:_not_used_|# administrator|# administrators}";
|
||||
"lng_channel_members_link#one" = "{count} member";
|
||||
"lng_channel_members_link#other" = "{count} members";
|
||||
"lng_channel_admins_link#one" = "{count} administrator";
|
||||
"lng_channel_admins_link#other" = "{count} administrators";
|
||||
|
||||
"lng_server_error" = "Internal server error.";
|
||||
"lng_flood_error" = "Too many tries. Please try again later.";
|
||||
"lng_gif_error" = "An error has occured while reading GIF animation :(";
|
||||
"lng_gif_error" = "An error has occurred while reading GIF animation :(";
|
||||
"lng_edit_error" = "You cannot edit this message";
|
||||
"lng_join_channel_error" = "Sorry, you have joined too many channels and supergroups. Please leave some before joining.";
|
||||
"lng_error_phone_flood" = "Sorry, you have deleted and re-created your account too many times recently. Please wait for a few days before signing up again.";
|
||||
"lng_error_start_minimized_passcoded" = "You have set a local passcode, so the app can't be launched minimized. App will ask you to enter the passcode before it can start working.";
|
||||
"lng_error_pinned_max" = "Sorry, you can pin no more than {count:_not_used_|# chat|# chats} to the top.";
|
||||
"lng_error_pinned_max#one" = "Sorry, you can pin no more than {count} chat to the top.";
|
||||
"lng_error_pinned_max#other" = "Sorry, you can pin no more than {count} chats to the top.";
|
||||
"lng_error_public_groups_denied" = "Unfortunately, you were banned from participating in public groups.\n{more_info}";
|
||||
"lng_error_cant_edit_admin" = "Sorry, you can't edit permissions for this admin.";
|
||||
"lng_error_cant_add_member" = "Sorry, you can't add the bot to this group. Ask a group admin to do it.";
|
||||
"lng_error_cant_add_bot" = "Sorry, this bot can't be added to groups.";
|
||||
"lng_error_cant_add_admin_invite" = "Sorry, you can't add this user as an admin because they are not a member of this group and you are not allowed to invite them.";
|
||||
"lng_error_cant_add_admin_unban" = "Sorry, you can't add this user as an admin because they are in the blacklist and you can't unban them.";
|
||||
"lng_error_cant_ban_admin" = "Sorry, you can't ban this user because they are an admin in this group and you are not allowed to demote them.";
|
||||
"lng_sure_add_admin_invite" = "This user is not a member of this group. Add them to the group and promote them to admin?";
|
||||
"lng_sure_add_admin_unban" = "This user is currently restricted or banned in this group. Are you sure you want to unban and promote them?";
|
||||
"lng_sure_ban_admin" = "This user is an admin in this group. Are you sure you want to go ahead and restrict them?";
|
||||
"lng_sure_ban_user_group" = "Ban {user} in the group?";
|
||||
"lng_sure_enable_socks" = "Are you sure you want to enable this proxy?\n\nServer: {server}\nPort: {port}\n\nYou can change your proxy server later in the Settings (Connection Type).";
|
||||
"lng_sure_enable" = "Enable";
|
||||
|
||||
"lng_edit_deleted" = "This message was deleted";
|
||||
"lng_edit_too_long" = "Your message text is too long";
|
||||
@@ -198,9 +223,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_signin_sure_reset" = "Warning!\n\nYou will lose all your chats and messages, along with any media and files you shared!\n\nDo you want to reset your account?";
|
||||
"lng_signin_reset" = "Reset";
|
||||
"lng_signin_reset_wait" = "Since the account {phone_number} is active and protected by a password, we will delete it in 1 week for security purposes. You can cancel this process at any time.\n\nYou’ll be able to reset your account in:\n{when}";
|
||||
"lng_signin_reset_in_days" = "{count_days:0 days|# day|# days} {count_hours:0 hours|# hour|# hours} {count_minutes:0 minutes|# minute|# minutes}";
|
||||
"lng_signin_reset_in_hours" = "{count_hours:0 hours|# hour|# hours} {count_minutes:0 minutes|# minute|# minutes}";
|
||||
"lng_signin_reset_in_minutes" = "{count_minutes:0 minutes|# minute|# minutes}";
|
||||
"lng_signin_reset_days#one" = "{count} day";
|
||||
"lng_signin_reset_days#other" = "{count} days";
|
||||
"lng_signin_reset_hours#one" = "{count} hour";
|
||||
"lng_signin_reset_hours#other" = "{count} hours";
|
||||
"lng_signin_reset_minutes#one" = "{count} minute";
|
||||
"lng_signin_reset_minutes#other" = "{count} minutes";
|
||||
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
|
||||
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
|
||||
"lng_signin_reset_cancelled" = "Your recent attempts to reset this account have been cancelled by its active user. Please try again in 7 days.";
|
||||
|
||||
"lng_signup_title" = "Your Info";
|
||||
@@ -223,7 +253,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_settings_save" = "Save";
|
||||
"lng_settings_upload" = "Set Profile Photo";
|
||||
"lng_settings_crop_profile" = "Select a square area for your profile photo";
|
||||
"lng_settings_crop_profile" = "Select an area for your profile photo";
|
||||
"lng_settings_uploading_photo" = "Uploading photo...";
|
||||
"lng_settings_edit" = "Edit";
|
||||
"lng_settings_drop_area_subtitle" = "to set it as your photo";
|
||||
@@ -241,10 +271,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_username_link" = "This link opens a chat with you:";
|
||||
"lng_username_copied" = "Link copied to clipboard.";
|
||||
|
||||
"lng_bio_title" = "Edit your bio";
|
||||
"lng_bio_placeholder" = "Bio";
|
||||
"lng_bio_about" = "You can add a few lines about yourself. Anyone who opens your profile will see this text.";
|
||||
|
||||
"lng_settings_section_info" = "Info";
|
||||
"lng_settings_phone_number" = "Phone number:";
|
||||
"lng_settings_username" = "Username:";
|
||||
"lng_settings_choose_username" = "Choose username";
|
||||
"lng_settings_empty_bio" = "None";
|
||||
|
||||
"lng_settings_section_notify" = "Notifications";
|
||||
"lng_settings_desktop_notify" = "Desktop notifications";
|
||||
@@ -303,7 +338,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_backgrounds_header" = "Choose your new chat background";
|
||||
"lng_theme_sure_keep" = "Keep this color theme?";
|
||||
"lng_theme_reverting" = "Reverting to the old color theme in {count:_not_used_|# second|# seconds}.";
|
||||
"lng_theme_reverting#one" = "Reverting to the old color theme in {count} second.";
|
||||
"lng_theme_reverting#other" = "Reverting to the old color theme in {count} seconds.";
|
||||
"lng_theme_keep_changes" = "Keep changes";
|
||||
"lng_theme_revert" = "Revert";
|
||||
|
||||
@@ -329,14 +365,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_local_storage_title" = "Local storage";
|
||||
"lng_settings_no_data_cached" = "No cached data found!";
|
||||
"lng_settings_images_cached" = "{count:_not_used_|# image|# images}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|# voice message|# voice messages}, {size}";
|
||||
"lng_settings_images_cached#one" = "{count} image, {size}";
|
||||
"lng_settings_images_cached#other" = "{count} images, {size}";
|
||||
"lng_settings_audios_cached#one" = "{count} voice message, {size}";
|
||||
"lng_settings_audios_cached#other" = "{count} voice messages, {size}";
|
||||
"lng_local_storage_clear" = "Clear all";
|
||||
"lng_local_storage_clearing" = "Clearing...";
|
||||
"lng_local_storage_cleared" = "Cleared!";
|
||||
"lng_local_storage_clear_failed" = "Clear failed :(";
|
||||
|
||||
"lng_settings_section_advanced_settings" = "Advanced Settings";
|
||||
"lng_settings_enable_night_theme" = "Enable night mode";
|
||||
"lng_settings_disable_night_theme" = "Disable night mode";
|
||||
|
||||
"lng_passcode_remove_button" = "Remove";
|
||||
|
||||
@@ -348,8 +388,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_passcode_autolock" = "Auto-Lock";
|
||||
"lng_passcode_autolock_away" = "Auto-Lock if away for:";
|
||||
"lng_passcode_autolock_inactive" = "Auto-Lock if inactive for:";
|
||||
"lng_passcode_autolock_minutes" = "{count:_not_used_|# minute|# minutes}";
|
||||
"lng_passcode_autolock_hours" = "{count:_not_used_|# hour|# hours}";
|
||||
"lng_passcode_autolock_minutes#one" = "{count} minute";
|
||||
"lng_passcode_autolock_minutes#other" = "{count} minutes";
|
||||
"lng_passcode_autolock_hours#one" = "{count} hour";
|
||||
"lng_passcode_autolock_hours#other" = "{count} hours";
|
||||
"lng_passcode_enter_old" = "Enter current passcode";
|
||||
"lng_passcode_enter_first" = "Enter a passcode";
|
||||
"lng_passcode_enter_new" = "Enter new passcode";
|
||||
@@ -455,32 +497,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_privacy_lastseen_title" = "Last seen privacy";
|
||||
"lng_edit_privacy_lastseen_description" = "You can choose who can see your last seen time:";
|
||||
"lng_edit_privacy_lastseen_warning" = "Important: you won't be able to see Last Seen times for people with whom you don't share your Last Seen time. Approximate last seen will be shown instead (recently, within a week, within a month).";
|
||||
"lng_edit_privacy_lastseen_always" = "Always share with{count:| # user| # users}";
|
||||
"lng_edit_privacy_lastseen_never" = "Never share with{count:| # user| # users}";
|
||||
"lng_edit_privacy_lastseen_always_empty" = "Always share with";
|
||||
"lng_edit_privacy_lastseen_always#one" = "Always share with {count} user";
|
||||
"lng_edit_privacy_lastseen_always#other" = "Always share with {count} users";
|
||||
"lng_edit_privacy_lastseen_never_empty" = "Never share with";
|
||||
"lng_edit_privacy_lastseen_never#one" = "Never share with {count} user";
|
||||
"lng_edit_privacy_lastseen_never#other" = "Never share with {count} users";
|
||||
"lng_edit_privacy_lastseen_exceptions" = "These settings will override the values above.";
|
||||
"lng_edit_privacy_lastseen_always_title" = "Always share with";
|
||||
"lng_edit_privacy_lastseen_never_title" = "Never share with";
|
||||
|
||||
"lng_edit_privacy_groups_title" = "Group invite settings";
|
||||
"lng_edit_privacy_groups_description" = "You can choose who can add you to groups and channels with granular precision:";
|
||||
"lng_edit_privacy_groups_always" = "Always allow{count:| # user| # users}";
|
||||
"lng_edit_privacy_groups_never" = "Never allow{count:| # user| # users}";
|
||||
"lng_edit_privacy_groups_always_empty" = "Always allow";
|
||||
"lng_edit_privacy_groups_always#one" = "Always allow {count} user";
|
||||
"lng_edit_privacy_groups_always#other" = "Always allow {count} users";
|
||||
"lng_edit_privacy_groups_never_empty" = "Never allow";
|
||||
"lng_edit_privacy_groups_never#one" = "Never allow {count} user";
|
||||
"lng_edit_privacy_groups_never#other" = "Never allow {count} users";
|
||||
"lng_edit_privacy_groups_exceptions" = "These users will or will not be able to add you to groups and channels regardless of the settings above.";
|
||||
"lng_edit_privacy_groups_always_title" = "Always allow";
|
||||
"lng_edit_privacy_groups_never_title" = "Never allow";
|
||||
|
||||
"lng_edit_privacy_calls_title" = "Phone calls privacy";
|
||||
"lng_edit_privacy_calls_description" = "You can restrict who can call you:";
|
||||
"lng_edit_privacy_calls_always" = "Always allow{count:| # user| # users}";
|
||||
"lng_edit_privacy_calls_never" = "Never allow{count:| # user| # users}";
|
||||
"lng_edit_privacy_calls_always_empty" = "Always allow";
|
||||
"lng_edit_privacy_calls_always#one" = "Always allow {count} user";
|
||||
"lng_edit_privacy_calls_always#other" = "Always allow {count} users";
|
||||
"lng_edit_privacy_calls_never_empty" = "Never allow";
|
||||
"lng_edit_privacy_calls_never#one" = "Never allow {count} user";
|
||||
"lng_edit_privacy_calls_never#other" = "Never allow {count} users";
|
||||
"lng_edit_privacy_calls_exceptions" = "These users will or will not be able to call you regardless of the settings above.";
|
||||
"lng_edit_privacy_calls_always_title" = "Always allow";
|
||||
"lng_edit_privacy_calls_never_title" = "Never allow";
|
||||
|
||||
"lng_self_destruct_title" = "Account self-destruction";
|
||||
"lng_self_destruct_description" = "If you don't come online at least once within this period, your account will be deleted along with all groups, messages and contacts.";
|
||||
"lng_self_destruct_months" = "{count:_not_used_|# month|# months}";
|
||||
"lng_self_destruct_years" = "{count:_not_used_|# year|# years}";
|
||||
"lng_self_destruct_months#one" = "{count} month";
|
||||
"lng_self_destruct_months#other" = "{count} months";
|
||||
"lng_self_destruct_years#one" = "{count} year";
|
||||
"lng_self_destruct_years#other" = "{count} years";
|
||||
|
||||
"lng_change_phone_title" = "Change phone number";
|
||||
"lng_change_phone_description" = "You can change your Telegram number\nhere. Your account and all your cloud data\n— messages, media, contacts, etc. will be\nmoved to the new number.\n\n[b]Important[/b]: all your Telegram contacts will\nget your [b]new number[/b] added to their address\nbook, provided they had your old number and\nyou haven't blocked them in Telegram.";
|
||||
@@ -506,15 +562,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_link_section" = "Invite link";
|
||||
"lng_profile_create_public_link" = "Create public link";
|
||||
"lng_profile_edit_public_link" = "Edit public link";
|
||||
"lng_profile_search_members" = "Search members";
|
||||
"lng_profile_manage_admins" = "Manage administrators";
|
||||
"lng_profile_manage_blocklist" = "Manage blocked users";
|
||||
"lng_profile_common_groups" = "{count:_not_used_|# group|# groups} in common";
|
||||
"lng_profile_manage_blocklist" = "Manage banned users";
|
||||
"lng_profile_manage_restrictedlist" = "Manage restricted users";
|
||||
"lng_profile_recent_actions" = "Recent actions";
|
||||
"lng_profile_common_groups#one" = "{count} group in common";
|
||||
"lng_profile_common_groups#other" = "{count} groups in common";
|
||||
"lng_profile_common_groups_section" = "Groups in common";
|
||||
"lng_profile_participants_section" = "Members";
|
||||
"lng_profile_info_section" = "Info";
|
||||
"lng_profile_mobile_number" = "Mobile:";
|
||||
"lng_profile_username" = "Username:";
|
||||
"lng_profile_link" = "Link:";
|
||||
"lng_profile_bio" = "Bio:";
|
||||
"lng_profile_add_contact" = "Add Contact";
|
||||
"lng_profile_edit_contact" = "Edit";
|
||||
"lng_profile_enable_notifications" = "Notifications";
|
||||
@@ -542,23 +603,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_delete_and_exit" = "Leave";
|
||||
"lng_profile_kick" = "Remove";
|
||||
"lng_profile_admin" = "admin";
|
||||
"lng_profile_edit_permissions" = "Edit";
|
||||
"lng_profile_sure_kick" = "Remove {user} from the group?";
|
||||
"lng_profile_sure_kick_channel" = "Remove {user} from the channel?";
|
||||
"lng_profile_sure_kick_admin" = "Remove {user} from administrators?";
|
||||
"lng_profile_loading" = "Loading...";
|
||||
"lng_profile_shared_media" = "Shared media";
|
||||
"lng_profile_no_media" = "No media in this conversation.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# photo|# photos}";
|
||||
"lng_profile_photos#one" = "{count} photo";
|
||||
"lng_profile_photos#other" = "{count} photos";
|
||||
"lng_profile_photos_header" = "Photos";
|
||||
"lng_profile_videos" = "{count:_not_used_|# video|# videos}";
|
||||
"lng_profile_videos#one" = "{count} video";
|
||||
"lng_profile_videos#other" = "{count} videos";
|
||||
"lng_profile_videos_header" = "Videos";
|
||||
"lng_profile_songs" = "{count:_not_used_|# audio file|# audio files}";
|
||||
"lng_profile_songs#one" = "{count} audio file";
|
||||
"lng_profile_songs#other" = "{count} audio files";
|
||||
"lng_profile_songs_header" = "Audio files";
|
||||
"lng_profile_files" = "{count:_not_used_|# file|# files}";
|
||||
"lng_profile_files#one" = "{count} file";
|
||||
"lng_profile_files#other" = "{count} files";
|
||||
"lng_profile_files_header" = "Files";
|
||||
"lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages}";
|
||||
"lng_profile_audios#one" = "{count} voice message";
|
||||
"lng_profile_audios#other" = "{count} voice messages";
|
||||
"lng_profile_audios_header" = "Voice messages";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links}";
|
||||
"lng_profile_shared_links#one" = "{count} shared link";
|
||||
"lng_profile_shared_links#other" = "{count} shared links";
|
||||
"lng_profile_shared_links_header" = "Shared links";
|
||||
"lng_profile_copy_phone" = "Copy Phone Number";
|
||||
"lng_profile_copy_fullname" = "Copy Name";
|
||||
@@ -578,16 +646,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_report_button" = "Report";
|
||||
"lng_report_thanks" = "Thank you! Your report will be reviewed by our team very soon.";
|
||||
|
||||
"lng_channel_add_admins" = "New administrator";
|
||||
"lng_channel_add_members" = "Add members";
|
||||
"lng_channel_add_banned" = "Ban user";
|
||||
"lng_channel_add_restricted" = "Restrict user";
|
||||
"lng_channel_members" = "Members";
|
||||
"lng_channel_only_last_shown" = "Only the last {count:_not_used_|# member is|# members are} shown here";
|
||||
"lng_channel_only_last_shown#one" = "Only the last {count} member is shown here";
|
||||
"lng_channel_only_last_shown#other" = "Only the last {count} members are shown here";
|
||||
"lng_channel_admins" = "Administrators";
|
||||
"lng_channel_add_admin" = "Add Administrator";
|
||||
"lng_channel_admin_sure" = "Add {user} to administrators?";
|
||||
"lng_channel_admins_too_much" = "Sorry, you have reached the limit of the administrators. Please remove one administrator first.";
|
||||
"lng_channel_admin_status_creator" = "Creator";
|
||||
"lng_channel_admin_status_promoted_by" = "Promoted by {user}";
|
||||
"lng_channel_admin_status_not_admin" = "Not administrator";
|
||||
|
||||
"lng_group_blocked_list_about" = "Blocked users are removed from the group and can only come back if invited by an admin.\nInvite links don't work for them.";
|
||||
"lng_group_blocked_list_about" = "Banned users are removed from the group and can only come back if invited by an admin.\nInvite links don't work for them.";
|
||||
|
||||
"lng_chat_all_members_admins" = "All Members Are Admins";
|
||||
"lng_chat_about_all_admins" = "Group members can add new members, edit name and photo of the group.";
|
||||
@@ -595,7 +667,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_participant_filter" = "Search";
|
||||
"lng_participant_invite" = "Invite";
|
||||
"lng_participant_invite_sorry" = "Sorry, you can only add the first {count:_not_used|# member|# members} to a channel personally.\n\nFrom now on, people will need to join via your invite link.";
|
||||
"lng_participant_invite_sorry#one" = "Sorry, you can only add the first {count} member to a channel personally.\n\nFrom now on, people will need to join via your invite link.";
|
||||
"lng_participant_invite_sorry#other" = "Sorry, you can only add the first {count} members to a channel personally.\n\nFrom now on, people will need to join via your invite link.";
|
||||
"lng_create_group_back" = "Back";
|
||||
"lng_create_group_next" = "Next";
|
||||
"lng_create_group_create" = "Create";
|
||||
@@ -618,8 +691,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_create_channel_link_available" = "This link is available";
|
||||
"lng_create_channel_link_copied" = "Link copied to clipboard";
|
||||
|
||||
"lng_create_group_crop" = "Select a square area for group photo";
|
||||
"lng_create_channel_crop" = "Select a square area for channel photo";
|
||||
"lng_create_group_crop" = "Select an area for group photo";
|
||||
"lng_create_channel_crop" = "Select an area for channel photo";
|
||||
|
||||
"lng_failed_add_participant" = "Could not add user. Please try again later.";
|
||||
"lng_failed_add_not_mutual" = "Sorry, if a person leaves a group, only a mutual contact can bring them back (they need to have your phone number, and you need theirs).";
|
||||
@@ -637,8 +710,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_message_empty" = "Empty Message";
|
||||
"lng_message_unsupported" = "This message is not supported by your version of Telegram Desktop. Please update to the last version in Settings or install it from {link}";
|
||||
|
||||
"lng_duration_seconds" = "{count:_not_used_|# second|# seconds}";
|
||||
"lng_duration_minutes_seconds" = "{count_minutes:# min|# min|# min} {count_seconds:# sec|# sec|# sec}";
|
||||
"lng_duration_seconds#one" = "{count} second";
|
||||
"lng_duration_seconds#other" = "{count} seconds";
|
||||
"lng_duration_minsec_minutes#one" = "{count} min";
|
||||
"lng_duration_minsec_minutes#other" = "{count} min";
|
||||
"lng_duration_minsec_seconds#one" = "{count} sec";
|
||||
"lng_duration_minsec_seconds#other" = "{count} sec";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_add_user" = "{from} added {user}";
|
||||
"lng_action_add_users_many" = "{from} added {users}";
|
||||
@@ -676,18 +754,33 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_sticker" = "a sticker";
|
||||
"lng_action_pinned_media_emoji_sticker" = "a {emoji} sticker";
|
||||
"lng_action_pinned_media_game" = "the game «{game}»";
|
||||
"lng_action_game_score" = "{from} scored {count:#|#|#} in {game}";
|
||||
"lng_action_game_you_scored" = "You scored {count:#|#|#} in {game}";
|
||||
"lng_action_game_score_no_game" = "{from} scored {count:#|#|#}";
|
||||
"lng_action_game_you_scored_no_game" = "You scored {count:#|#|#}";
|
||||
"lng_action_game_score#one" = "{from} scored {count} in {game}";
|
||||
"lng_action_game_score#other" = "{from} scored {count} in {game}";
|
||||
"lng_action_game_you_scored#one" = "You scored {count} in {game}";
|
||||
"lng_action_game_you_scored#other" = "You scored {count} in {game}";
|
||||
"lng_action_game_score_no_game#one" = "{from} scored {count}";
|
||||
"lng_action_game_score_no_game#other" = "{from} scored {count}";
|
||||
"lng_action_game_you_scored_no_game#one" = "You scored {count}";
|
||||
"lng_action_game_you_scored_no_game#other" = "You scored {count}";
|
||||
"lng_action_payment_done" = "You have just successfully transferred {amount} to {user}";
|
||||
"lng_action_payment_done_for" = "You have just successfully transferred {amount} to {user} for {invoice}";
|
||||
"lng_action_took_screenshot" = "{from} took a screenshot!";
|
||||
"lng_action_you_took_screenshot" = "You took a screenshot!";
|
||||
|
||||
"lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached";
|
||||
"lng_ttl_photo_received" = "{from} sent you a self-destructing photo. Please view it on your mobile.";
|
||||
"lng_ttl_photo_sent" = "You sent a self-destructing photo.";
|
||||
"lng_ttl_photo_expired" = "Photo has expired";
|
||||
"lng_ttl_video_received" = "{from} sent you a self-destructing video. Please view it on your mobile.";
|
||||
"lng_ttl_video_sent" = "You sent a self-destructing video.";
|
||||
"lng_ttl_video_expired" = "Video has expired";
|
||||
|
||||
"lng_profile_migrate_reached#one" = "{count} member limit reached";
|
||||
"lng_profile_migrate_reached#other" = "{count} members limit reached";
|
||||
"lng_profile_migrate_body" = "To get over this limit, you can upgrade your group to a supergroup.";
|
||||
"lng_profile_migrate_learn_more" = "Learn more »";
|
||||
"lng_profile_migrate_about" = "If you'd like to go over this limit, you can upgrade your group to a supergroup. In supergroups:";
|
||||
"lng_profile_migrate_feature1" = "— The members limit is {count:_not_used_|# user|# users}";
|
||||
"lng_profile_migrate_feature1#one" = "— The members limit is {count} user";
|
||||
"lng_profile_migrate_feature1#other" = "— The members limit is {count} users";
|
||||
"lng_profile_migrate_feature2" = "— New members see the entire chat history";
|
||||
"lng_profile_migrate_feature3" = "— Admins delete messages for everyone";
|
||||
"lng_profile_migrate_feature4" = "— Notifications are muted by default";
|
||||
@@ -702,7 +795,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_convert_feature4" = "— Creator can set a public link for the group";
|
||||
"lng_profile_convert_warning" = "{bold_start}Note:{bold_end} This action can not be undone";
|
||||
"lng_profile_convert_confirm" = "Convert";
|
||||
"lng_profile_add_more_after_upgrade" = "You will be able to add up to {count:_not_used_|# member|# members} after you upgrade your group to a supergroup.";
|
||||
"lng_profile_add_more_after_upgrade#one" = "You will be able to add up to {count} member after you upgrade your group to a supergroup.";
|
||||
"lng_profile_add_more_after_upgrade#other" = "You will be able to add up to {count} members after you upgrade your group to a supergroup.";
|
||||
|
||||
"lng_channel_not_accessible" = "Sorry, this channel is not accessible.";
|
||||
"lng_group_not_accessible" = "Sorry, this group is not accessible.";
|
||||
@@ -717,7 +811,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_group_invite_want_join_channel" = "Do you want to join the channel «{title}»?";
|
||||
"lng_group_invite_join" = "Join";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# member|# members}, among them:";
|
||||
"lng_group_invite_members#one" = "{count} member, among them:";
|
||||
"lng_group_invite_members#other" = "{count} members, among them:";
|
||||
|
||||
"lng_group_invite_link" = "Invite link:";
|
||||
"lng_group_invite_create" = "Create an invite link";
|
||||
@@ -730,6 +825,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_channel_public_link_copied" = "Link copied to clipboard.";
|
||||
|
||||
"lng_forwarded" = "Forwarded from {user}";
|
||||
"lng_forwarded_date" = "Original: {date}";
|
||||
"lng_forwarded_channel" = "Forwarded from {channel}";
|
||||
"lng_forwarded_via" = "Forwarded from {user} via {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Forwarded from {channel} via {inline_bot}";
|
||||
@@ -809,7 +905,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_stickers_you_have" = "Manage and reorder sticker packs";
|
||||
"lng_stickers_featured" = "Trending Stickers";
|
||||
"lng_stickers_return" = "Undo";
|
||||
"lng_stickers_count" = "{count:Loading...|# sticker|# stickers}";
|
||||
"lng_stickers_count#one" = "{count} sticker";
|
||||
"lng_stickers_count#other" = "{count} stickers";
|
||||
"lng_stickers_masks_pack" = "This is a pack of mask stickers. You can use them in the photo editor on our mobile apps.";
|
||||
|
||||
"lng_in_dlg_photo" = "Photo";
|
||||
@@ -839,6 +936,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_cant_invite_banned" = "Sorry, only admin can add this user.";
|
||||
"lng_cant_invite_privacy" = "Sorry, you cannot add this user to groups because of their privacy settings.";
|
||||
"lng_cant_invite_privacy_channel" = "Sorry, you cannot add this user to channels because of their privacy settings.";
|
||||
"lng_cant_delete_group#one" = "Sorry, it is currently not possible to manually delete communities that have more than {count} member. Please contact Telegram support if you would like to delete this group.";
|
||||
"lng_cant_delete_group#other" = "Sorry, it is currently not possible to manually delete communities that have more than {count} members. Please contact Telegram support if you would like to delete this group.";
|
||||
"lng_cant_delete_channel#one" = "Sorry, it is currently not possible to manually delete communities that have more than {count} member. Please contact Telegram support if you would like to delete this channel.";
|
||||
"lng_cant_delete_channel#other" = "Sorry, it is currently not possible to manually delete communities that have more than {count} members. Please contact Telegram support if you would like to delete this channel.";
|
||||
"lng_cant_do_this" = "Sorry, this action is unavailable.";
|
||||
|
||||
"lng_send_button" = "Send";
|
||||
@@ -884,11 +985,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_typing" = "typing";
|
||||
"lng_user_typing" = "{user} is typing";
|
||||
"lng_users_typing" = "{user} and {second_user} are typing";
|
||||
"lng_many_typing" = "{count:_not_used_|# is|# are} typing";
|
||||
"lng_many_typing#one" = "{count} is typing";
|
||||
"lng_many_typing#other" = "{count} are typing";
|
||||
"lng_playing_game" = "playing a game";
|
||||
"lng_user_playing_game" = "{user} is playing a game";
|
||||
"lng_users_playing_game" = "{user} and {second_user} are playing a game";
|
||||
"lng_many_playing_game" = "{count:_not_used_|# is|# are} playing a game";
|
||||
"lng_many_playing_game#one" = "{count} is playing a game";
|
||||
"lng_many_playing_game#other" = "{count} are playing a game";
|
||||
"lng_send_action_record_video" = "recording a video";
|
||||
"lng_user_action_record_video" = "{user} is recording a video";
|
||||
"lng_send_action_upload_video" = "sending a video";
|
||||
@@ -909,7 +1012,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_geo_location" = "{user} is picking a location";
|
||||
"lng_send_action_choose_contact" = "choosing a contact";
|
||||
"lng_user_action_choose_contact" = "{user} is choosing a contact";
|
||||
"lng_unread_bar" = "{count:_not_used_|# unread message|# unread messages}";
|
||||
"lng_unread_bar#one" = "{count} unread message";
|
||||
"lng_unread_bar#other" = "{count} unread messages";
|
||||
|
||||
"lng_maps_point" = "Location";
|
||||
"lng_save_photo" = "Save image";
|
||||
@@ -932,7 +1036,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_from_top" = "Unpin from top";
|
||||
|
||||
"lng_context_promote_admin" = "Promote to admin";
|
||||
"lng_context_remove_admin" = "Remove from admins";
|
||||
"lng_context_edit_permissions" = "Edit permissions";
|
||||
"lng_context_restrict_user" = "Restrict user";
|
||||
"lng_context_remove_from_group" = "Remove from group";
|
||||
|
||||
"lng_context_copy_link" = "Copy Link";
|
||||
@@ -970,31 +1075,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_msg" = "Unpin Message";
|
||||
"lng_context_cancel_upload" = "Cancel Upload";
|
||||
"lng_context_copy_selected" = "Copy Selected Text";
|
||||
"lng_context_copy_selected_items" = "Copy Selected as Text";
|
||||
"lng_context_forward_selected" = "Forward Selected";
|
||||
"lng_context_delete_selected" = "Delete Selected";
|
||||
"lng_context_clear_selection" = "Clear Selection";
|
||||
"lng_really_send_image" = "Do you want to send this image?";
|
||||
"lng_really_send_file" = "Do you want to send this file?";
|
||||
"lng_really_share_contact" = "Do you want to share this contact?";
|
||||
"lng_send_images_compress" = "Compress {count:_not_used_|image|images}";
|
||||
"lng_send_images_compress#one" = "Compress image";
|
||||
"lng_send_images_compress#other" = "Compress images";
|
||||
"lng_send_image_non_local" = "Could not send a non local file: {name}";
|
||||
"lng_send_image_empty" = "Could not send an empty file: {name}";
|
||||
"lng_send_image_too_large" = "Could not send a file, because it is larger than 1500 MB: {name}";
|
||||
"lng_send_folder" = "Could not send «{name}» because it is a directory :(";
|
||||
"lng_send_images_selected" = "{count:_not_used_|# image|# images} selected";
|
||||
"lng_send_photos" = "Send {count:_not_used_|# photo|# photos}";
|
||||
"lng_send_files_selected" = "{count:_not_used_|# file|# files} selected";
|
||||
"lng_send_files" = "Send {count:_not_used_|# file|# files}";
|
||||
"lng_send_images_selected#one" = "{count} image selected";
|
||||
"lng_send_images_selected#other" = "{count} images selected";
|
||||
"lng_send_photos#one" = "Send {count} photo";
|
||||
"lng_send_photos#other" = "Send {count} photos";
|
||||
"lng_send_files_selected#one" = "{count} file selected";
|
||||
"lng_send_files_selected#other" = "{count} files selected";
|
||||
"lng_send_files#one" = "Send {count} file";
|
||||
"lng_send_files#other" = "Send {count} files";
|
||||
|
||||
"lng_forward_choose" = "Choose recipient...";
|
||||
"lng_forward_cant" = "Sorry, no way to forward here :(";
|
||||
"lng_forward_confirm" = "Forward to {recipient}?";
|
||||
"lng_forward_share_contact" = "Share contact to {recipient}?";
|
||||
"lng_forward_share_cant" = "Sorry, no way to share contact here :(";
|
||||
"lng_forward_send_file_confirm" = "Send «{name}» to {recipient}?";
|
||||
"lng_forward_send_files_confirm" = "Send selected files to {recipient}?";
|
||||
"lng_forward_send_files_cant" = "Sorry, no way to send media here :(";
|
||||
"lng_forward_send" = "Send";
|
||||
"lng_forward_messages" = "{count:_not_used_|Forwarded message|# forwarded messages}";
|
||||
"lng_forwarding_from" = "{user} and {count:_not_used_|# other|# others}";
|
||||
"lng_forward_messages#one" = "{count} forwarded message";
|
||||
"lng_forward_messages#other" = "{count} forwarded messages";
|
||||
"lng_forwarding_from#one" = "{user} and {count} other";
|
||||
"lng_forwarding_from#other" = "{user} and {count} others";
|
||||
"lng_forwarding_from_two" = "{user} and {second_user}";
|
||||
"lng_inline_switch_choose" = "Choose conversation...";
|
||||
"lng_inline_switch_cant" = "Sorry, no way to write here :(";
|
||||
@@ -1016,6 +1131,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_contact_title" = "Edit contact name";
|
||||
"lng_edit_channel_title" = "Edit channel";
|
||||
"lng_edit_sign_messages" = "Sign messages";
|
||||
"lng_edit_group_who_invites" = "Who can add members";
|
||||
"lng_edit_group_invites_everybody" = "All members";
|
||||
"lng_edit_group_invites_only_admins" = "Only admins";
|
||||
"lng_edit_group" = "Edit group";
|
||||
"lng_edit_self_title" = "Edit your name";
|
||||
"lng_confirm_contact_data" = "New Contact";
|
||||
@@ -1040,15 +1158,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_selected_clear" = "Cancel";
|
||||
"lng_selected_delete" = "Delete";
|
||||
"lng_selected_forward" = "Forward";
|
||||
"lng_selected_count" = "{count:_not_used_|# message|# messages}";
|
||||
"lng_selected_count#one" = "{count} message";
|
||||
"lng_selected_count#other" = "{count} messages";
|
||||
"lng_selected_cancel_sure_this" = "Cancel uploading?";
|
||||
"lng_selected_upload_stop" = "Stop";
|
||||
"lng_selected_delete_sure_this" = "Do you want to delete this message?";
|
||||
"lng_selected_delete_sure" = "Do you want to delete {count:_not_used_|# message|# messages}?";
|
||||
"lng_selected_delete_sure#one" = "Do you want to delete {count} message?";
|
||||
"lng_selected_delete_sure#other" = "Do you want to delete {count} messages?";
|
||||
"lng_delete_photo_sure" = "Do you want to delete this photo?";
|
||||
"lng_delete_for_everyone_hint" = "This will delete {count:_not_used_|it|them} for everyone in this chat.";
|
||||
"lng_delete_for_me_chat_hint" = "This will delete {count:_not_used_|it|them} just for you, not for other participants of the chat.";
|
||||
"lng_delete_for_me_hint" = "This will delete {count:_not_used_|it|them} just for you.";
|
||||
"lng_delete_for_everyone_hint#one" = "This will delete it for everyone in this chat.";
|
||||
"lng_delete_for_everyone_hint#other" = "This will delete them for everyone in this chat.";
|
||||
"lng_delete_for_me_chat_hint#one" = "This will delete it just for you, not for other participants of the chat.";
|
||||
"lng_delete_for_me_chat_hint#other" = "This will delete them just for you, not for other participants of the chat.";
|
||||
"lng_delete_for_me_hint#one" = "This will delete it just for you.";
|
||||
"lng_delete_for_me_hint#other" = "This will delete them just for you.";
|
||||
"lng_delete_for_everyone_check" = "Delete for everyone";
|
||||
"lng_delete_for_other_check" = "Delete for {user}";
|
||||
"lng_box_delete" = "Delete";
|
||||
@@ -1060,7 +1183,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_about_text_3" = "Visit {faq_open}Telegram FAQ{faq_close} for more info.";
|
||||
"lng_about_done" = "Done";
|
||||
|
||||
"lng_search_found_results" = "{count:No messages found|Found # message|Found # messages}";
|
||||
"lng_search_no_results" = "No messages found";
|
||||
"lng_search_found_results#one" = "Found {count} message";
|
||||
"lng_search_found_results#other" = "Found {count} messages";
|
||||
"lng_search_global_results" = "Global search results";
|
||||
|
||||
"lng_media_save_progress" = "{ready} of {total} {mb}";
|
||||
@@ -1169,11 +1294,133 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_player_message_yesterday" = "Yesterday at {time}";
|
||||
"lng_player_message_date" = "{date} at {time}";
|
||||
|
||||
"lng_rights_edit_admin" = "Edit administrator";
|
||||
"lng_rights_edit_admin_header" = "What can this admin do?";
|
||||
"lng_rights_about_add_admins_yes" = "This admin will be able to add new admins with the same (or more limited) permissions.";
|
||||
"lng_rights_about_add_admins_no" = "This admin will not be able to add new admins.";
|
||||
"lng_rights_about_admin_cant_edit" = "You cannot edit rights of this admin.";
|
||||
"lng_rights_user_restrictions" = "User restrictions";
|
||||
"lng_rights_user_restrictions_header" = "What can this user do?";
|
||||
|
||||
"lng_rights_channel_info" = "Change channel info";
|
||||
"lng_rights_channel_post" = "Post messages";
|
||||
"lng_rights_channel_edit" = "Edit messages of others";
|
||||
"lng_rights_channel_delete" = "Delete messages of others";
|
||||
"lng_rights_group_info" = "Change group info";
|
||||
"lng_rights_group_ban" = "Ban users";
|
||||
"lng_rights_group_invite_link" = "Invite users via link";
|
||||
"lng_rights_group_invite" = "Add users";
|
||||
"lng_rights_group_pin" = "Pin messages";
|
||||
"lng_rights_group_delete" = "Delete messages";
|
||||
"lng_rights_add_admins" = "Add new admins";
|
||||
"lng_rights_chat_read" = "Read messages";
|
||||
"lng_rights_chat_send_text" = "Send messages";
|
||||
"lng_rights_chat_send_media" = "Send media";
|
||||
"lng_rights_chat_send_stickers" = "Send stickers & GIFs";
|
||||
"lng_rights_chat_send_links" = "Embed links";
|
||||
"lng_rights_chat_banned_until_header" = "Restricted until";
|
||||
"lng_rights_chat_banned_forever" = "Forever";
|
||||
"lng_rights_chat_banned_day#one" = "For {count} day";
|
||||
"lng_rights_chat_banned_day#other" = "For {count} days";
|
||||
"lng_rights_chat_banned_week#one" = "For {count} week";
|
||||
"lng_rights_chat_banned_week#other" = "For {count} weeks";
|
||||
"lng_rights_chat_banned_custom" = "Custom";
|
||||
"lng_rights_chat_banned_custom_date" = "Until {date}";
|
||||
"lng_rights_chat_banned_block" = "Ban and remove from group";
|
||||
|
||||
"lng_restricted_send_message" = "The admins of this group restricted you from writing here.";
|
||||
"lng_restricted_send_media" = "The admins of this group restricted you from posting media content here.";
|
||||
"lng_restricted_send_stickers" = "The admins of this group restricted you from posting stickers here.";
|
||||
"lng_restricted_send_gifs" = "The admins of this group restricted you from posting GIFs here.";
|
||||
"lng_restricted_send_inline" = "The admins of this group restricted you from posting inline content here.";
|
||||
|
||||
"lng_restricted_list_title" = "Restricted users";
|
||||
"lng_banned_list_title" = "Banned users";
|
||||
|
||||
"lng_admin_log_title_all" = "All actions";
|
||||
"lng_admin_log_title_selected" = "Selected actions";
|
||||
"lng_admin_log_filter" = "Filter";
|
||||
"lng_admin_log_filter_title" = "Filter";
|
||||
"lng_admin_log_filter_all_actions" = "All actions";
|
||||
"lng_admin_log_filter_restrictions" = "New restrictions";
|
||||
"lng_admin_log_filter_admins_new" = "New admins";
|
||||
"lng_admin_log_filter_members_new" = "New members";
|
||||
"lng_admin_log_filter_info_group" = "Group info";
|
||||
"lng_admin_log_filter_info_channel" = "Channel info";
|
||||
"lng_admin_log_filter_messages_deleted" = "Deleted messages";
|
||||
"lng_admin_log_filter_messages_edited" = "Edited messages";
|
||||
"lng_admin_log_filter_messages_pinned" = "Pinned messages";
|
||||
"lng_admin_log_filter_members_removed" = "Leaving members";
|
||||
"lng_admin_log_filter_all_admins" = "All users and admins";
|
||||
"lng_admin_log_about" = "What is this?";
|
||||
"lng_admin_log_about_text" = "This is a list of all service actions taken by the group's members and admins in the last 48 hours.";
|
||||
"lng_admin_log_no_results_title" = "No actions found";
|
||||
"lng_admin_log_no_results_text" = "No recent actions that match your query have been found.";
|
||||
"lng_admin_log_no_results_search_text" = "No recent actions that contain '{query}' have been found.";
|
||||
"lng_admin_log_no_events_title" = "No actions yet";
|
||||
"lng_admin_log_no_events_text" = "There were no service actions\ntaken by the group's members\nand admins in the last 48 hours.";
|
||||
|
||||
"lng_admin_log_empty_text" = "Empty";
|
||||
"lng_admin_log_changed_title_group" = "{from} changed group name to «{title}»";
|
||||
"lng_admin_log_changed_title_channel" = "{from} changed channel name to «{title}»";
|
||||
"lng_admin_log_changed_description_group" = "{from} edited group description:";
|
||||
"lng_admin_log_removed_description_group" = "{from} removed group description";
|
||||
"lng_admin_log_changed_description_channel" = "{from} edited channel description:";
|
||||
"lng_admin_log_removed_description_channel" = "{from} removed channel description";
|
||||
"lng_admin_log_previous_description" = "Previous description";
|
||||
"lng_admin_log_changed_link_group" = "{from} changed group link:";
|
||||
"lng_admin_log_removed_link_group" = "{from} removed group link";
|
||||
"lng_admin_log_changed_link_channel" = "{from} changed channel link:";
|
||||
"lng_admin_log_removed_link_channel" = "{from} removed channel link";
|
||||
"lng_admin_log_previous_link" = "Previous link";
|
||||
"lng_admin_log_changed_photo_group" = "{from} changed group photo";
|
||||
"lng_admin_log_changed_photo_channel" = "{from} changed channel photo";
|
||||
"lng_admin_log_removed_photo_group" = "{from} removed group photo";
|
||||
"lng_admin_log_removed_photo_channel" = "{from} removed channel photo";
|
||||
"lng_admin_log_invites_enabled" = "{from} enabled group invites";
|
||||
"lng_admin_log_invites_disabled" = "{from} disabled group invites";
|
||||
"lng_admin_log_signatures_enabled" = "{from} enabled signatures";
|
||||
"lng_admin_log_signatures_disabled" = "{from} disabled signatures";
|
||||
"lng_admin_log_pinned_message" = "{from} pinned message:";
|
||||
"lng_admin_log_unpinned_message" = "{from} unpinned message";
|
||||
"lng_admin_log_edited_caption" = "{from} edited caption:";
|
||||
"lng_admin_log_removed_caption" = "{from} removed caption";
|
||||
"lng_admin_log_previous_caption" = "Original caption";
|
||||
"lng_admin_log_edited_message" = "{from} edited message:";
|
||||
"lng_admin_log_previous_message" = "Original message";
|
||||
"lng_admin_log_deleted_message" = "{from} deleted message:";
|
||||
"lng_admin_log_participant_joined" = "{from} joined the group";
|
||||
"lng_admin_log_participant_joined_channel" = "{from} joined the channel";
|
||||
"lng_admin_log_participant_left" = "{from} left the group";
|
||||
"lng_admin_log_participant_left_channel" = "{from} left the channel";
|
||||
"lng_admin_log_invited" = "invited {user}";
|
||||
"lng_admin_log_banned" = "banned {user}";
|
||||
"lng_admin_log_restricted" = "changed restrictions for {user} {until}";
|
||||
"lng_admin_log_promoted" = "changed privileges for {user}";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_restricted_forever" = "indefinitely";
|
||||
"lng_admin_log_restricted_until" = "until {date}";
|
||||
"lng_admin_log_banned_view_messages" = "Read messages";
|
||||
"lng_admin_log_banned_send_messages" = "Send messages";
|
||||
"lng_admin_log_banned_send_media" = "Send media";
|
||||
"lng_admin_log_banned_send_stickers" = "Send stickers & GIFs";
|
||||
"lng_admin_log_banned_embed_links" = "Embed links";
|
||||
"lng_admin_log_admin_change_info" = "Change info";
|
||||
"lng_admin_log_admin_post_messages" = "Post messages";
|
||||
"lng_admin_log_admin_edit_messages" = "Edit messages";
|
||||
"lng_admin_log_admin_delete_messages" = "Delete messages";
|
||||
"lng_admin_log_admin_ban_users" = "Ban users";
|
||||
"lng_admin_log_admin_invite_users" = "Add users";
|
||||
"lng_admin_log_admin_invite_link" = "Invite users via link";
|
||||
"lng_admin_log_admin_pin_messages" = "Pin messages";
|
||||
"lng_admin_log_admin_add_admins" = "Add new admins";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "Info";
|
||||
"lng_profile_group_info" = "Group info";
|
||||
"lng_profile_channel_info" = "Channel info";
|
||||
"lng_channel_add_admins" = "New administrator";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_menu_update" = "Update";
|
||||
"lng_menu_restart" = "Neustart";
|
||||
"lng_menu_back" = "Zurück";
|
||||
"lng_menu_night_mode" = "Nachtmodus";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Benachrichtigungen aus";
|
||||
"lng_enable_notifications_from_tray" = "Benachrichtigungen ein";
|
||||
@@ -88,7 +89,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_continue" = "Weiter";
|
||||
"lng_close" = "Schließen";
|
||||
"lng_connecting" = "Verbinde...";
|
||||
"lng_reconnecting" = "Neu verbinden {count:jetzt|in # s|in # s}...";
|
||||
"lng_connecting_to_proxy" = "Verbinde mit Proxy...";
|
||||
"lng_connecting_settings" = "Einstellungen";
|
||||
"lng_reconnecting#one" = "Neu verbinden in {count} s...";
|
||||
"lng_reconnecting#other" = "Neu verbinden in {count} s...";
|
||||
"lng_reconnecting_try_now" = "Jetzt versuchen";
|
||||
|
||||
"lng_status_service_notifications" = "Servicemeldungen";
|
||||
@@ -102,8 +106,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_last_month" = "innerhalb eines Monats gesehen";
|
||||
"lng_status_invisible" = "unsichtbar";
|
||||
"lng_status_lastseen_now" = "gerade eben gesehen";
|
||||
"lng_status_lastseen_minutes" = "zuletzt gesehen vor {count:_not_used_|# Minute|# Minuten}";
|
||||
"lng_status_lastseen_hours" = "zuletzt gesehen vor {count:_not_used_|# Stunde|# Stunden}";
|
||||
"lng_status_lastseen_minutes#one" = "zuletzt gesehen vor {count} Minute";
|
||||
"lng_status_lastseen_minutes#other" = "zuletzt gesehen vor {count} Minuten";
|
||||
"lng_status_lastseen_hours#one" = "zuletzt gesehen vor {count} Stunde";
|
||||
"lng_status_lastseen_hours#other" = "zuletzt gesehen vor {count} Stunden";
|
||||
"lng_status_lastseen_today" = "zuletzt heute um {time} gesehen";
|
||||
"lng_status_lastseen_yesterday" = "gestern um {time} zuletzt gesehen";
|
||||
"lng_status_lastseen_date" = "zuletzt gesehen am {date}";
|
||||
@@ -112,24 +118,43 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_connecting" = "verbinden...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "Gruppe ist nicht verfügbar";
|
||||
"lng_chat_status_members" = "{count:keine Mitglieder|# Mitglied|# Mitglieder}";
|
||||
"lng_chat_status_members_online" = "{count:_not_used_|# Mitglied|# Mitglieder}, {count_online:_not_used_|# online|# online}";
|
||||
"lng_chat_status_no_members" = "keine Mitglieder";
|
||||
"lng_chat_status_members#one" = "{count} Mitglied";
|
||||
"lng_chat_status_members#other" = "{count} Mitglieder";
|
||||
"lng_chat_status_online#one" = "{count} online";
|
||||
"lng_chat_status_online#other" = "{count} online";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
|
||||
"lng_channel_status" = "Kanal";
|
||||
"lng_group_status" = "Gruppe";
|
||||
|
||||
"lng_channel_members_link" = "{count:_not_used_|# Mitglied|# Mitglieder}";
|
||||
"lng_channel_admins_link" = "{count:_not_used_|# Administrator|# Administratoren}";
|
||||
"lng_channel_members_link#one" = "{count} Mitglied";
|
||||
"lng_channel_members_link#other" = "{count} Mitglieder";
|
||||
"lng_channel_admins_link#one" = "{count} Administrator";
|
||||
"lng_channel_admins_link#other" = "{count} Administratoren";
|
||||
|
||||
"lng_server_error" = "Interner Serverfehler.";
|
||||
"lng_flood_error" = "Zu viele Versuche, bitte später erneut probieren.";
|
||||
"lng_gif_error" = "GIF-Animation kann nicht abgespielt werden :(";
|
||||
"lng_gif_error" = "Ein Fehler ist beim Laden der GIF-Animation aufgetreten :(";
|
||||
"lng_edit_error" = "Du kannst diese Nachricht nicht bearbeiten";
|
||||
"lng_join_channel_error" = "Du bist bereits in zu vielen Kanälen und Supergruppen. Bitte trenne dich zuvor von ein paar davon.";
|
||||
"lng_error_phone_flood" = "Du hast dein Konto leider zu oft gelöscht. Bitte warte einige Tage, erst dann kannst du dich erneut registrieren.";
|
||||
"lng_error_start_minimized_passcoded" = "Du hast den lokalen Pincode-Schutz aktiviert, deshalb kannst du die App nicht minimiert starten. Die App muss dich vorher nach dem Pincode fragen.";
|
||||
"lng_error_pinned_max" = "Du kannst nicht mehr als {count:_not_used_|# Chat|# Chats} oben anheften.";
|
||||
"lng_error_pinned_max#one" = "Du kannst nicht mehr als {count} Chat oben anheften.";
|
||||
"lng_error_pinned_max#other" = "Du kannst nicht mehr als {count} Chats oben anheften.";
|
||||
"lng_error_public_groups_denied" = "Leider kannst du an keinen öffentlichen Gruppen mehr teilnehmen.\n{more_info}";
|
||||
"lng_error_cant_edit_admin" = "Du kannst die Berechtigungen für diesen Admin nicht ändern.";
|
||||
"lng_error_cant_add_member" = "Du kannst diesen Bot leider nicht der Gruppe hinzufügen. Ein Admin der Gruppe kann ihn hinzufügen.";
|
||||
"lng_error_cant_add_bot" = "Dieser Bot kann Gruppen nicht hinzugefügt werden.";
|
||||
"lng_error_cant_add_admin_invite" = "Du kannst diesen Nutzer nicht als Admin festlegen, da er kein Mitglied dieser Gruppe ist oder du keine Erlaubnis hast, ihn einzuladen.";
|
||||
"lng_error_cant_add_admin_unban" = "Du kannst diesen Nutzer nicht als Admin festlegen, da er sich in der Sperrliste befindet und du ihn nicht entsperren darfst.";
|
||||
"lng_error_cant_ban_admin" = "Du kannst diesen Nutzer nicht sperren, da er ein Admin dieser Gruppe ist und du keine Berechtigung hast, ihn zurückzustufen.";
|
||||
"lng_sure_add_admin_invite" = "Dieser Nutzer ist kein Gruppenmitglied. Möchtest du ihn der Gruppe hinzufügen und als Admin festlegen?";
|
||||
"lng_sure_add_admin_unban" = "Dieser Nutzer ist derzeit in dieser Gruppe eingeschränkt oder gesperrt. Möchtest du ihn entsperren und befördern?";
|
||||
"lng_sure_ban_admin" = "Dieser Nutzer ist Admin in dieser Gruppe. Möchtest du fortfahren und ihn einschränken?";
|
||||
"lng_sure_ban_user_group" = "{user} in der Gruppe sperren?";
|
||||
"lng_sure_enable_socks" = "Möchtest du wirklich diesen Proxy aktivieren?\n\nServer: {server}\nPort: {port}\n\nDu kannst ihn später in den Einstellungen (Verbindungsart) ändern.";
|
||||
"lng_sure_enable" = "Aktivieren";
|
||||
|
||||
"lng_edit_deleted" = "Diese Nachricht wurde gelöscht";
|
||||
"lng_edit_too_long" = "Der Text ist leider zu lang";
|
||||
@@ -198,9 +223,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_signin_sure_reset" = "Hinweis!\n\nDu verlierst du alle Chats und Nachrichten, ebenso deine geteilten Bilder und Videos.\n\nKonto wirklich zurücksetzen?";
|
||||
"lng_signin_reset" = "Zurücksetzen";
|
||||
"lng_signin_reset_wait" = "Da dein Konto {phone_number} aktiv und durch ein Kennwort geschützt ist, löschen wir es aus Sicherheitsgründen in einer Woche. Du kannst den Vorgang jederzeit abbrechen.\n\nDu kannst dein Konto zurücksetzen in:\n{when}";
|
||||
"lng_signin_reset_in_days" = "{count_days:0 Tage|# Tag|# Tage} {count_hours:0 Stunden|# Stunde|# Stunden} {count_minutes:0 Minuten|# Minute|# Minuten}";
|
||||
"lng_signin_reset_in_hours" = "{count_hours:0 Stunden|# Stunde|# Stunden} {count_minutes:0 Minuten|# Minute|# Minuten}";
|
||||
"lng_signin_reset_in_minutes" = "{count_minutes:0 Minuten|# Minute|# Minuten}";
|
||||
"lng_signin_reset_days#one" = "{count} Tag";
|
||||
"lng_signin_reset_days#other" = "{count} Tage";
|
||||
"lng_signin_reset_hours#one" = "{count} Stunde";
|
||||
"lng_signin_reset_hours#other" = "{count} Stunden";
|
||||
"lng_signin_reset_minutes#one" = "{count} Minute";
|
||||
"lng_signin_reset_minutes#other" = "{count} Minuten";
|
||||
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
|
||||
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
|
||||
"lng_signin_reset_cancelled" = "Deine vorherigen Versuche das Konto zurückzusetzen wurden durch den aktiven Nutzer abgebrochen. Bitte in 7 Tagen erneut probieren.";
|
||||
|
||||
"lng_signup_title" = "Deine Info";
|
||||
@@ -223,7 +253,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_settings_save" = "Speichern";
|
||||
"lng_settings_upload" = "Profilbild festlegen";
|
||||
"lng_settings_crop_profile" = "Sichtbaren Bereich für Bild wählen";
|
||||
"lng_settings_crop_profile" = "Wähle einen Bereich für dein Profilbild";
|
||||
"lng_settings_uploading_photo" = "Bild wird geladen...";
|
||||
"lng_settings_edit" = "Bearbeiten";
|
||||
"lng_settings_drop_area_subtitle" = "um es als dein Bild auszuwählen";
|
||||
@@ -241,10 +271,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_username_link" = "Dieser Link öffnet einen Chat mit dir:";
|
||||
"lng_username_copied" = "Link in die Zwischenablage kopiert.";
|
||||
|
||||
"lng_bio_title" = "Bio bearbeiten";
|
||||
"lng_bio_placeholder" = "Bio";
|
||||
"lng_bio_about" = "Hier kannst du etwas über dich schreiben. Jeder der dein Profil öffnet, kann diesen Text lesen.";
|
||||
|
||||
"lng_settings_section_info" = "Info";
|
||||
"lng_settings_phone_number" = "Telefonnummer:";
|
||||
"lng_settings_username" = "Benutzername:";
|
||||
"lng_settings_choose_username" = "Benutzername wählen";
|
||||
"lng_settings_empty_bio" = "Keine";
|
||||
|
||||
"lng_settings_section_notify" = "Benachrichtigungen";
|
||||
"lng_settings_desktop_notify" = "Desktopbenachrichtigungen";
|
||||
@@ -303,7 +338,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_backgrounds_header" = "Neuen Chat-Hintergrund wählen";
|
||||
"lng_theme_sure_keep" = "Wirklich dieses Thema verwenden?";
|
||||
"lng_theme_reverting" = "Vorheriges Thema wird in {count:_not_used_|# Sekunde|# Sekunden} benutzt.";
|
||||
"lng_theme_reverting#one" = "Vorheriges Thema wird in {count} Sekunde benutzt.";
|
||||
"lng_theme_reverting#other" = "Vorheriges Thema wird in {count} Sekunden benutzt.";
|
||||
"lng_theme_keep_changes" = "Anwenden";
|
||||
"lng_theme_revert" = "Zurücksetzen";
|
||||
|
||||
@@ -329,14 +365,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_local_storage_title" = "Lokaler Cache";
|
||||
"lng_settings_no_data_cached" = "Keine temporären Daten!";
|
||||
"lng_settings_images_cached" = "{count:_not_used_|# Bild|# Bilder}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|# Sprachnachricht|# Sprachnachrichten}, {size}";
|
||||
"lng_settings_images_cached#one" = "{count} Bild, {size}";
|
||||
"lng_settings_images_cached#other" = "{count} Bilder, {size}";
|
||||
"lng_settings_audios_cached#one" = "{count} Sprachnachricht, {size}";
|
||||
"lng_settings_audios_cached#other" = "{count} Sprachnachrichten, {size}";
|
||||
"lng_local_storage_clear" = "Leeren";
|
||||
"lng_local_storage_clearing" = "Leeren...";
|
||||
"lng_local_storage_cleared" = "Alles entfernt!";
|
||||
"lng_local_storage_clear_failed" = "Ein Fehler ist aufgetreten :(";
|
||||
|
||||
"lng_settings_section_advanced_settings" = "Erweiterte Einstellungen";
|
||||
"lng_settings_enable_night_theme" = "Nachtmodus aktivieren";
|
||||
"lng_settings_disable_night_theme" = "Nachtmodus deaktivieren";
|
||||
|
||||
"lng_passcode_remove_button" = "Entfernen";
|
||||
|
||||
@@ -348,8 +388,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_passcode_autolock" = "Auto-Sperre";
|
||||
"lng_passcode_autolock_away" = "Auto-Sperre bei Abwesenheit:";
|
||||
"lng_passcode_autolock_inactive" = "Auto-Sperre bei Inaktivität:";
|
||||
"lng_passcode_autolock_minutes" = "{count:_not_used_|# Minute|# Minuten}";
|
||||
"lng_passcode_autolock_hours" = "{count:_not_used_|# Stunde|# Stunden}";
|
||||
"lng_passcode_autolock_minutes#one" = "{count} Minute";
|
||||
"lng_passcode_autolock_minutes#other" = "{count} Minuten";
|
||||
"lng_passcode_autolock_hours#one" = "{count} Stunde";
|
||||
"lng_passcode_autolock_hours#other" = "{count} Stunden";
|
||||
"lng_passcode_enter_old" = "Aktuellen Pincode eingeben";
|
||||
"lng_passcode_enter_first" = "Pincode festlegen";
|
||||
"lng_passcode_enter_new" = "Neuer Pincode";
|
||||
@@ -455,32 +497,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_privacy_lastseen_title" = "Zuletzt gesehen";
|
||||
"lng_edit_privacy_lastseen_description" = "Wer darf deine \"zuletzt gesehen\" Zeit sehen:";
|
||||
"lng_edit_privacy_lastseen_warning" = "Wichtig: Du kannst den \"zuletzt gesehen\" Status nur von Personen sehen, mit denen du auch deinen teilst. Sonst wird nur die ungefähre Zeit angezeigt.";
|
||||
"lng_edit_privacy_lastseen_always" = "Immer teilen mit{count:| # Kontakt| # Kontakten}";
|
||||
"lng_edit_privacy_lastseen_never" = "Niemals teilen mit{count:| # Kontakt| # Kontakten}";
|
||||
"lng_edit_privacy_lastseen_always_empty" = "Immer teilen mit";
|
||||
"lng_edit_privacy_lastseen_always#one" = "Immer teilen mit {count} Kontakt";
|
||||
"lng_edit_privacy_lastseen_always#other" = "Immer teilen mit {count} Kontakten";
|
||||
"lng_edit_privacy_lastseen_never_empty" = "Niemals teilen mit";
|
||||
"lng_edit_privacy_lastseen_never#one" = "Niemals teilen mit {count} Kontakt";
|
||||
"lng_edit_privacy_lastseen_never#other" = "Niemals teilen mit {count} Kontakten";
|
||||
"lng_edit_privacy_lastseen_exceptions" = "Hier kannst du Kontakte hinzufügen, für die eine Ausnahme gemacht werden soll.";
|
||||
"lng_edit_privacy_lastseen_always_title" = "Immer teilen mit";
|
||||
"lng_edit_privacy_lastseen_never_title" = "Niemals teilen mit";
|
||||
|
||||
"lng_edit_privacy_groups_title" = "Wer kann mich Gruppen hinzufügen?";
|
||||
"lng_edit_privacy_groups_description" = "Du kannst bestimmen, wer dich in Gruppen oder Kanälen hinzufügen kann:";
|
||||
"lng_edit_privacy_groups_always" = "Immer erlauben{count:| # Kontakt| # Kontakten}";
|
||||
"lng_edit_privacy_groups_never" = "Niemals erlauben{count:| # Kontakt| # Kontakten}";
|
||||
"lng_edit_privacy_groups_always_empty" = "Immer erlauben";
|
||||
"lng_edit_privacy_groups_always#one" = "Immer {count} Kontakt erlauben";
|
||||
"lng_edit_privacy_groups_always#other" = "Immer {count} Kontakten erlauben";
|
||||
"lng_edit_privacy_groups_never_empty" = "Niemals erlauben";
|
||||
"lng_edit_privacy_groups_never#one" = "Niemals {count} Kontakt erlauben";
|
||||
"lng_edit_privacy_groups_never#other" = "Niemals {count} Kontakten erlauben";
|
||||
"lng_edit_privacy_groups_exceptions" = "Hier kannst du Nutzer hinzufügen, für die eine Ausnahme gemacht werden soll.";
|
||||
"lng_edit_privacy_groups_always_title" = "Immer erlauben";
|
||||
"lng_edit_privacy_groups_never_title" = "Niemals erlauben";
|
||||
|
||||
"lng_edit_privacy_calls_title" = "Anrufe";
|
||||
"lng_edit_privacy_calls_description" = "Du kannst festlegen, wer dich anrufen darf:";
|
||||
"lng_edit_privacy_calls_always" = "Immer erlauben{count:| # Kontakt| # Kontakte}";
|
||||
"lng_edit_privacy_calls_never" = "Niemals erlauben{count:| # Kontakt| # Kontakte}";
|
||||
"lng_edit_privacy_calls_always_empty" = "Immer erlauben";
|
||||
"lng_edit_privacy_calls_always#one" = "Immer {count} Kontakt erlauben";
|
||||
"lng_edit_privacy_calls_always#other" = "Immer {count} Kontakten erlauben";
|
||||
"lng_edit_privacy_calls_never_empty" = "Niemals erlauben";
|
||||
"lng_edit_privacy_calls_never#one" = "Niemals {count} Kontakt erlauben";
|
||||
"lng_edit_privacy_calls_never#other" = "Niemals {count} Kontakten erlauben";
|
||||
"lng_edit_privacy_calls_exceptions" = "Hier kannst du Nutzer hinzufügen, für die eine Ausnahme gemacht werden soll.";
|
||||
"lng_edit_privacy_calls_always_title" = "Immer erlauben";
|
||||
"lng_edit_privacy_calls_never_title" = "Niemals erlauben";
|
||||
|
||||
"lng_self_destruct_title" = "Automatische Kontolöschung";
|
||||
"lng_self_destruct_description" = "Wenn du dich innerhalb dieser Zeit nicht anmeldest, wird dein Konto mit allen Nachrichten, Gruppen und Kontakten gelöscht.";
|
||||
"lng_self_destruct_months" = "{count:_not_used_|# Monat|# Monate}";
|
||||
"lng_self_destruct_years" = "{count:_not_used_|# Jahr|# Jahre}";
|
||||
"lng_self_destruct_months#one" = "{count} Monat";
|
||||
"lng_self_destruct_months#other" = "{count} Monate";
|
||||
"lng_self_destruct_years#one" = "{count} Jahr";
|
||||
"lng_self_destruct_years#other" = "{count} Jahre";
|
||||
|
||||
"lng_change_phone_title" = "Nummer ändern";
|
||||
"lng_change_phone_description" = "Du kannst deine Telefonnummer hier ändern.\nDein Konto und alle Daten in der Cloud, also \nNachrichten, Medien, Kontakte, etc. werden \nauf das neue Konto übertragen.\n\n[b]Wichtig[/b]: Alle deine Kontakte erhalten deine\n[b]neue Nummer[/b] ihrem Telefonbuch\nhinzugefügt, sofern sie deine alte Nummer \nhatten und du sie nicht blockiert hattest.";
|
||||
@@ -506,15 +562,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_link_section" = "Einladungslink";
|
||||
"lng_profile_create_public_link" = "Öffentlichen Link erstellen";
|
||||
"lng_profile_edit_public_link" = "Öffentlichen Link bearbeiten";
|
||||
"lng_profile_search_members" = "Mitglieder suchen";
|
||||
"lng_profile_manage_admins" = "Administratoren verwalten";
|
||||
"lng_profile_manage_blocklist" = "Blockierte Nutzer verwalten";
|
||||
"lng_profile_common_groups" = "{count:_not_used_|# gemeinsame Gruppe|# gemeinsame Gruppen}";
|
||||
"lng_profile_manage_blocklist" = "Gesperrte Nutzer verwalten";
|
||||
"lng_profile_manage_restrictedlist" = "Eingeschränke Nutzer verwalten";
|
||||
"lng_profile_recent_actions" = "Letzte Aktionen";
|
||||
"lng_profile_common_groups#one" = "{count} gemeinsame Gruppe";
|
||||
"lng_profile_common_groups#other" = "{count} gemeinsame Gruppen";
|
||||
"lng_profile_common_groups_section" = "Gemeinsame Gruppen";
|
||||
"lng_profile_participants_section" = "Teilnehmer";
|
||||
"lng_profile_info_section" = "Info";
|
||||
"lng_profile_mobile_number" = "Telefon:";
|
||||
"lng_profile_username" = "Benutzername:";
|
||||
"lng_profile_link" = "Link:";
|
||||
"lng_profile_bio" = "Bio:";
|
||||
"lng_profile_add_contact" = "Kontakt hinzufügen";
|
||||
"lng_profile_edit_contact" = "Bearbeiten";
|
||||
"lng_profile_enable_notifications" = "Benachrichtigungen";
|
||||
@@ -542,23 +603,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_delete_and_exit" = "Verlassen";
|
||||
"lng_profile_kick" = "Entfernen";
|
||||
"lng_profile_admin" = "Admin";
|
||||
"lng_profile_edit_permissions" = "Bearbeiten";
|
||||
"lng_profile_sure_kick" = "{user} aus der Gruppe entfernen?";
|
||||
"lng_profile_sure_kick_channel" = "{user} aus dem Kanal entfernen?";
|
||||
"lng_profile_sure_kick_admin" = "{user} als Administrator entfernen?";
|
||||
"lng_profile_loading" = "Lade...";
|
||||
"lng_profile_shared_media" = "Geteilte Medien";
|
||||
"lng_profile_no_media" = "Noch keine Medien in diesem Chat";
|
||||
"lng_profile_photos" = "{count:_not_used_|# Bild|# Bilder}";
|
||||
"lng_profile_photos#one" = "{count} Bild";
|
||||
"lng_profile_photos#other" = "{count} Bilder";
|
||||
"lng_profile_photos_header" = "Bilder";
|
||||
"lng_profile_videos" = "{count:_not_used_|# Video|# Videos}";
|
||||
"lng_profile_videos#one" = "{count} Video";
|
||||
"lng_profile_videos#other" = "{count} Videos";
|
||||
"lng_profile_videos_header" = "Videos";
|
||||
"lng_profile_songs" = "{count:_not_used_|# Audio|# Audios}";
|
||||
"lng_profile_songs#one" = "{count} Audiodatei";
|
||||
"lng_profile_songs#other" = "{count} Audiodateien";
|
||||
"lng_profile_songs_header" = "Audiodateien";
|
||||
"lng_profile_files" = "{count:_not_used_|# Datei|# Dateien}";
|
||||
"lng_profile_files#one" = "{count} Datei";
|
||||
"lng_profile_files#other" = "{count} Dateien";
|
||||
"lng_profile_files_header" = "Dateien";
|
||||
"lng_profile_audios" = "{count:_not_used_|# Sprachnachricht|# Sprachnachrichten}";
|
||||
"lng_profile_audios#one" = "{count} Sprachnachricht";
|
||||
"lng_profile_audios#other" = "{count} Sprachnachrichten";
|
||||
"lng_profile_audios_header" = "Sprachnachrichten";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# Geteilter Link|# Geteilte Links}";
|
||||
"lng_profile_shared_links#one" = "{count} geteilter Link";
|
||||
"lng_profile_shared_links#other" = "{count} geteilte Links";
|
||||
"lng_profile_shared_links_header" = "Geteilte Links";
|
||||
"lng_profile_copy_phone" = "Telefonnummer kopieren";
|
||||
"lng_profile_copy_fullname" = "Name kopieren";
|
||||
@@ -578,16 +646,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_report_button" = "Melden";
|
||||
"lng_report_thanks" = "Vielen Dank! Unser Team wird sich um deine Meldung kümmern.";
|
||||
|
||||
"lng_channel_add_admins" = "Neuer Administrator";
|
||||
"lng_channel_add_members" = "Mitglieder hinzufügen";
|
||||
"lng_channel_add_banned" = "Nutzer sperren";
|
||||
"lng_channel_add_restricted" = "Nutzer einschränken";
|
||||
"lng_channel_members" = "Mitglieder";
|
||||
"lng_channel_only_last_shown" = "Nur {count:_not_used_|# letztes Mitglied wird angezeigt|letzte # Mitglieder werden angezeigt}";
|
||||
"lng_channel_only_last_shown#one" = "Nur {count} letztes Mitgled wird hier angezeigt";
|
||||
"lng_channel_only_last_shown#other" = "Nur {count} letzte Mitgleder werden hier angezeigt";
|
||||
"lng_channel_admins" = "Administratoren";
|
||||
"lng_channel_add_admin" = "Administrator hinzufügen";
|
||||
"lng_channel_admin_sure" = "Soll {user} Administrator werden?";
|
||||
"lng_channel_admins_too_much" = "Leider kannst du keine weiteren Admins dieser Gruppe hinzufügen, bitte erst welche löschen.";
|
||||
"lng_channel_admin_status_creator" = "Ersteller";
|
||||
"lng_channel_admin_status_promoted_by" = "Befördert von {user}";
|
||||
"lng_channel_admin_status_not_admin" = "Kein Administrator";
|
||||
|
||||
"lng_group_blocked_list_about" = "Blockierte Nutzer werden aus der Gruppe entfernt und können nur durch einen Admin hinzugefügt werden.\n\nEinladungslinks funktionieren nicht.";
|
||||
"lng_group_blocked_list_about" = "Gesperrte Nutzer werden von der Gruppe entfernt und können nur durch Admins erneut hinzugefügt werden. \nEinladungslinks funktionieren nicht.";
|
||||
|
||||
"lng_chat_all_members_admins" = "Alle Mitglieder Sind Admins";
|
||||
"lng_chat_about_all_admins" = "Gruppenmitglieder können neue Leute hinzufügen sowie den Gruppennamen und das Bild ändern.";
|
||||
@@ -595,7 +667,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_participant_filter" = "Suche";
|
||||
"lng_participant_invite" = "Einladen";
|
||||
"lng_participant_invite_sorry" = "Du kannst selbst nur {count:_not_used| das erste Mitglied|die ersten # Mitglieder} in einen Kanal einladen.\n\nWeitere Mitglieder können deinem Kanal über den Einladungslink beitreten.";
|
||||
"lng_participant_invite_sorry#one" = "Du kannst selbst nur das erste {count} Mitglied einem Kanal hinzufügen.\n\nWeitere Leute können den Kanal über den Einladungslink betreten.";
|
||||
"lng_participant_invite_sorry#other" = "Du kannst selbst nur die ersten {count} Mitglieder einem Kanal hinzufügen.\n\nWeitere Leute können den Kanal über den Einladungslink betreten.";
|
||||
"lng_create_group_back" = "Zurück";
|
||||
"lng_create_group_next" = "Weiter";
|
||||
"lng_create_group_create" = "Erstellen";
|
||||
@@ -618,8 +691,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_create_channel_link_available" = "Dieser Link ist verfügbar";
|
||||
"lng_create_channel_link_copied" = "Link in die Zwischenablage kopiert";
|
||||
|
||||
"lng_create_group_crop" = "Sichtbaren Bereich für Bild wählen";
|
||||
"lng_create_channel_crop" = "Sichtbaren Bereich für Bild wählen";
|
||||
"lng_create_group_crop" = "Wähle einen Bereich für dein Gruppenbild";
|
||||
"lng_create_channel_crop" = "Wähle einen Bereich für dein Kanalbild";
|
||||
|
||||
"lng_failed_add_participant" = "Kann Teilnehmer nicht hinzufügen. Später erneut versuchen.";
|
||||
"lng_failed_add_not_mutual" = "Wenn man eine Gruppe verlässt, kann nur ein gemeinsamer Kontakt die Person erneut einladen (beide Seiten müssen die Nummer des anderen gespeichert haben).";
|
||||
@@ -637,8 +710,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_message_empty" = "Leere Nachricht";
|
||||
"lng_message_unsupported" = "Diese Nachricht wird von deiner Telegram Desktop Version nicht unterstützt. Bitte aktualisiere sie in den Einstellungen oder über {link}";
|
||||
|
||||
"lng_duration_seconds" = "{count:_not_used_|# Sekunde|# Sekunden}";
|
||||
"lng_duration_minutes_seconds" = "{count_minutes:# Min|# Min|# Min} {count_seconds:# Sek|# Sek|# Sek}";
|
||||
"lng_duration_seconds#one" = "{count} Sekunde";
|
||||
"lng_duration_seconds#other" = "{count} Sekunden";
|
||||
"lng_duration_minsec_minutes#one" = "{count} Min";
|
||||
"lng_duration_minsec_minutes#other" = "{count} Min";
|
||||
"lng_duration_minsec_seconds#one" = "{count} Sek";
|
||||
"lng_duration_minsec_seconds#other" = "{count} Sek";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_add_user" = "{from} hat {user} hinzugefügt";
|
||||
"lng_action_add_users_many" = "{from} hat {users} hinzugefügt";
|
||||
@@ -676,18 +754,33 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_sticker" = "einen Sticker";
|
||||
"lng_action_pinned_media_emoji_sticker" = "einen {emoji} Sticker";
|
||||
"lng_action_pinned_media_game" = "das Spiel «{game}»";
|
||||
"lng_action_game_score" = "{from} erzielte {count:# Punkte|# Punkt|# Punkte} bei {game}";
|
||||
"lng_action_game_you_scored" = "Du hast {count:# Punkte|# Punkt|# Punkte} bei {game} erzielt";
|
||||
"lng_action_game_score_no_game" = "{from} erzielte {count:# Punkte|# Punkt|# Punkte}";
|
||||
"lng_action_game_you_scored_no_game" = "Du hast {count:# Punkte erzielt|# Punkt erzielt|# Punkte erzielt}";
|
||||
"lng_action_game_score#one" = "{from} erzielte {count} Punkt bei {game}";
|
||||
"lng_action_game_score#other" = "{from} erzielte {count} Punkte bei {game}";
|
||||
"lng_action_game_you_scored#one" = "Du hast {count} Punkt bei {game} erzielt";
|
||||
"lng_action_game_you_scored#other" = "Du hast {count} Punkte bei {game} erzielt";
|
||||
"lng_action_game_score_no_game#one" = "{from} erzielte {count} Punkt";
|
||||
"lng_action_game_score_no_game#other" = "{from} erzielte {count} Punkte";
|
||||
"lng_action_game_you_scored_no_game#one" = "Du hast {count} Punkt erzielt";
|
||||
"lng_action_game_you_scored_no_game#other" = "Du hast {count} Punkte erzielt";
|
||||
"lng_action_payment_done" = "Du hast erfolgreich {amount} an {user} übermittelt";
|
||||
"lng_action_payment_done_for" = "Du hast erfolgreich {amount} an {user} für {invoice} übermittelt";
|
||||
"lng_action_took_screenshot" = "{from} hat ein Bildschirmfoto gemacht!";
|
||||
"lng_action_you_took_screenshot" = "Du hast ein Bildschirmfoto gemacht!";
|
||||
|
||||
"lng_profile_migrate_reached" = "Limit von {count:_not_used_|# Mitglied|# Mitgliedern} erreicht";
|
||||
"lng_ttl_photo_received" = "{from} hat dir ein selbstzerstörendes Bild gesendet. Um es anzuzeigen, bitte Handy benutzen.";
|
||||
"lng_ttl_photo_sent" = "Du hast ein selbstzerstörendes Bild gesendet.";
|
||||
"lng_ttl_photo_expired" = "Bild ist abgelaufen";
|
||||
"lng_ttl_video_received" = "{from} hat dir ein selbstzerstörendes Video gesendet. Um es anzuzeigen, bitte Handy benutzen.";
|
||||
"lng_ttl_video_sent" = "Du hast ein selbstzerstörendes Video gesendet.";
|
||||
"lng_ttl_video_expired" = "Video ist abgelaufen";
|
||||
|
||||
"lng_profile_migrate_reached#one" = "Limit von {count} Mitglied erreicht";
|
||||
"lng_profile_migrate_reached#other" = "Limit von {count} Mitgliedern erreicht";
|
||||
"lng_profile_migrate_body" = "Um das Limit aufzuheben, ändere die Gruppe in eine Supergruppe.";
|
||||
"lng_profile_migrate_learn_more" = "Mehr unter:";
|
||||
"lng_profile_migrate_about" = "Für weitere Funktionen und um das Limit aufzuheben in Supergruppe ändern:";
|
||||
"lng_profile_migrate_feature1" = "— Bis zu {count:_not_used_|# Mitglied|# Mitglieder} sind nun möglich";
|
||||
"lng_profile_migrate_feature1#one" = "— Das Limit beträgt {count} Mitglied";
|
||||
"lng_profile_migrate_feature1#other" = "— Das Limit beträgt {count} Mitglieder";
|
||||
"lng_profile_migrate_feature2" = "— Neue Mitglieder sehen gesamten Verlauf";
|
||||
"lng_profile_migrate_feature3" = "— Admins können alle Nachrichten löschen";
|
||||
"lng_profile_migrate_feature4" = "— Mitteilungen sind standardmäßig stumm";
|
||||
@@ -702,7 +795,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_convert_feature4" = "— Gründer kann Gruppe öffentlich machen";
|
||||
"lng_profile_convert_warning" = "{bold_start}Wichtig:{bold_end} Die Änderung in eine Supergruppe kann nicht rückgängig gemacht werden.";
|
||||
"lng_profile_convert_confirm" = "Ändern";
|
||||
"lng_profile_add_more_after_upgrade" = "Du kannst nach der Änderung der Gruppe in eine Supergruppe bis zu {count:_not_used_|# Mitglied|# Mitglieder} hinzufügen.";
|
||||
"lng_profile_add_more_after_upgrade#one" = "Du kannst nach der Änderung der Gruppe in eine Supergruppe bis zu {count} Mitglied hinzufügen.";
|
||||
"lng_profile_add_more_after_upgrade#other" = "Du kannst nach der Änderung der Gruppe in eine Supergruppe bis zu {count} Mitglieder hinzufügen.";
|
||||
|
||||
"lng_channel_not_accessible" = "Dieser Kanal ist nicht zugänglich";
|
||||
"lng_group_not_accessible" = "Diese Gruppe ist nicht zugänglich.";
|
||||
@@ -717,7 +811,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_group_invite_want_join_channel" = "Möchtest du dem Kanal «{title}» beitreten?";
|
||||
"lng_group_invite_join" = "Beitreten";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# Mitglied|# Mitglieder}, darunter:";
|
||||
"lng_group_invite_members#one" = "{count} Mitglied, darunter:";
|
||||
"lng_group_invite_members#other" = "{count} Mitglieder, darunter:";
|
||||
|
||||
"lng_group_invite_link" = "Einladungslink:";
|
||||
"lng_group_invite_create" = "Neuer Link";
|
||||
@@ -730,6 +825,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_channel_public_link_copied" = "Link in die Zwischenablage kopiert.\n";
|
||||
|
||||
"lng_forwarded" = "Weitergeleitet von {user}";
|
||||
"lng_forwarded_date" = "Original: {date}";
|
||||
"lng_forwarded_channel" = "Weitergeleitet aus {channel}";
|
||||
"lng_forwarded_via" = "Weitergeleitet von {user} via {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Weitergeleitet aus {channel} via {inline_bot}";
|
||||
@@ -809,7 +905,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_stickers_you_have" = "Sticker-Pakete verwalten";
|
||||
"lng_stickers_featured" = "Angesagte Sticker";
|
||||
"lng_stickers_return" = "Rückgängig";
|
||||
"lng_stickers_count" = "{count:Lade...|# Sticker|# Sticker}";
|
||||
"lng_stickers_count#one" = "{count} Sticker";
|
||||
"lng_stickers_count#other" = "{count} Sticker";
|
||||
"lng_stickers_masks_pack" = "Das ist ein Masken-Paket. Du kannst Masken nur im Editor unserer mobilen Apps verwenden.";
|
||||
|
||||
"lng_in_dlg_photo" = "Bild";
|
||||
@@ -839,6 +936,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_cant_invite_banned" = "Nur Admins können diesen Nutzer hinzufügen.";
|
||||
"lng_cant_invite_privacy" = "Du kannst mit diesem Nutzer keine Gruppe erstellen, weil er es nicht erlaubt.";
|
||||
"lng_cant_invite_privacy_channel" = "Du kannst diesen Nutzer keinen Kanälen hinzufügen, weil er es nicht erlaubt.";
|
||||
"lng_cant_delete_group#one" = "Über die App kannst du derzeit keine Gruppen mit mehr als {count} Mitglied löschen. Bitte melde dich bei unserem Support Chat, wenn du diese Gruppe löschen lassen möchtest.";
|
||||
"lng_cant_delete_group#other" = "Über die App kannst du derzeit keine Gruppen mit mehr als {count} Mitgliedern löschen. Bitte melde dich bei unserem Support Chat, wenn du diese Gruppe löschen lassen möchtest.";
|
||||
"lng_cant_delete_channel#one" = "Über die App kannst du derzeit keine Kanäle mit mehr als {count} Mitglied löschen. Bitte melde dich bei unserem Support Chat, wenn du diesen Kanal löschen lassen möchtest.";
|
||||
"lng_cant_delete_channel#other" = "Über die App kannst du derzeit keinen Kanäle mit mehr als {count} Mitgliedern löschen. Bitte melde dich bei unserem Support Chat, wenn du diesen Kanal löschen lassen möchtest.";
|
||||
"lng_cant_do_this" = "Verzeihung. Das ist leider nicht möglich.";
|
||||
|
||||
"lng_send_button" = "Senden";
|
||||
@@ -884,11 +985,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_typing" = "tippt";
|
||||
"lng_user_typing" = "{user} tippt";
|
||||
"lng_users_typing" = "{user} und {second_user} tippen";
|
||||
"lng_many_typing" = "{count:_not_used_|# tippt|# tippen}";
|
||||
"lng_many_typing#one" = "{count} tippt";
|
||||
"lng_many_typing#other" = "{count} tippen";
|
||||
"lng_playing_game" = "spielt ein Spiel";
|
||||
"lng_user_playing_game" = "{user} spielt ein Spiel";
|
||||
"lng_users_playing_game" = "{user} und {second_user} spielen ein Spiel";
|
||||
"lng_many_playing_game" = "{count:_not_used_|# spielt|# spielen} ein Spiel";
|
||||
"lng_many_playing_game#one" = "{count} spielt ein Spiel";
|
||||
"lng_many_playing_game#other" = "{count} spielen ein Spiel";
|
||||
"lng_send_action_record_video" = "schickt Video";
|
||||
"lng_user_action_record_video" = "{user} sendet ein Video";
|
||||
"lng_send_action_upload_video" = "schickt ein Video";
|
||||
@@ -909,7 +1012,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_geo_location" = "{user} wählt einen Standort aus";
|
||||
"lng_send_action_choose_contact" = "wählt einen Kontakt aus";
|
||||
"lng_user_action_choose_contact" = "{user} wählt einen Kontakt aus";
|
||||
"lng_unread_bar" = "{count:_not_used_|# Ungelesene Nachricht|# Ungelesene Nachrichten}";
|
||||
"lng_unread_bar#one" = "{count} ungelesene Nachricht";
|
||||
"lng_unread_bar#other" = "{count} ungelesene Nachrichten";
|
||||
|
||||
"lng_maps_point" = "Standort";
|
||||
"lng_save_photo" = "Bild speichern";
|
||||
@@ -932,7 +1036,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_from_top" = "Oben entfernen";
|
||||
|
||||
"lng_context_promote_admin" = "Zum Admin machen";
|
||||
"lng_context_remove_admin" = "Als Admin entfernen";
|
||||
"lng_context_edit_permissions" = "Berechtigungen bearbeiten";
|
||||
"lng_context_restrict_user" = "Nutzer einschränken";
|
||||
"lng_context_remove_from_group" = "Aus Gruppe entfernen";
|
||||
|
||||
"lng_context_copy_link" = "Link kopieren";
|
||||
@@ -970,31 +1075,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_msg" = "Nachricht entfernen";
|
||||
"lng_context_cancel_upload" = "Upload abbrechen";
|
||||
"lng_context_copy_selected" = "Text kopieren";
|
||||
"lng_context_copy_selected_items" = "Als Text kopieren";
|
||||
"lng_context_forward_selected" = "Auswahl weiterleiten";
|
||||
"lng_context_delete_selected" = "Auswahl löschen";
|
||||
"lng_context_clear_selection" = "Auswahl aufheben";
|
||||
"lng_really_send_image" = "Willst du dieses Bild senden?";
|
||||
"lng_really_send_file" = "Willst du diese Datei senden?";
|
||||
"lng_really_share_contact" = "Willst du diesen Kontakt senden?";
|
||||
"lng_send_images_compress" = "Komprimiere {count:_not_used_|Bild|Bilder}";
|
||||
"lng_send_images_compress#one" = "Bild komprimieren";
|
||||
"lng_send_images_compress#other" = "Bilder komprimieren";
|
||||
"lng_send_image_non_local" = "{name} befindet sich nicht direkt auf dem Gerät";
|
||||
"lng_send_image_empty" = "Leere Datei {name} konnte nicht gesendet werden";
|
||||
"lng_send_image_too_large" = "{name} ist größer als 1500 MB und kann daher nicht gesendet werden";
|
||||
"lng_send_folder" = "Verzeichnis «{name}» kann nicht gesendet werden :(";
|
||||
"lng_send_images_selected" = "{count:_not_used_|# Bild|# Bilder} ausgewählt";
|
||||
"lng_send_photos" = "{count:_not_used_|# Bild|# Bilder} senden";
|
||||
"lng_send_files_selected" = "{count:_not_used_|# Datei|# Dateien} ausgewählt";
|
||||
"lng_send_files" = "{count:_not_used_|# Datei|# Dateien} senden";
|
||||
"lng_send_images_selected#one" = "{count} Bild ausgewählt";
|
||||
"lng_send_images_selected#other" = "{count} Bilder ausgewählt";
|
||||
"lng_send_photos#one" = "{count} Bild senden";
|
||||
"lng_send_photos#other" = "{count} Bilder senden";
|
||||
"lng_send_files_selected#one" = "{count} Datei ausgewählt";
|
||||
"lng_send_files_selected#other" = "{count} Dateien ausgewählt";
|
||||
"lng_send_files#one" = "{count} Datei senden";
|
||||
"lng_send_files#other" = "{count} Dateien senden";
|
||||
|
||||
"lng_forward_choose" = "Empfänger wählen...";
|
||||
"lng_forward_cant" = "Weiterleiten nicht möglich :(";
|
||||
"lng_forward_confirm" = "An {recipient} weiterleiten?";
|
||||
"lng_forward_share_contact" = "Kontakt an {recipient} senden?";
|
||||
"lng_forward_share_cant" = "Kontakt teilen nicht möglich :(";
|
||||
"lng_forward_send_file_confirm" = "«{name}» an {recipient} senden?";
|
||||
"lng_forward_send_files_confirm" = "Ausgewählte Dateien an {recipient} senden?";
|
||||
"lng_forward_send_files_cant" = "Medien senden nicht möglich :(";
|
||||
"lng_forward_send" = "Senden";
|
||||
"lng_forward_messages" = "{count:_not_used_|Nachrichtenanhang|# Nachrichtenanhänge}";
|
||||
"lng_forwarding_from" = "{user} und {count:_not_used_|# anderer|# andere}";
|
||||
"lng_forward_messages#one" = "{count} weitergeleitete Nachricht";
|
||||
"lng_forward_messages#other" = "{count} weitergeleitete Nachrichten";
|
||||
"lng_forwarding_from#one" = "{user} und {count} anderer";
|
||||
"lng_forwarding_from#other" = "{user} und {count} andere";
|
||||
"lng_forwarding_from_two" = "{user} und {second_user}";
|
||||
"lng_inline_switch_choose" = "Chat wählen...";
|
||||
"lng_inline_switch_cant" = "Hier kannst du nicht schreiben :(";
|
||||
@@ -1016,6 +1131,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_contact_title" = "Kontaktnamen ändern";
|
||||
"lng_edit_channel_title" = "Kanal bearbeiten";
|
||||
"lng_edit_sign_messages" = "Nachrichten unterschreiben";
|
||||
"lng_edit_group_who_invites" = "Wer kann Mitglieder hinzufügen";
|
||||
"lng_edit_group_invites_everybody" = "Alle Mitglieder";
|
||||
"lng_edit_group_invites_only_admins" = "Nur Admins";
|
||||
"lng_edit_group" = "Gruppe bearbeiten";
|
||||
"lng_edit_self_title" = "Name bearbeiten";
|
||||
"lng_confirm_contact_data" = "Neuer Kontakt";
|
||||
@@ -1040,15 +1158,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_selected_clear" = "Abbrechen";
|
||||
"lng_selected_delete" = "Löschen";
|
||||
"lng_selected_forward" = "Weiterleiten";
|
||||
"lng_selected_count" = "{count:_not_used_|# Nachricht|# Nachrichten}";
|
||||
"lng_selected_count#one" = "{count} Nachricht";
|
||||
"lng_selected_count#other" = "{count} Nachrichten";
|
||||
"lng_selected_cancel_sure_this" = "Upload abbrechen?";
|
||||
"lng_selected_upload_stop" = "Stoppen";
|
||||
"lng_selected_delete_sure_this" = "Diese Nachricht wirklich löschen?";
|
||||
"lng_selected_delete_sure" = "Willst du {count:_not_used_|# Nachricht|# Nachrichten} löschen?";
|
||||
"lng_selected_delete_sure#one" = "Möchtest du {count} Nachricht löschen?";
|
||||
"lng_selected_delete_sure#other" = "Möchtest du {count} Nachrichten löschen?";
|
||||
"lng_delete_photo_sure" = "Dieses Bild wirklich löschen?";
|
||||
"lng_delete_for_everyone_hint" = "Das wird {count:_not_used_|sie|sie} bei allen im Chat löschen.";
|
||||
"lng_delete_for_me_chat_hint" = "Das wird {count:_not_used_|sie|sie} nur bei dir löschen und nicht bei anderen Teilnehmern.";
|
||||
"lng_delete_for_me_hint" = "Das wird {count:_not_used_|sie|sie} nur bei dir löschen.";
|
||||
"lng_delete_for_everyone_hint#one" = "Das wird es bei allen im Chat löschen.";
|
||||
"lng_delete_for_everyone_hint#other" = "Das wird sie bei allen im Chat löschen.";
|
||||
"lng_delete_for_me_chat_hint#one" = "Das wird es nur bei dir löschen und nicht bei anderen Teilnehmern.";
|
||||
"lng_delete_for_me_chat_hint#other" = "Das wird sie nur bei dir löschen und nicht bei anderen Teilnehmern.";
|
||||
"lng_delete_for_me_hint#one" = "Das wird es nur bei dir löschen.";
|
||||
"lng_delete_for_me_hint#other" = "Das wird sie nur bei dir löschen.";
|
||||
"lng_delete_for_everyone_check" = "Bei allen löschen";
|
||||
"lng_delete_for_other_check" = "Bei {user} löschen";
|
||||
"lng_box_delete" = "Löschen";
|
||||
@@ -1060,7 +1183,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_about_text_3" = "Fragen? Besuche doch {faq_open}unsere FAQ{faq_close} für mehr Infos.";
|
||||
"lng_about_done" = "Fertig";
|
||||
|
||||
"lng_search_found_results" = "{count:Keine Nachrichten|# Nachricht|# Nachrichten}";
|
||||
"lng_search_no_results" = "Keine Nachrichten gefunden";
|
||||
"lng_search_found_results#one" = "{count} Nachricht gefunden";
|
||||
"lng_search_found_results#other" = "{count} Nachrichten gefunden";
|
||||
"lng_search_global_results" = "Globale Suchergebnisse";
|
||||
|
||||
"lng_media_save_progress" = "{ready} von {total} {mb}";
|
||||
@@ -1169,11 +1294,133 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_player_message_yesterday" = "Gestern um {time}";
|
||||
"lng_player_message_date" = "{date} um {time}";
|
||||
|
||||
"lng_rights_edit_admin" = "Administrator bearbeiten";
|
||||
"lng_rights_edit_admin_header" = "Was kann dieser Admin machen?";
|
||||
"lng_rights_about_add_admins_yes" = "Dieser Admin wird neue Admins mit gleichen (oder eingeschränkten) Rechten hinzufügen können.";
|
||||
"lng_rights_about_add_admins_no" = "Dieser Admin kann keine neuen Admins hinzufügen.";
|
||||
"lng_rights_about_admin_cant_edit" = "Du kannst die Berechtigungen für diesen Admin nicht ändern.";
|
||||
"lng_rights_user_restrictions" = "Nutzerbeschränkungen";
|
||||
"lng_rights_user_restrictions_header" = "Was kann dieser Nutzer machen?";
|
||||
|
||||
"lng_rights_channel_info" = "Kanal-Info ändern";
|
||||
"lng_rights_channel_post" = "Nachrichten senden";
|
||||
"lng_rights_channel_edit" = "Nachrichten von anderen bearbeiten";
|
||||
"lng_rights_channel_delete" = "Nachrichten von anderen löschen";
|
||||
"lng_rights_group_info" = "Gruppen-Info ändern";
|
||||
"lng_rights_group_ban" = "Nutzer sperren";
|
||||
"lng_rights_group_invite_link" = "Nutzer per Link einladen";
|
||||
"lng_rights_group_invite" = "Nutzer hinzufügen";
|
||||
"lng_rights_group_pin" = "Nachrichten anheften";
|
||||
"lng_rights_group_delete" = "Nachrichten löschen";
|
||||
"lng_rights_add_admins" = "Neue Admins hinzufügen";
|
||||
"lng_rights_chat_read" = "Nachrichten lesen";
|
||||
"lng_rights_chat_send_text" = "Nachrichten senden";
|
||||
"lng_rights_chat_send_media" = "Medien senden";
|
||||
"lng_rights_chat_send_stickers" = "Sticker & GIFs senden";
|
||||
"lng_rights_chat_send_links" = "Linkvorschau senden";
|
||||
"lng_rights_chat_banned_until_header" = "Eingeschränkt bis";
|
||||
"lng_rights_chat_banned_forever" = "Dauerhaft";
|
||||
"lng_rights_chat_banned_day#one" = "Für {count} Tag";
|
||||
"lng_rights_chat_banned_day#other" = "Für {count} Tage";
|
||||
"lng_rights_chat_banned_week#one" = "Für {count} Woche";
|
||||
"lng_rights_chat_banned_week#other" = "Für {count} Wochen";
|
||||
"lng_rights_chat_banned_custom" = "Eigener";
|
||||
"lng_rights_chat_banned_custom_date" = "Bis {date}";
|
||||
"lng_rights_chat_banned_block" = "Sperren und aus Gruppe entfernen";
|
||||
|
||||
"lng_restricted_send_message" = "Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Nachrichten zu senden.";
|
||||
"lng_restricted_send_media" = "Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Medien zu senden.";
|
||||
"lng_restricted_send_stickers" = "Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Sticker zu senden.";
|
||||
"lng_restricted_send_gifs" = "Die Admins dieser Gruppe haben dir die Berechtigung entzogen, GIFs zu senden.";
|
||||
"lng_restricted_send_inline" = "Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Inline-Bot Inhalte zu senden.";
|
||||
|
||||
"lng_restricted_list_title" = "Eingeschränke Nutzer";
|
||||
"lng_banned_list_title" = "Gesperrte Nutzer";
|
||||
|
||||
"lng_admin_log_title_all" = "Alle Aktionen";
|
||||
"lng_admin_log_title_selected" = "Ausgewählte Aktionen";
|
||||
"lng_admin_log_filter" = "Filtern";
|
||||
"lng_admin_log_filter_title" = "Filtern";
|
||||
"lng_admin_log_filter_all_actions" = "Alle Aktionen";
|
||||
"lng_admin_log_filter_restrictions" = "Neue Einschränkungen";
|
||||
"lng_admin_log_filter_admins_new" = "Neue Admins";
|
||||
"lng_admin_log_filter_members_new" = "Neue Mitglieder";
|
||||
"lng_admin_log_filter_info_group" = "Gruppen-Info";
|
||||
"lng_admin_log_filter_info_channel" = "Kanal-Info";
|
||||
"lng_admin_log_filter_messages_deleted" = "Gelöschte Nachrichten";
|
||||
"lng_admin_log_filter_messages_edited" = "Bearbeitete Nachrichten";
|
||||
"lng_admin_log_filter_messages_pinned" = "Angeheftete Nachrichten";
|
||||
"lng_admin_log_filter_members_removed" = "Ehemalige Mitglieder";
|
||||
"lng_admin_log_filter_all_admins" = "Alle Nutzer";
|
||||
"lng_admin_log_about" = "Was ist das?";
|
||||
"lng_admin_log_about_text" = "Das ist eine Liste aller Aktionen, die von Gruppenmitgliedern und Admins in den letzten 48 Stunden durchgeführt wurden.";
|
||||
"lng_admin_log_no_results_title" = "Keine Aktionen gefunden";
|
||||
"lng_admin_log_no_results_text" = "Keine kürzlichen Ereignisse gefunden, die deinen Suchbegriff beinhalten.";
|
||||
"lng_admin_log_no_results_search_text" = "Keine kürzlichen Aktionen gefunden, die '{query}' beinhalten.";
|
||||
"lng_admin_log_no_events_title" = "Keine Aktionen gefunden";
|
||||
"lng_admin_log_no_events_text" = "Es wurden keine Service-Aktionen \nvon Admins und Gruppenmitgliedern\nin den letzten 48 Stunden durchgeführt.";
|
||||
|
||||
"lng_admin_log_empty_text" = "Leer";
|
||||
"lng_admin_log_changed_title_group" = "{from} hat den Gruppennamen in «{title}» geändert";
|
||||
"lng_admin_log_changed_title_channel" = "{from} hat den Kanalnamen in «{title}» geändert";
|
||||
"lng_admin_log_changed_description_group" = "{from} hat Gruppenbeschreibung bearbeitet:";
|
||||
"lng_admin_log_removed_description_group" = "{from} hat Gruppenbeschreibung entfernt";
|
||||
"lng_admin_log_changed_description_channel" = "{from} hat Kanalbeschreibung bearbeitet:";
|
||||
"lng_admin_log_removed_description_channel" = "{from} hat Kanalbeschreibung entfernt";
|
||||
"lng_admin_log_previous_description" = "Vorherige Beschreibung";
|
||||
"lng_admin_log_changed_link_group" = "{from} hat Gruppen-Link geändert:";
|
||||
"lng_admin_log_removed_link_group" = "{from} hat Gruppen-Link entfernt";
|
||||
"lng_admin_log_changed_link_channel" = "{from} hat Kanal-Link geändert:";
|
||||
"lng_admin_log_removed_link_channel" = "{from} hat Kanal-Link entfernt";
|
||||
"lng_admin_log_previous_link" = "Vorheriger Link";
|
||||
"lng_admin_log_changed_photo_group" = "{from} hat Gruppenbild geändert";
|
||||
"lng_admin_log_changed_photo_channel" = "{from} hat Kanalbild geändert";
|
||||
"lng_admin_log_removed_photo_group" = "{from} hat Gruppenbild entfernt";
|
||||
"lng_admin_log_removed_photo_channel" = "{from} hat Kanalbild entfernt";
|
||||
"lng_admin_log_invites_enabled" = "{from} hat Gruppeneinladungen aktiviert";
|
||||
"lng_admin_log_invites_disabled" = "{from} hat Gruppeneinladungen deaktiviert";
|
||||
"lng_admin_log_signatures_enabled" = "{from} hat Unterschriften aktiviert";
|
||||
"lng_admin_log_signatures_disabled" = "{from} hat Unterschriften deaktiviert";
|
||||
"lng_admin_log_pinned_message" = "{from} hat Nachricht angeheftet:";
|
||||
"lng_admin_log_unpinned_message" = "{from} hat angeheftete Nachricht entfernt";
|
||||
"lng_admin_log_edited_caption" = "{from} hat Beschriftung bearbeitet:";
|
||||
"lng_admin_log_removed_caption" = "{from} hat Beschriftung entfernt";
|
||||
"lng_admin_log_previous_caption" = "Original-Beschriftung";
|
||||
"lng_admin_log_edited_message" = "{from} hat Nachricht bearbeitet:";
|
||||
"lng_admin_log_previous_message" = "Original-Nachricht";
|
||||
"lng_admin_log_deleted_message" = "{from} hat Nachricht gelöscht:";
|
||||
"lng_admin_log_participant_joined" = "{from} ist der Gruppe beigetreten";
|
||||
"lng_admin_log_participant_joined_channel" = "{from} ist dem Kanal beigetreten";
|
||||
"lng_admin_log_participant_left" = "{from} hat die Gruppe verlassen";
|
||||
"lng_admin_log_participant_left_channel" = "{from} hat den Kanal verlassen";
|
||||
"lng_admin_log_invited" = "hat {user} eingeladen";
|
||||
"lng_admin_log_banned" = "hat {user} gesperrt";
|
||||
"lng_admin_log_restricted" = "hat Einschränkungen für {user} {until} geändert";
|
||||
"lng_admin_log_promoted" = "hat Berechtigungen für {user} geändert";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_restricted_forever" = "unbegrenzt";
|
||||
"lng_admin_log_restricted_until" = "bis {date}";
|
||||
"lng_admin_log_banned_view_messages" = "Nachrichten lesen";
|
||||
"lng_admin_log_banned_send_messages" = "Nachrichten senden";
|
||||
"lng_admin_log_banned_send_media" = "Medien senden";
|
||||
"lng_admin_log_banned_send_stickers" = "Sticker & GIFs senden";
|
||||
"lng_admin_log_banned_embed_links" = "Linkvorschau senden";
|
||||
"lng_admin_log_admin_change_info" = "Info ändern";
|
||||
"lng_admin_log_admin_post_messages" = "Nachrichten senden";
|
||||
"lng_admin_log_admin_edit_messages" = "Nachrichten bearbeiten";
|
||||
"lng_admin_log_admin_delete_messages" = "Nachrichten löschen";
|
||||
"lng_admin_log_admin_ban_users" = "Nutzer sperren";
|
||||
"lng_admin_log_admin_invite_users" = "Nutzer hinzufügen";
|
||||
"lng_admin_log_admin_invite_link" = "Nutzer per Link einladen";
|
||||
"lng_admin_log_admin_pin_messages" = "Nachrichten anheften";
|
||||
"lng_admin_log_admin_add_admins" = "Neue Admins hinzufügen";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "Info";
|
||||
"lng_profile_group_info" = "Gruppeninfo";
|
||||
"lng_profile_channel_info" = "Info";
|
||||
"lng_channel_add_admins" = "Neuer Administrator";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_menu_update" = "Actualizar";
|
||||
"lng_menu_restart" = "Reiniciar";
|
||||
"lng_menu_back" = "Atrás";
|
||||
"lng_menu_night_mode" = "Modo noche";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Desactivar notificaciones";
|
||||
"lng_enable_notifications_from_tray" = "Activar notificaciones";
|
||||
@@ -88,7 +89,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_continue" = "Continuar";
|
||||
"lng_close" = "Cerrar";
|
||||
"lng_connecting" = "Conectando...";
|
||||
"lng_reconnecting" = "Reconectar {count:ahora|en # s|en # s}...";
|
||||
"lng_connecting_to_proxy" = "Conectando al proxy...";
|
||||
"lng_connecting_settings" = "Ajustes";
|
||||
"lng_reconnecting#one" = "Reconectar en {count} s...";
|
||||
"lng_reconnecting#other" = "Reconectar en {count} s...";
|
||||
"lng_reconnecting_try_now" = "Intentar ahora";
|
||||
|
||||
"lng_status_service_notifications" = "servicio de notificaciones";
|
||||
@@ -102,8 +106,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_last_month" = "última vez hace unas semanas";
|
||||
"lng_status_invisible" = "invisible";
|
||||
"lng_status_lastseen_now" = "última vez hace un momento";
|
||||
"lng_status_lastseen_minutes" = "última vez hace {count:_not_used_|# minuto|# minutos}";
|
||||
"lng_status_lastseen_hours" = "última vez hace {count:_not_used_|# hora|# horas}";
|
||||
"lng_status_lastseen_minutes#one" = "última vez hace {count} minuto";
|
||||
"lng_status_lastseen_minutes#other" = "última vez hace {count} minutos";
|
||||
"lng_status_lastseen_hours#one" = "última vez hace {count} hora";
|
||||
"lng_status_lastseen_hours#other" = "última vez hace {count} horas";
|
||||
"lng_status_lastseen_today" = "última vez hoy a las {time}";
|
||||
"lng_status_lastseen_yesterday" = "última vez ayer a las {time}";
|
||||
"lng_status_lastseen_date" = "última vez el {date}";
|
||||
@@ -112,14 +118,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_connecting" = "conectando...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "grupo inaccesible";
|
||||
"lng_chat_status_members" = "{count:sin miembros|# miembro|# miembros}";
|
||||
"lng_chat_status_members_online" = "{count:_not_used_|# miembro|# miembros}, {count_online:_not_used_|# en línea|# en línea}";
|
||||
"lng_chat_status_no_members" = "sin miembros";
|
||||
"lng_chat_status_members#one" = "{count} miembro";
|
||||
"lng_chat_status_members#other" = "{count} miembros";
|
||||
"lng_chat_status_online#one" = "{count} en línea";
|
||||
"lng_chat_status_online#other" = "{count} en línea";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
|
||||
"lng_channel_status" = "canal";
|
||||
"lng_group_status" = "grupo";
|
||||
|
||||
"lng_channel_members_link" = "{count:_not_used_|# miembro|# miembros}";
|
||||
"lng_channel_admins_link" = "{count:_not_used_|# administrador|# administradores}";
|
||||
"lng_channel_members_link#one" = "{count} miembro";
|
||||
"lng_channel_members_link#other" = "{count} miembros";
|
||||
"lng_channel_admins_link#one" = "{count} administrador";
|
||||
"lng_channel_admins_link#other" = "{count} administradores";
|
||||
|
||||
"lng_server_error" = "Error interno del servidor.";
|
||||
"lng_flood_error" = "Muchos intentos. Por favor, reinténtalo más tarde.";
|
||||
@@ -128,8 +140,21 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_join_channel_error" = "Lo sentimos, te has unido a demasiados canales y supergrupos. Por favor, sal de algunos antes de unirte.";
|
||||
"lng_error_phone_flood" = "Has eliminado y vuelto a crear tu cuenta muchas veces recientemente. Por favor, espera algunos días antes de inscribirte de nuevo.";
|
||||
"lng_error_start_minimized_passcoded" = "Has configurado un código de acceso, así que no puedes iniciar la app minimizada. La app te pedirá el código de acceso para que empiece a funcionar.";
|
||||
"lng_error_pinned_max" = "Lo sentimos, no puedes anclar más de {count:_not_used_|# chat|# chats}.";
|
||||
"lng_error_pinned_max#one" = "Lo sentimos, no puedes anclar más de {count} chat.";
|
||||
"lng_error_pinned_max#other" = "Lo sentimos, no puedes anclar más de {count} chats.";
|
||||
"lng_error_public_groups_denied" = "Lamentablemente, tienes prohibido participar en grupos públicos.\n{more_info}";
|
||||
"lng_error_cant_edit_admin" = "No puedes editar los permisos de este administrador.";
|
||||
"lng_error_cant_add_member" = "No puedes añadir al bot a este grupo. Pide a algún administrador que lo haga.";
|
||||
"lng_error_cant_add_bot" = "Este bot no puede se añadido a grupos.";
|
||||
"lng_error_cant_add_admin_invite" = "No puedes añadir a este usuario como administrador porque no es un miembro de este grupo y no puedes invitarlo.";
|
||||
"lng_error_cant_add_admin_unban" = "No puedes añadir a este usuario como administrador porque está en la lista de suspendidos y no puedes quitar su suspensión.";
|
||||
"lng_error_cant_ban_admin" = "No puedes suspender a este usuario porque es un administrador del grupo y no puedes degradarlo.";
|
||||
"lng_sure_add_admin_invite" = "Este usuario no es miembro del grupo. ¿Quieres añadirlo y ascenderlo a administrador?";
|
||||
"lng_sure_add_admin_unban" = "Este usuario está restringido o suspendido del grupo. ¿Quieres quitar su suspensión y ascenderlo a administrador?";
|
||||
"lng_sure_ban_admin" = "Este usuario es administrador del grupo. ¿Quieres continuar y restringirlo?";
|
||||
"lng_sure_ban_user_group" = "¿Suspender a {user} en el grupo?";
|
||||
"lng_sure_enable_socks" = "¿Quieres activar este proxy?\n\nServidor: {server}\nPuerto: {port}\n\nPuedes cambiar tu servidor proxy más tarde en Ajustes (Tipo de conexión).";
|
||||
"lng_sure_enable" = "Activar";
|
||||
|
||||
"lng_edit_deleted" = "Este mensaje fue eliminado";
|
||||
"lng_edit_too_long" = "Tu texto es demasiado largo";
|
||||
@@ -157,7 +182,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_phone_ph" = "Tu número de teléfono";
|
||||
"lng_phone_title" = "Tu teléfono";
|
||||
"lng_phone_desc" = "Por favor, confirma el código de tu país\ny tu número de teléfono.";
|
||||
"lng_phone_notreg" = "Si no tienes una cuenta de Telegram todavía, \npor favor, [b]regístrate[/b] con {link_start}Android / iPhone{link_end}\no aquí {signup_start}here{signup_end}";
|
||||
"lng_phone_notreg" = "Si no tienes una cuenta de Telegram todavía, \npor favor, [b]regístrate[/b] con {link_start}Android / iPhone{link_end}\no {signup_start}aquí{signup_end}";
|
||||
"lng_country_code" = "Código de país";
|
||||
"lng_bad_country_code" = "Código de país inválido";
|
||||
"lng_country_ph" = "Buscar";
|
||||
@@ -198,9 +223,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_signin_sure_reset" = "¡Advertencia!\n\n¡Perderás todos tus chats y mensajes, junto con la multimedia y archivos compartidos!\n\n¿Quieres restablecer tu cuenta?";
|
||||
"lng_signin_reset" = "Restablecer";
|
||||
"lng_signin_reset_wait" = "Como la cuenta {phone_number} está activa y protegida con una contraseña, la eliminaremos en 1 semana, por motivos de seguridad. Puedes cancelar el proceso en cualquier momento.\n\nPodrás restablecer tu cuenta en:\n{when}";
|
||||
"lng_signin_reset_in_days" = "{count_days:0 días|# día|# días} {count_hours:0 horas|# hora|# horas} {count_minutes:0 minutos|# minuto|# minutos}";
|
||||
"lng_signin_reset_in_hours" = "{count_hours:0 horas|# hora|# horas} {count_minutes:0 minutos|# minuto|# minutos}";
|
||||
"lng_signin_reset_in_minutes" = "{count_minutes:0 minutos|# minuto|# minutos}";
|
||||
"lng_signin_reset_days#one" = "{count} día";
|
||||
"lng_signin_reset_days#other" = "{count} días";
|
||||
"lng_signin_reset_hours#one" = "{count} hora";
|
||||
"lng_signin_reset_hours#other" = "{count} horas";
|
||||
"lng_signin_reset_minutes#one" = "{count} minuto";
|
||||
"lng_signin_reset_minutes#other" = "{count} minutos";
|
||||
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
|
||||
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
|
||||
"lng_signin_reset_cancelled" = "Tus intentos recientes para restablecer la cuenta fueron cancelados por su usuario activo. Por favor, reinténtalo en 7 días.";
|
||||
|
||||
"lng_signup_title" = "Tu información";
|
||||
@@ -223,7 +253,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_settings_save" = "Guardar";
|
||||
"lng_settings_upload" = "Poner foto de perfil";
|
||||
"lng_settings_crop_profile" = "Selecciona el área para tu foto de perfil";
|
||||
"lng_settings_crop_profile" = "Selecciona un área para tu foto de perfil";
|
||||
"lng_settings_uploading_photo" = "Subiendo foto...";
|
||||
"lng_settings_edit" = "Editar";
|
||||
"lng_settings_drop_area_subtitle" = "para ponerla como tu foto";
|
||||
@@ -241,10 +271,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_username_link" = "Este enlace abre un chat contigo:";
|
||||
"lng_username_copied" = "Enlace copiado al portapapeles.";
|
||||
|
||||
"lng_bio_title" = "Editar tu biografía";
|
||||
"lng_bio_placeholder" = "Biografía";
|
||||
"lng_bio_about" = "Puedes añadir algunas palabras sobre ti. Cualquiera que abra tu perfil verá este texto.";
|
||||
|
||||
"lng_settings_section_info" = "Información";
|
||||
"lng_settings_phone_number" = "Número de teléfono:";
|
||||
"lng_settings_username" = "Alias:";
|
||||
"lng_settings_choose_username" = "Elige un alias";
|
||||
"lng_settings_empty_bio" = "Ninguna";
|
||||
|
||||
"lng_settings_section_notify" = "Notificaciones";
|
||||
"lng_settings_desktop_notify" = "Notificaciones de escritorio";
|
||||
@@ -303,7 +338,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_backgrounds_header" = "Elige tu nuevo fondo de chat";
|
||||
"lng_theme_sure_keep" = "¿Mantener este tema?";
|
||||
"lng_theme_reverting" = "Regresar al tema anterior en {count:_not_used_|# segundo|# segundos}.";
|
||||
"lng_theme_reverting#one" = "Regresar al tema anterior en {count} segundo.";
|
||||
"lng_theme_reverting#other" = "Regresar al tema anterior en {count} segundos.";
|
||||
"lng_theme_keep_changes" = "Mantener cambios";
|
||||
"lng_theme_revert" = "Revertir";
|
||||
|
||||
@@ -329,14 +365,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_local_storage_title" = "Almacenamiento local";
|
||||
"lng_settings_no_data_cached" = "¡No se encontraron datos en la caché!";
|
||||
"lng_settings_images_cached" = "{count:_not_used_|# imagen|# imágenes}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|# mensaje de voz|# mensajes de voz}, {size}";
|
||||
"lng_settings_images_cached#one" = "{count} imagen, {size}";
|
||||
"lng_settings_images_cached#other" = "{count} imágenes, {size}";
|
||||
"lng_settings_audios_cached#one" = "{count} mensaje de voz, {size}";
|
||||
"lng_settings_audios_cached#other" = "{count} mensajes de voz, {size}";
|
||||
"lng_local_storage_clear" = "Eliminar todo";
|
||||
"lng_local_storage_clearing" = "Borrando...";
|
||||
"lng_local_storage_cleared" = "¡Borrado!";
|
||||
"lng_local_storage_clear_failed" = "Borrado fallido :(";
|
||||
|
||||
"lng_settings_section_advanced_settings" = "Ajustes avanzados";
|
||||
"lng_settings_enable_night_theme" = "Activar modo noche";
|
||||
"lng_settings_disable_night_theme" = "Desactivar modo noche";
|
||||
|
||||
"lng_passcode_remove_button" = "Quitar";
|
||||
|
||||
@@ -348,8 +388,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_passcode_autolock" = "Autobloqueo";
|
||||
"lng_passcode_autolock_away" = "Autobloqueo si estoy fuera:";
|
||||
"lng_passcode_autolock_inactive" = "Autobloqueo si estoy inactivo:";
|
||||
"lng_passcode_autolock_minutes" = "{count:_not_used_|# minuto|# minutos}";
|
||||
"lng_passcode_autolock_hours" = "{count:_not_used_|# hora|# horas}";
|
||||
"lng_passcode_autolock_minutes#one" = "{count} minuto";
|
||||
"lng_passcode_autolock_minutes#other" = "{count} minutos";
|
||||
"lng_passcode_autolock_hours#one" = "{count} hora";
|
||||
"lng_passcode_autolock_hours#other" = "{count} horas";
|
||||
"lng_passcode_enter_old" = "Pon el código de acceso actual";
|
||||
"lng_passcode_enter_first" = "Pon un código de acceso";
|
||||
"lng_passcode_enter_new" = "Pon tu nuevo código";
|
||||
@@ -455,32 +497,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_privacy_lastseen_title" = "Última conexión";
|
||||
"lng_edit_privacy_lastseen_description" = "Puedes elegir quién ve tu última conexión:";
|
||||
"lng_edit_privacy_lastseen_warning" = "Importante: No verás la última conexión de las personas con las que no compartes la tuya. En su lugar, se mostrarán conexiones indeterminadas (recientemente, hace unos días, hace unas semanas).";
|
||||
"lng_edit_privacy_lastseen_always" = "Compartir con{count:| # usuario| # usuarios}";
|
||||
"lng_edit_privacy_lastseen_never" = "No compartir con{count:| # usuario| # usuarios}";
|
||||
"lng_edit_privacy_lastseen_always_empty" = "Compartir con";
|
||||
"lng_edit_privacy_lastseen_always#one" = "Compartir con {count} usuario";
|
||||
"lng_edit_privacy_lastseen_always#other" = "Compartir con {count} usuarios";
|
||||
"lng_edit_privacy_lastseen_never_empty" = "No compartir con";
|
||||
"lng_edit_privacy_lastseen_never#one" = "No compartir con {count} usuario";
|
||||
"lng_edit_privacy_lastseen_never#other" = "No compartir con {count} usuarios";
|
||||
"lng_edit_privacy_lastseen_exceptions" = "Estos ajustes anularán los valores de arriba.";
|
||||
"lng_edit_privacy_lastseen_always_title" = "Compartir con";
|
||||
"lng_edit_privacy_lastseen_never_title" = "No compartir con";
|
||||
|
||||
"lng_edit_privacy_groups_title" = "Invitación a grupos";
|
||||
"lng_edit_privacy_groups_description" = "Puedes restringir quién puede añadirte a grupos o canales con gran precisión:";
|
||||
"lng_edit_privacy_groups_always" = "Permitir{count:| # usuario| # usuarios}";
|
||||
"lng_edit_privacy_groups_never" = "No permitir{count:| # usuario| # usuarios}";
|
||||
"lng_edit_privacy_groups_always_empty" = "Permitir";
|
||||
"lng_edit_privacy_groups_always#one" = "Permitir {count} usuario";
|
||||
"lng_edit_privacy_groups_always#other" = "Permitir {count} usuarios";
|
||||
"lng_edit_privacy_groups_never_empty" = "No permitir";
|
||||
"lng_edit_privacy_groups_never#one" = "No permitir {count} usuario";
|
||||
"lng_edit_privacy_groups_never#other" = "No permitir {count} usuarios";
|
||||
"lng_edit_privacy_groups_exceptions" = "Estos usuarios podrán o no añadirte a grupos y canales, independiente de los ajustes de arriba.";
|
||||
"lng_edit_privacy_groups_always_title" = "Permitir";
|
||||
"lng_edit_privacy_groups_never_title" = "No permitir";
|
||||
|
||||
"lng_edit_privacy_calls_title" = "Privacidad de llamadas";
|
||||
"lng_edit_privacy_calls_description" = "Puedes restringir quién puede llamarte:";
|
||||
"lng_edit_privacy_calls_always" = "Permitir{count:| # usuario| # usuarios}";
|
||||
"lng_edit_privacy_calls_never" = "No permitir{count:| # usuario| # usuarios}";
|
||||
"lng_edit_privacy_calls_always_empty" = "Permitir";
|
||||
"lng_edit_privacy_calls_always#one" = "Permitir {count} usuario";
|
||||
"lng_edit_privacy_calls_always#other" = "Permitir {count} usuarios";
|
||||
"lng_edit_privacy_calls_never_empty" = "No permitir";
|
||||
"lng_edit_privacy_calls_never#one" = "No permitir {count} usuario";
|
||||
"lng_edit_privacy_calls_never#other" = "No permitir {count} usuarios";
|
||||
"lng_edit_privacy_calls_exceptions" = "Estos usuarios podrán o no llamarte, independiente de los ajustes de arriba.";
|
||||
"lng_edit_privacy_calls_always_title" = "Permitir";
|
||||
"lng_edit_privacy_calls_never_title" = "No permitir";
|
||||
|
||||
"lng_self_destruct_title" = "Autodestrucción de la cuenta";
|
||||
"lng_self_destruct_description" = "Si no estás en línea durante este tiempo, al menos una vez, tu cuenta se eliminará con todos tus grupos, mensajes y contactos.";
|
||||
"lng_self_destruct_months" = "{count:_not_used_|# mes|# meses}";
|
||||
"lng_self_destruct_years" = "{count:_not_used_|# año|# años}";
|
||||
"lng_self_destruct_months#one" = "{count} mes";
|
||||
"lng_self_destruct_months#other" = "{count} meses";
|
||||
"lng_self_destruct_years#one" = "{count} año";
|
||||
"lng_self_destruct_years#other" = "{count} años";
|
||||
|
||||
"lng_change_phone_title" = "Cambiar número de teléfono";
|
||||
"lng_change_phone_description" = "Puedes cambiar tu número de Telegram aquí. \nTu cuenta y todos tus datos de la nube, mensajes,\narchivos, grupos, contactos, etc., se moverán al \nnuevo número.\n\n[b]Importante[/b]: Todos tus contactos de Telegram\ntendrán tu [b]nuevo número[/b] añadido a sus \nagendas de contactos, siempre que hayan tenido \ntu número viejo y no los hayas bloqueado.";
|
||||
@@ -506,15 +562,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_link_section" = "Enlace de invitación";
|
||||
"lng_profile_create_public_link" = "Crear enlace público";
|
||||
"lng_profile_edit_public_link" = "Editar enlace público";
|
||||
"lng_profile_search_members" = "Buscar miembros";
|
||||
"lng_profile_manage_admins" = "Gestionar administradores";
|
||||
"lng_profile_manage_blocklist" = "Administrar usuarios bloqueados";
|
||||
"lng_profile_common_groups" = "{count:_not_used_|# grupo|# grupos} en común";
|
||||
"lng_profile_manage_blocklist" = "Administrar usuarios suspendidos";
|
||||
"lng_profile_manage_restrictedlist" = "Administrar usuarios restringidos";
|
||||
"lng_profile_recent_actions" = "Acciones recientes";
|
||||
"lng_profile_common_groups#one" = "{count} grupo en común";
|
||||
"lng_profile_common_groups#other" = "{count} grupos en común";
|
||||
"lng_profile_common_groups_section" = "Grupos en común";
|
||||
"lng_profile_participants_section" = "Miembros";
|
||||
"lng_profile_info_section" = "Información";
|
||||
"lng_profile_mobile_number" = "Número:";
|
||||
"lng_profile_username" = "Alias:";
|
||||
"lng_profile_link" = "Enlace:";
|
||||
"lng_profile_bio" = "Biografía:";
|
||||
"lng_profile_add_contact" = "Añadir contacto";
|
||||
"lng_profile_edit_contact" = "Editar";
|
||||
"lng_profile_enable_notifications" = "Notificaciones";
|
||||
@@ -542,23 +603,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_delete_and_exit" = "Salir";
|
||||
"lng_profile_kick" = "Eliminar";
|
||||
"lng_profile_admin" = "administrador";
|
||||
"lng_profile_edit_permissions" = "Editar";
|
||||
"lng_profile_sure_kick" = "¿Eliminar a {user} del grupo?";
|
||||
"lng_profile_sure_kick_channel" = "¿Eliminar a {user} del canal?";
|
||||
"lng_profile_sure_kick_admin" = "¿Eliminar a {user} de los administradores?";
|
||||
"lng_profile_loading" = "Cargando...";
|
||||
"lng_profile_shared_media" = "Multimedia";
|
||||
"lng_profile_no_media" = "No hay multimedia en este chat.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# foto|# fotos}";
|
||||
"lng_profile_photos#one" = "{count} foto";
|
||||
"lng_profile_photos#other" = "{count} fotos";
|
||||
"lng_profile_photos_header" = "Fotos";
|
||||
"lng_profile_videos" = "{count:_not_used_|# vídeo|# vídeos}";
|
||||
"lng_profile_videos#one" = "{count} vídeo";
|
||||
"lng_profile_videos#other" = "{count} vídeos";
|
||||
"lng_profile_videos_header" = "Vídeos";
|
||||
"lng_profile_songs" = "{count:_not_used_|# audio|# audios}";
|
||||
"lng_profile_songs#one" = "{count} audio";
|
||||
"lng_profile_songs#other" = "{count} audios";
|
||||
"lng_profile_songs_header" = "Audios";
|
||||
"lng_profile_files" = "{count:_not_used_|# archivo|# archivos}";
|
||||
"lng_profile_files#one" = "{count} archivo";
|
||||
"lng_profile_files#other" = "{count} archivos";
|
||||
"lng_profile_files_header" = "Archivos";
|
||||
"lng_profile_audios" = "{count:_not_used_|# mensaje de voz|# mensajes de voz}";
|
||||
"lng_profile_audios#one" = "{count} mensaje de voz";
|
||||
"lng_profile_audios#other" = "{count} mensajes de voz";
|
||||
"lng_profile_audios_header" = "Mensajes de voz";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# enlace|# enlaces}";
|
||||
"lng_profile_shared_links#one" = "{count} enlace";
|
||||
"lng_profile_shared_links#other" = "{count} enlaces";
|
||||
"lng_profile_shared_links_header" = "Enlaces";
|
||||
"lng_profile_copy_phone" = "Copiar número de teléfono";
|
||||
"lng_profile_copy_fullname" = "Copiar nombre";
|
||||
@@ -578,16 +646,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_report_button" = "Reportar";
|
||||
"lng_report_thanks" = "¡Gracias! Tu reporte será revisado por nuestro equipo muy pronto.";
|
||||
|
||||
"lng_channel_add_admins" = "Nuevo administrador";
|
||||
"lng_channel_add_members" = "Añadir miembros";
|
||||
"lng_channel_add_banned" = "Suspender usuario";
|
||||
"lng_channel_add_restricted" = "Restringir usuario";
|
||||
"lng_channel_members" = "Miembros";
|
||||
"lng_channel_only_last_shown" = "Sólo {count:_not_used_|aparece el último miembro|aparecen los últimos # miembros}";
|
||||
"lng_channel_only_last_shown#one" = "Sólo aparece el último miembro";
|
||||
"lng_channel_only_last_shown#other" = "Sólo aparecen los últimos {count} miembros";
|
||||
"lng_channel_admins" = "Administradores";
|
||||
"lng_channel_add_admin" = "Añadir administrador";
|
||||
"lng_channel_admin_sure" = "¿Añadir a {user} como administrador?";
|
||||
"lng_channel_admins_too_much" = "Lo sentimos, alcanzaste el límite de administradores. Por favor, elimina un administrador primero.";
|
||||
"lng_channel_admin_status_creator" = "Creador";
|
||||
"lng_channel_admin_status_promoted_by" = "Ascendido por {user}";
|
||||
"lng_channel_admin_status_not_admin" = "No es administrador";
|
||||
|
||||
"lng_group_blocked_list_about" = "Los usuarios bloqueados son eliminados del grupo y sólo pueden volver si son invitados por un administrador.\n\nLos enlaces de invitación no funcionan para ellos.";
|
||||
"lng_group_blocked_list_about" = "Los usuarios suspendidos son eliminados del grupo y sólo pueden volver si son invitados por un administrador. \nLos enlaces de invitación no funcionan para ellos.";
|
||||
|
||||
"lng_chat_all_members_admins" = "Todos son administradores";
|
||||
"lng_chat_about_all_admins" = "Todos pueden añadir nuevos miembros, editar el nombre y la foto del grupo.";
|
||||
@@ -595,7 +667,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_participant_filter" = "Buscar";
|
||||
"lng_participant_invite" = "Invitar";
|
||||
"lng_participant_invite_sorry" = "Lo sentimos, sólo puedes añadir {count:_not_used|# miembros|# miembros} a un canal personalmente.\n\nAhora, las personas deben unirse con un enlace de invitación.";
|
||||
"lng_participant_invite_sorry#one" = "Lo sentimos, sólo puedes añadir a {count} miembro a un canal. \n\nAhora será necesario un enlace de invitación para unirse.";
|
||||
"lng_participant_invite_sorry#other" = "Lo sentimos, sólo puedes añadir a los primeros {count} miembros a un canal. \n\nAhora será necesario un enlace de invitación para unirse.";
|
||||
"lng_create_group_back" = "Atrás";
|
||||
"lng_create_group_next" = "Siguiente";
|
||||
"lng_create_group_create" = "Crear";
|
||||
@@ -618,8 +691,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_create_channel_link_available" = "Este enlace está disponible";
|
||||
"lng_create_channel_link_copied" = "Enlace copiado al portapapeles";
|
||||
|
||||
"lng_create_group_crop" = "Selecciona el área para la foto del grupo";
|
||||
"lng_create_channel_crop" = "Selecciona el área para la foto del canal";
|
||||
"lng_create_group_crop" = "Selecciona un área para la foto del grupo";
|
||||
"lng_create_channel_crop" = "Selecciona un área para la foto del canal";
|
||||
|
||||
"lng_failed_add_participant" = "No se pudo añadir al usuario. Por favor, reinténtalo más tarde.";
|
||||
"lng_failed_add_not_mutual" = "Lo sentimos, si una persona sale del grupo, sólo un contacto mutuo puede volver a invitarlo (necesitan tener tu número y tú el suyo).";
|
||||
@@ -637,8 +710,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_message_empty" = "Mensaje vacío";
|
||||
"lng_message_unsupported" = "Este mensaje no es soportado por tu versión de Telegram Desktop. Por favor, actualiza a la última versión desde Ajustes o instálala desde {link}";
|
||||
|
||||
"lng_duration_seconds" = "{count:_not_used_|# segundo|# segundos}";
|
||||
"lng_duration_minutes_seconds" = "{count_minutes:# min|# min|# min} {count_seconds:# s|# s|# s}";
|
||||
"lng_duration_seconds#one" = "{count} segundo";
|
||||
"lng_duration_seconds#other" = "{count} segundos";
|
||||
"lng_duration_minsec_minutes#one" = "{count} min";
|
||||
"lng_duration_minsec_minutes#other" = "{count} min";
|
||||
"lng_duration_minsec_seconds#one" = "{count} s";
|
||||
"lng_duration_minsec_seconds#other" = "{count} s";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_add_user" = "{from} añadió a {user}";
|
||||
"lng_action_add_users_many" = "{from} añadió a {users}";
|
||||
@@ -668,7 +746,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_video" = "un vídeo";
|
||||
"lng_action_pinned_media_audio" = "un audio";
|
||||
"lng_action_pinned_media_voice" = "un mensaje de voz";
|
||||
"lng_action_pinned_media_video_message" = "un mensaje de vídeo";
|
||||
"lng_action_pinned_media_video_message" = "un videomensaje";
|
||||
"lng_action_pinned_media_file" = "un archivo";
|
||||
"lng_action_pinned_media_gif" = "un GIF";
|
||||
"lng_action_pinned_media_contact" = "un contacto";
|
||||
@@ -676,18 +754,33 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_sticker" = "un sticker";
|
||||
"lng_action_pinned_media_emoji_sticker" = "un {emoji} sticker";
|
||||
"lng_action_pinned_media_game" = "el juego «{game}»";
|
||||
"lng_action_game_score" = "{from} consiguió {count:# puntos|# punto|# puntos} en {game}";
|
||||
"lng_action_game_you_scored" = "Conseguiste {count:# puntos|# punto|# puntos} en {game}";
|
||||
"lng_action_game_score_no_game" = "{from} consiguió {count:# puntos|# punto|# puntos}";
|
||||
"lng_action_game_you_scored_no_game" = "Conseguiste {count:# puntos|# punto|# puntos}";
|
||||
"lng_action_game_score#one" = "{from} consiguió {count} punto en {game}";
|
||||
"lng_action_game_score#other" = "{from} consiguió {count} puntos en {game}";
|
||||
"lng_action_game_you_scored#one" = "Conseguiste {count} punto en {game}";
|
||||
"lng_action_game_you_scored#other" = "Conseguiste {count} puntos en {game}";
|
||||
"lng_action_game_score_no_game#one" = "{from} consiguió {count} punto";
|
||||
"lng_action_game_score_no_game#other" = "{from} consiguió {count} puntos";
|
||||
"lng_action_game_you_scored_no_game#one" = "Conseguiste {count} punto";
|
||||
"lng_action_game_you_scored_no_game#other" = "Conseguiste {count} puntos";
|
||||
"lng_action_payment_done" = "Has transferido satisfactoriamente {amount} a {user}";
|
||||
"lng_action_payment_done_for" = "Has transferido satisfactoriamente {amount} a {name} por {invoice}";
|
||||
"lng_action_took_screenshot" = "¡{from} hizo una captura de pantalla!";
|
||||
"lng_action_you_took_screenshot" = "¡Hiciste una captura de pantalla!";
|
||||
|
||||
"lng_profile_migrate_reached" = "Límite de {count:_not_used_|# miembro|# miembros} alcanzado";
|
||||
"lng_ttl_photo_received" = "{from} te envió una foto con autodestrucción. Por favor, mírala en tu teléfono.";
|
||||
"lng_ttl_photo_sent" = "Enviaste una foto con autodestrucción";
|
||||
"lng_ttl_photo_expired" = "La foto expiró";
|
||||
"lng_ttl_video_received" = "{from} te envió un vídeo con autodestrucción. Por favor, míralo en tu teléfono.";
|
||||
"lng_ttl_video_sent" = "Enviaste un vídeo con autodestrucción";
|
||||
"lng_ttl_video_expired" = "El vídeo expiró";
|
||||
|
||||
"lng_profile_migrate_reached#one" = "Límite de {count} miembro alcanzado";
|
||||
"lng_profile_migrate_reached#other" = "Límite de {count} miembros alcanzado";
|
||||
"lng_profile_migrate_body" = "Para superar este límite, puedes convertir tu grupo en un supergrupo.";
|
||||
"lng_profile_migrate_learn_more" = "Saber más »";
|
||||
"lng_profile_migrate_about" = "Para superar el límite y tener características adicionales, conviértelo en un supergrupo:";
|
||||
"lng_profile_migrate_feature1" = "— Permiten hasta {count:_not_used_|# usuario|# usuarios}";
|
||||
"lng_profile_migrate_feature1#one" = "— Permiten hasta {count} usuario";
|
||||
"lng_profile_migrate_feature1#other" = "— Permiten hasta {count} usuarios";
|
||||
"lng_profile_migrate_feature2" = "— Nuevos miembros ven todo el historial";
|
||||
"lng_profile_migrate_feature3" = "— Un admin. borra mensajes para todos";
|
||||
"lng_profile_migrate_feature4" = "— Notificaciones silenciadas por defecto";
|
||||
@@ -702,7 +795,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_convert_feature4" = "— El creador puede generar un enlace público";
|
||||
"lng_profile_convert_warning" = "{bold_start}Importante:{bold_end} Esta acción no se puede deshacer";
|
||||
"lng_profile_convert_confirm" = "Convertir";
|
||||
"lng_profile_add_more_after_upgrade" = "Podrás añadir hasta {count:_not_used_|# miembro|# miembros} una vez que conviertas tu grupo en un supergrupo.";
|
||||
"lng_profile_add_more_after_upgrade#one" = "Podrás añadir hasta {count} miembro una vez que conviertas tu grupo en un supergrupo.";
|
||||
"lng_profile_add_more_after_upgrade#other" = "Podrás añadir hasta {count} miembros una vez que conviertas tu grupo en un supergrupo.";
|
||||
|
||||
"lng_channel_not_accessible" = "Lo sentimos, este canal no es accesible.";
|
||||
"lng_group_not_accessible" = "Lo sentimos, este grupo no es accesible.";
|
||||
@@ -717,7 +811,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_group_invite_want_join_channel" = "¿Quieres unirte al canal «{title}»?";
|
||||
"lng_group_invite_join" = "Unirme";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# miembro|# miembros}, entre ellos:";
|
||||
"lng_group_invite_members#one" = "{count} miembro, entre ellos:";
|
||||
"lng_group_invite_members#other" = "{count} miembros, entre ellos:";
|
||||
|
||||
"lng_group_invite_link" = "Enlace de invitación:";
|
||||
"lng_group_invite_create" = "Crear un enlace de invitación";
|
||||
@@ -730,6 +825,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_channel_public_link_copied" = "Enlace copiado al portapapeles.";
|
||||
|
||||
"lng_forwarded" = "Reenviado desde {user}";
|
||||
"lng_forwarded_date" = "Original: {date}";
|
||||
"lng_forwarded_channel" = "Reenviado desde {channel}";
|
||||
"lng_forwarded_via" = "Reenviado desde {user} vía {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Reenviado desde {channel} vía {inline_bot}";
|
||||
@@ -809,7 +905,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_stickers_you_have" = "Administrar y ordenar los packs de stickers";
|
||||
"lng_stickers_featured" = "Stickers destacados";
|
||||
"lng_stickers_return" = "Deshacer";
|
||||
"lng_stickers_count" = "{count:Cargando...|# sticker|# stickers}";
|
||||
"lng_stickers_count#one" = "{count} sticker";
|
||||
"lng_stickers_count#other" = "{count} stickers";
|
||||
"lng_stickers_masks_pack" = "Este es un pack de stickers de máscaras. Puedes usarlas en el editor de fotos de nuestras aplicaciones en móviles.";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
@@ -817,7 +914,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_in_dlg_audio_file" = "Audio";
|
||||
"lng_in_dlg_contact" = "Contacto";
|
||||
"lng_in_dlg_audio" = "Mensaje de voz";
|
||||
"lng_in_dlg_video_message" = "Mensaje de vídeo";
|
||||
"lng_in_dlg_video_message" = "Videomensaje";
|
||||
"lng_in_dlg_file" = "Archivo";
|
||||
"lng_in_dlg_sticker" = "Sticker";
|
||||
"lng_in_dlg_sticker_emoji" = "{emoji} Sticker";
|
||||
@@ -839,6 +936,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_cant_invite_banned" = "Sólo el administrador puede añadir a este usuario.";
|
||||
"lng_cant_invite_privacy" = "No puedes añadir a este usuario a grupos por sus ajustes de privacidad.";
|
||||
"lng_cant_invite_privacy_channel" = "No puedes añadir a este usuario a canales por sus ajustes de privacidad.";
|
||||
"lng_cant_delete_group#one" = "No es posible eliminar manualmente comunidades que tienen más de {count} miembro. Por favor, contacta al soporte de Telegram si quieres eliminar el grupo.";
|
||||
"lng_cant_delete_group#other" = "No es posible eliminar manualmente comunidades que tienen más de {count} miembros. Por favor, contacta al soporte de Telegram si quieres eliminar el grupo.";
|
||||
"lng_cant_delete_channel#one" = "No es posible eliminar manualmente comunidades que tienen más de {count} miembro. Por favor, contacta al soporte de Telegram si quieres eliminar el canal.";
|
||||
"lng_cant_delete_channel#other" = "No es posible eliminar manualmente comunidades que tienen más de {count} miembros. Por favor, contacta al soporte de Telegram si quieres eliminar el canal.";
|
||||
"lng_cant_do_this" = "Lo sentimos, esta acción no está disponible.";
|
||||
|
||||
"lng_send_button" = "Enviar";
|
||||
@@ -884,11 +985,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_typing" = "escribiendo";
|
||||
"lng_user_typing" = "{user} está escribiendo";
|
||||
"lng_users_typing" = "{user} y {second_user} están escribiendo";
|
||||
"lng_many_typing" = "{count:_not_used_|# está|# están} escribiendo";
|
||||
"lng_many_typing#one" = "{count} está escribiendo";
|
||||
"lng_many_typing#other" = "{count} están escribiendo";
|
||||
"lng_playing_game" = "jugando";
|
||||
"lng_user_playing_game" = "{user} está jugando";
|
||||
"lng_users_playing_game" = "{user} y {second_user} están jugando";
|
||||
"lng_many_playing_game" = "{count:_not_used_|# está|# están} jugando";
|
||||
"lng_many_playing_game#one" = "{count} está jugando";
|
||||
"lng_many_playing_game#other" = "{count} están jugando";
|
||||
"lng_send_action_record_video" = "grabando un vídeo";
|
||||
"lng_user_action_record_video" = "{user} está grabando un vídeo";
|
||||
"lng_send_action_upload_video" = "enviando un vídeo";
|
||||
@@ -897,10 +1000,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_record_audio" = "{user} está grabando un mensaje de voz";
|
||||
"lng_send_action_upload_audio" = "enviando un mensaje de voz";
|
||||
"lng_user_action_upload_audio" = "{user} está enviando un mensaje de voz";
|
||||
"lng_send_action_record_round" = "grabando un mensaje de vídeo";
|
||||
"lng_user_action_record_round" = "{user} está grabando un mensaje de vídeo";
|
||||
"lng_send_action_upload_round" = "enviando un mensaje de vídeo";
|
||||
"lng_user_action_upload_round" = "{user} está enviando un mensaje de vídeo";
|
||||
"lng_send_action_record_round" = "grabando un videomensaje";
|
||||
"lng_user_action_record_round" = "{user} está grabando un videomensaje";
|
||||
"lng_send_action_upload_round" = "enviando un videomensaje";
|
||||
"lng_user_action_upload_round" = "{user} está enviando un videomensaje";
|
||||
"lng_send_action_upload_photo" = "enviando una foto";
|
||||
"lng_user_action_upload_photo" = "{user} está enviando una foto";
|
||||
"lng_send_action_upload_file" = "enviando un archivo";
|
||||
@@ -909,7 +1012,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_geo_location" = "{user} está obteniendo una ubicación";
|
||||
"lng_send_action_choose_contact" = "eligiendo un contacto";
|
||||
"lng_user_action_choose_contact" = "{user} está eligiendo un contacto";
|
||||
"lng_unread_bar" = "{count:_not_used_|# mensaje sin leer|# mensajes sin leer}";
|
||||
"lng_unread_bar#one" = "{count} mensaje no leído";
|
||||
"lng_unread_bar#other" = "{count} mensajes no leídos";
|
||||
|
||||
"lng_maps_point" = "Ubicación";
|
||||
"lng_save_photo" = "Guardar imagen";
|
||||
@@ -932,7 +1036,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_from_top" = "Desanclar";
|
||||
|
||||
"lng_context_promote_admin" = "Nombrar administrador";
|
||||
"lng_context_remove_admin" = "Eliminar de los administradores";
|
||||
"lng_context_edit_permissions" = "Editar permisos";
|
||||
"lng_context_restrict_user" = "Restringir usuario";
|
||||
"lng_context_remove_from_group" = "Eliminar del grupo";
|
||||
|
||||
"lng_context_copy_link" = "Copiar enlace";
|
||||
@@ -970,31 +1075,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_msg" = "Desanclar mensaje";
|
||||
"lng_context_cancel_upload" = "Cancelar envío";
|
||||
"lng_context_copy_selected" = "Copiar el texto seleccionado";
|
||||
"lng_context_copy_selected_items" = "Copiar como texto";
|
||||
"lng_context_forward_selected" = "Reenviar lo seleccionado";
|
||||
"lng_context_delete_selected" = "Eliminar lo seleccionado";
|
||||
"lng_context_clear_selection" = "Eliminar selección";
|
||||
"lng_really_send_image" = "¿Quieres enviar esta imagen?";
|
||||
"lng_really_send_file" = "¿Quieres enviar este archivo?";
|
||||
"lng_really_share_contact" = "¿Quieres compartir este contacto?";
|
||||
"lng_send_images_compress" = "Comprimir {count:_not_used_|imagen|imágenes}";
|
||||
"lng_send_images_compress#one" = "Comprimir imagen";
|
||||
"lng_send_images_compress#other" = "Comprimir imágenes";
|
||||
"lng_send_image_non_local" = "No se pudo enviar el archivo remoto: {name}";
|
||||
"lng_send_image_empty" = "No se pudo enviar el archivo vacío: {name}";
|
||||
"lng_send_image_too_large" = "No se pudo enviar el archivo porque supera los 1500 MB: {name}";
|
||||
"lng_send_folder" = "No se pudo enviar «{name}», porque es un directorio :(";
|
||||
"lng_send_images_selected" = "{count:_not_used_|# imagen seleccionada|# imágenes seleccionadas}";
|
||||
"lng_send_photos" = "Enviar {count:_not_used_|# foto|# fotos}";
|
||||
"lng_send_files_selected" = "{count:_not_used_|# archivo seleccionado|# archivos seleccionados}";
|
||||
"lng_send_files" = "Enviar {count:_not_used_|# archivo|# archivos}";
|
||||
"lng_send_images_selected#one" = "{count} imagen seleccionada";
|
||||
"lng_send_images_selected#other" = "{count} imágenes seleccionadas";
|
||||
"lng_send_photos#one" = "Enviar {count} foto";
|
||||
"lng_send_photos#other" = "Enviar {count} fotos";
|
||||
"lng_send_files_selected#one" = "{count} archivo seleccionado";
|
||||
"lng_send_files_selected#other" = "{count} archivos seleccionados";
|
||||
"lng_send_files#one" = "Enviar {count} archivo";
|
||||
"lng_send_files#other" = "Enviar {count} archivos";
|
||||
|
||||
"lng_forward_choose" = "Elige un destinatario...";
|
||||
"lng_forward_cant" = "Lo sentimos, no puedes reenviar aquí :(";
|
||||
"lng_forward_confirm" = "¿Reenviar a {recipient}?";
|
||||
"lng_forward_share_contact" = "¿Compartir contacto con {recipient}?";
|
||||
"lng_forward_share_cant" = "No hay forma de compartir un contacto aquí :(";
|
||||
"lng_forward_send_file_confirm" = "¿Enviar «{name}» a {recipient}?";
|
||||
"lng_forward_send_files_confirm" = "¿Enviar los archivos seleccionados a {recipient}?";
|
||||
"lng_forward_send_files_cant" = "No hay forma de enviar multimedia aquí :(";
|
||||
"lng_forward_send" = "Enviar";
|
||||
"lng_forward_messages" = "{count:_not_used_|Mensaje adjunto|# mensajes adjuntos}";
|
||||
"lng_forwarding_from" = "{user} y {count:_not_used_|# otro|# otros}";
|
||||
"lng_forward_messages#one" = "{count} mensaje reenviado";
|
||||
"lng_forward_messages#other" = "{count} mensajes reenviados";
|
||||
"lng_forwarding_from#one" = "{user} y {count} otro";
|
||||
"lng_forwarding_from#other" = "{user} y {count} otros";
|
||||
"lng_forwarding_from_two" = "{user} y {second_user}";
|
||||
"lng_inline_switch_choose" = "Elige una conversación...";
|
||||
"lng_inline_switch_cant" = "Lo sentimos, no puedes escribir aquí :(";
|
||||
@@ -1016,6 +1131,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_contact_title" = "Editar nombre del contacto";
|
||||
"lng_edit_channel_title" = "Editar canal";
|
||||
"lng_edit_sign_messages" = "Firmar los mensajes";
|
||||
"lng_edit_group_who_invites" = "Quién puede añadir miembros";
|
||||
"lng_edit_group_invites_everybody" = "Todos los miembros";
|
||||
"lng_edit_group_invites_only_admins" = "Sólo administradores";
|
||||
"lng_edit_group" = "Editar grupo";
|
||||
"lng_edit_self_title" = "Editar tu nombre";
|
||||
"lng_confirm_contact_data" = "Nuevo contacto";
|
||||
@@ -1040,15 +1158,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_selected_clear" = "Cancelar";
|
||||
"lng_selected_delete" = "Eliminar";
|
||||
"lng_selected_forward" = "Reenviar";
|
||||
"lng_selected_count" = "{count:_not_used_|# mensaje|# mensajes}";
|
||||
"lng_selected_count#one" = "{count} mensaje";
|
||||
"lng_selected_count#other" = "{count} mensajes";
|
||||
"lng_selected_cancel_sure_this" = "¿Detener el envío?";
|
||||
"lng_selected_upload_stop" = "Detener";
|
||||
"lng_selected_delete_sure_this" = "¿Quieres eliminar este mensaje?";
|
||||
"lng_selected_delete_sure" = "¿Quieres eliminar {count:_not_used_|# mensaje|# mensajes}?";
|
||||
"lng_selected_delete_sure#one" = "¿Quieres eliminar {count} mensaje?";
|
||||
"lng_selected_delete_sure#other" = "¿Quieres eliminar {count} mensajes?";
|
||||
"lng_delete_photo_sure" = "¿Quieres eliminar esta foto?";
|
||||
"lng_delete_for_everyone_hint" = "Esto {count:_not_used_|lo|los} eliminará para todos en este chat.";
|
||||
"lng_delete_for_me_chat_hint" = "Esto {count:_not_used_|lo|los} eliminará sólo para ti, y no para los otros participantes del chat.";
|
||||
"lng_delete_for_me_hint" = "Esto {count:_not_used_|lo|los} eliminará sólo para ti.";
|
||||
"lng_delete_for_everyone_hint#one" = "Esto lo eliminará para todos en este chat.";
|
||||
"lng_delete_for_everyone_hint#other" = "Esto los eliminará para todos en este chat.";
|
||||
"lng_delete_for_me_chat_hint#one" = "Esto lo eliminará sólo para ti, no para los otros miembros del chat.";
|
||||
"lng_delete_for_me_chat_hint#other" = "Esto los eliminará sólo para ti, no para los otros miembros del chat.";
|
||||
"lng_delete_for_me_hint#one" = "Esto lo eliminará sólo para ti.";
|
||||
"lng_delete_for_me_hint#other" = "Esto los eliminará sólo para ti.";
|
||||
"lng_delete_for_everyone_check" = "Eliminar para todos";
|
||||
"lng_delete_for_other_check" = "Eliminar para {user}";
|
||||
"lng_box_delete" = "Eliminar";
|
||||
@@ -1060,7 +1183,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_about_text_3" = "Conoce más en las {faq_open}preguntas frecuentes de Telegram{faq_close}.";
|
||||
"lng_about_done" = "Hecho";
|
||||
|
||||
"lng_search_found_results" = "{count:No se encontraron mensajes|# mensaje encontrado|# mensajes encontrados}";
|
||||
"lng_search_no_results" = "No se encontraron mensajes";
|
||||
"lng_search_found_results#one" = "{count} mensaje encontrado";
|
||||
"lng_search_found_results#other" = "{count} mensajes encontrados";
|
||||
"lng_search_global_results" = "Resultados de la búsqueda global";
|
||||
|
||||
"lng_media_save_progress" = "{ready} de {total} {mb}";
|
||||
@@ -1169,11 +1294,133 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_player_message_yesterday" = "Ayer a las {time}";
|
||||
"lng_player_message_date" = "{date} a las {time}";
|
||||
|
||||
"lng_rights_edit_admin" = "Editar administrador";
|
||||
"lng_rights_edit_admin_header" = "¿Qué puede hacer este administrador?";
|
||||
"lng_rights_about_add_admins_yes" = "Este administrador podrá añadir administradores con los mismos (o menos) permisos.";
|
||||
"lng_rights_about_add_admins_no" = "Este administrador no podrá añadir administradores.";
|
||||
"lng_rights_about_admin_cant_edit" = "No puedes editar los permisos de este administrador.";
|
||||
"lng_rights_user_restrictions" = "Restricciones";
|
||||
"lng_rights_user_restrictions_header" = "¿Qué puede hacer este usuario?";
|
||||
|
||||
"lng_rights_channel_info" = "Cambiar información del canal";
|
||||
"lng_rights_channel_post" = "Publicar mensajes";
|
||||
"lng_rights_channel_edit" = "Editar mensajes de otros";
|
||||
"lng_rights_channel_delete" = "Eliminar mensajes de otros";
|
||||
"lng_rights_group_info" = "Cambiar información del grupo";
|
||||
"lng_rights_group_ban" = "Suspender usuarios";
|
||||
"lng_rights_group_invite_link" = "Invitar con un enlace";
|
||||
"lng_rights_group_invite" = "Añadir usuarios";
|
||||
"lng_rights_group_pin" = "Anclar mensajes";
|
||||
"lng_rights_group_delete" = "Eliminar mensajes";
|
||||
"lng_rights_add_admins" = "Añadir administradores";
|
||||
"lng_rights_chat_read" = "Leer mensajes";
|
||||
"lng_rights_chat_send_text" = "Enviar mensajes";
|
||||
"lng_rights_chat_send_media" = "Enviar multimedia";
|
||||
"lng_rights_chat_send_stickers" = "Enviar stickers y GIF";
|
||||
"lng_rights_chat_send_links" = "Enviar vista previa de enlaces";
|
||||
"lng_rights_chat_banned_until_header" = "Restringido hasta";
|
||||
"lng_rights_chat_banned_forever" = "Siempre";
|
||||
"lng_rights_chat_banned_day#one" = "Por {count} día";
|
||||
"lng_rights_chat_banned_day#other" = "Por {count} días";
|
||||
"lng_rights_chat_banned_week#one" = "Por {count} semana";
|
||||
"lng_rights_chat_banned_week#other" = "Por {count} semanas";
|
||||
"lng_rights_chat_banned_custom" = "Personalizado";
|
||||
"lng_rights_chat_banned_custom_date" = "Hasta el {date}";
|
||||
"lng_rights_chat_banned_block" = "Suspender y eliminar del grupo";
|
||||
|
||||
"lng_restricted_send_message" = "Los administradores del grupo han restringido que escribas.";
|
||||
"lng_restricted_send_media" = "Los administradores del grupo han restringido que envíes multimedia.";
|
||||
"lng_restricted_send_stickers" = "Los administradores del grupo han restringido que envíes stickers.";
|
||||
"lng_restricted_send_gifs" = "Los administradores del grupo han restringido que envíes GIF.";
|
||||
"lng_restricted_send_inline" = "Los administradores del grupo han restringido que envíes contenido integrado.";
|
||||
|
||||
"lng_restricted_list_title" = "Usuarios restringidos";
|
||||
"lng_banned_list_title" = "Usuarios suspendidos";
|
||||
|
||||
"lng_admin_log_title_all" = "Todas las acciones";
|
||||
"lng_admin_log_title_selected" = "Acciones seleccionadas";
|
||||
"lng_admin_log_filter" = "Filtrar";
|
||||
"lng_admin_log_filter_title" = "Filtrar";
|
||||
"lng_admin_log_filter_all_actions" = "Todas las acciones";
|
||||
"lng_admin_log_filter_restrictions" = "Nuevas restricciones";
|
||||
"lng_admin_log_filter_admins_new" = "Nuevos administradores";
|
||||
"lng_admin_log_filter_members_new" = "Nuevos miembros";
|
||||
"lng_admin_log_filter_info_group" = "Información del grupo";
|
||||
"lng_admin_log_filter_info_channel" = "Información del canal";
|
||||
"lng_admin_log_filter_messages_deleted" = "Mensajes eliminados";
|
||||
"lng_admin_log_filter_messages_edited" = "Mensajes editados";
|
||||
"lng_admin_log_filter_messages_pinned" = "Mensajes anclados";
|
||||
"lng_admin_log_filter_members_removed" = "Miembros eliminados";
|
||||
"lng_admin_log_filter_all_admins" = "Todos los usuarios";
|
||||
"lng_admin_log_about" = "¿Qué es esto?";
|
||||
"lng_admin_log_about_text" = "Esta es una lista de las acciones de servicio realizadas por los miembros y administradores del grupo en las últimas 48 horas.";
|
||||
"lng_admin_log_no_results_title" = "No se encontraron acciones";
|
||||
"lng_admin_log_no_results_text" = "No se encontraron acciones que coincidan con tu solicitud.";
|
||||
"lng_admin_log_no_results_search_text" = "No se encontraron acciones que contengan “{query}”.";
|
||||
"lng_admin_log_no_events_title" = "Aún no hay acciones";
|
||||
"lng_admin_log_no_events_text" = "Los miembros y administradores\nno han realizado acciones de \nservicio en las últimas 48 horas.";
|
||||
|
||||
"lng_admin_log_empty_text" = "Vacío";
|
||||
"lng_admin_log_changed_title_group" = "{from} cambió el nombre del grupo a «{title}»";
|
||||
"lng_admin_log_changed_title_channel" = "{from} cambió el nombre del canal a «{title}»";
|
||||
"lng_admin_log_changed_description_group" = "{from} editó la descripción del grupo:";
|
||||
"lng_admin_log_removed_description_group" = "{from} eliminó la descripción del grupo";
|
||||
"lng_admin_log_changed_description_channel" = "{from} editó la descripción del canal:";
|
||||
"lng_admin_log_removed_description_channel" = "{from} eliminó la descripción del canal";
|
||||
"lng_admin_log_previous_description" = "Descripción anterior";
|
||||
"lng_admin_log_changed_link_group" = "{from} cambió el enlace del grupo:";
|
||||
"lng_admin_log_removed_link_group" = "{from} eliminó el enlace del grupo";
|
||||
"lng_admin_log_changed_link_channel" = "{from} cambió el enlace del canal:";
|
||||
"lng_admin_log_removed_link_channel" = "{from} eliminó el enlace del canal";
|
||||
"lng_admin_log_previous_link" = "Enlace previo";
|
||||
"lng_admin_log_changed_photo_group" = "{from} cambió la foto de grupo";
|
||||
"lng_admin_log_changed_photo_channel" = "{from} cambió la foto del canal";
|
||||
"lng_admin_log_removed_photo_group" = "{from} eliminó la foto del grupo";
|
||||
"lng_admin_log_removed_photo_channel" = "{from} eliminó la foto del canal";
|
||||
"lng_admin_log_invites_enabled" = "{from} permitió las invitaciones";
|
||||
"lng_admin_log_invites_disabled" = "{from} desactivó las invitaciones";
|
||||
"lng_admin_log_signatures_enabled" = "{from} activó las firmas";
|
||||
"lng_admin_log_signatures_disabled" = "{from} desactivó las firmas";
|
||||
"lng_admin_log_pinned_message" = "{from} ancló un mensaje:";
|
||||
"lng_admin_log_unpinned_message" = "{from} desancló un mensaje";
|
||||
"lng_admin_log_edited_caption" = "{from} editó un comentario:";
|
||||
"lng_admin_log_removed_caption" = "{from} eliminó un comentario";
|
||||
"lng_admin_log_previous_caption" = "Comentario original";
|
||||
"lng_admin_log_edited_message" = "{from} editó un mensaje:";
|
||||
"lng_admin_log_previous_message" = "Mensaje original";
|
||||
"lng_admin_log_deleted_message" = "{from} eliminó un mensaje:";
|
||||
"lng_admin_log_participant_joined" = "{from} se unió al grupo";
|
||||
"lng_admin_log_participant_joined_channel" = "{from} se unió al canal";
|
||||
"lng_admin_log_participant_left" = "{from} dejó el grupo";
|
||||
"lng_admin_log_participant_left_channel" = "{from} dejó el canal";
|
||||
"lng_admin_log_invited" = "invitó a {user}";
|
||||
"lng_admin_log_banned" = "suspendió a {user}";
|
||||
"lng_admin_log_restricted" = "cambió las restricciones de {user} {until}";
|
||||
"lng_admin_log_promoted" = "cambió los privilegios de {user}";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_restricted_forever" = "indefinidamente";
|
||||
"lng_admin_log_restricted_until" = "hasta el {date}";
|
||||
"lng_admin_log_banned_view_messages" = "Leer mensajes";
|
||||
"lng_admin_log_banned_send_messages" = "Enviar mensajes";
|
||||
"lng_admin_log_banned_send_media" = "Enviar multimedia";
|
||||
"lng_admin_log_banned_send_stickers" = "Enviar stickers y GIF";
|
||||
"lng_admin_log_banned_embed_links" = "Enviar vista previa de enlaces";
|
||||
"lng_admin_log_admin_change_info" = "Cambiar información";
|
||||
"lng_admin_log_admin_post_messages" = "Publicar mensajes";
|
||||
"lng_admin_log_admin_edit_messages" = "Editar mensajes";
|
||||
"lng_admin_log_admin_delete_messages" = "Eliminar mensajes";
|
||||
"lng_admin_log_admin_ban_users" = "Suspender usuarios";
|
||||
"lng_admin_log_admin_invite_users" = "Añadir usuarios";
|
||||
"lng_admin_log_admin_invite_link" = "Invitar con un enlace";
|
||||
"lng_admin_log_admin_pin_messages" = "Anclar mensajes";
|
||||
"lng_admin_log_admin_add_admins" = "Añadir administradores";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "Información";
|
||||
"lng_profile_group_info" = "Información";
|
||||
"lng_profile_channel_info" = "Información";
|
||||
"lng_channel_add_admins" = "Nuevo administrador";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_menu_update" = "Aggiorna";
|
||||
"lng_menu_restart" = "Riavvia";
|
||||
"lng_menu_back" = "Indietro";
|
||||
"lng_menu_night_mode" = "Modalità notte";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Disattiva notifiche";
|
||||
"lng_enable_notifications_from_tray" = "Attiva notifiche";
|
||||
@@ -88,7 +89,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_continue" = "Continua";
|
||||
"lng_close" = "Chiudi";
|
||||
"lng_connecting" = "Connetto...";
|
||||
"lng_reconnecting" = "Riconnetto {count:ora|tra # s|tra # s}...";
|
||||
"lng_connecting_to_proxy" = "Connetto al proxy...";
|
||||
"lng_connecting_settings" = "Impostazioni";
|
||||
"lng_reconnecting#one" = "Riconnetto tra {count} s...";
|
||||
"lng_reconnecting#other" = "Riconnetto tra {count} s...";
|
||||
"lng_reconnecting_try_now" = "Prova ora";
|
||||
|
||||
"lng_status_service_notifications" = "notifiche di servizio";
|
||||
@@ -102,8 +106,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_last_month" = "ultimo accesso entro un mese";
|
||||
"lng_status_invisible" = "invisibile";
|
||||
"lng_status_lastseen_now" = "ultimo accesso adesso";
|
||||
"lng_status_lastseen_minutes" = "ultimo accesso {count:_not_used_|# minuto|# minuti} fa";
|
||||
"lng_status_lastseen_hours" = "ultimo accesso {count:_not_used_|# ora|# ore} fa";
|
||||
"lng_status_lastseen_minutes#one" = "ultimo accesso {count} minuto fa";
|
||||
"lng_status_lastseen_minutes#other" = "ultimo accesso {count} minuti fa";
|
||||
"lng_status_lastseen_hours#one" = "ultimo accesso {count} ora fa";
|
||||
"lng_status_lastseen_hours#other" = "ultimo accesso {count} ore fa";
|
||||
"lng_status_lastseen_today" = "ultimo accesso oggi alle {time}";
|
||||
"lng_status_lastseen_yesterday" = "ultimo accesso ieri alle {time}";
|
||||
"lng_status_lastseen_date" = "ultimo accesso {date}";
|
||||
@@ -112,24 +118,43 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_connecting" = "connetto...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "gruppo inaccessibile";
|
||||
"lng_chat_status_members" = "{count:nessun membro|# membro|# membri}";
|
||||
"lng_chat_status_members_online" = "{count:_not_used_|# membro|# membri}, {count_online:_not_used_|# in linea|# in linea}";
|
||||
"lng_chat_status_no_members" = "nessun membro";
|
||||
"lng_chat_status_members#one" = "{count} membro";
|
||||
"lng_chat_status_members#other" = "{count} membri";
|
||||
"lng_chat_status_online#one" = "{count} in linea";
|
||||
"lng_chat_status_online#other" = "{count} in linea";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
|
||||
"lng_channel_status" = "canale";
|
||||
"lng_group_status" = "gruppo";
|
||||
|
||||
"lng_channel_members_link" = "{count:_not_used_|# membro|# membri}";
|
||||
"lng_channel_admins_link" = "{count:_not_used_|# amministratore|# amministratori}";
|
||||
"lng_channel_members_link#one" = "{count} membro";
|
||||
"lng_channel_members_link#other" = "{count} membri";
|
||||
"lng_channel_admins_link#one" = "{count} amministratore";
|
||||
"lng_channel_admins_link#other" = "{count} amministratori";
|
||||
|
||||
"lng_server_error" = "Errore interno del server.";
|
||||
"lng_flood_error" = "Troppi tentativi. Per favore riprova più tardi.";
|
||||
"lng_gif_error" = "C'è stato un errore nel leggere la GIF :(";
|
||||
"lng_gif_error" = "Si è verificato un errore nel leggere la GIF :(";
|
||||
"lng_edit_error" = "Non puoi modificare questo messaggio";
|
||||
"lng_join_channel_error" = "Spiacenti, ti sei unito a troppi canali e supergruppi. Per favore lasciane qualcuno prima di unirti.";
|
||||
"lng_error_phone_flood" = "Spiacenti, hai eliminato e ricreato il tuo account troppe volte di recente. Per favore attendi alcuni giorni prima di iscriverti di nuovo.";
|
||||
"lng_error_start_minimized_passcoded" = "Hai inserito un codice di blocco, quindi l'app non può essere avviata minimizzata. L'app ti chiederà il codice prima di potersi avviare.";
|
||||
"lng_error_pinned_max" = "Spiacenti, non puoi fissare in alto più di {count:_not_used_|# chat|# chat}.";
|
||||
"lng_error_pinned_max#one" = "Spiacenti, non puoi fissare in alto più di {count} chat.";
|
||||
"lng_error_pinned_max#other" = "Spiacenti, non puoi fissare in alto più di {count} chat.";
|
||||
"lng_error_public_groups_denied" = "Sfortunatamente, non ti è permesso partecipare ai gruppi pubblici.\n{more_info}";
|
||||
"lng_error_cant_edit_admin" = "Spiacenti, non puoi modificare le autorizzazioni di questo amministratore.";
|
||||
"lng_error_cant_add_member" = "Spiacenti, non puoi aggiungere il bot a questo gruppo. Chiedi ad un amministratore di farlo.";
|
||||
"lng_error_cant_add_bot" = "Spiacenti, questo bot non può essere aggiunto ai gruppi.";
|
||||
"lng_error_cant_add_admin_invite" = "Spiacenti, non puoi aggiungere questo utente come amministratore perché non è un membro del gruppo e non sei autorizzato ad invitarlo.";
|
||||
"lng_error_cant_add_admin_unban" = "Spiacenti, non puoi aggiungere questo utente come amministratore perché è bloccato e non puoi sbloccarlo.";
|
||||
"lng_error_cant_ban_admin" = "Spiacenti, non puoi bloccare questo utente perché è un amministratore in questo gruppo e non sei autorizzato a degradarlo.";
|
||||
"lng_sure_add_admin_invite" = "Questo utente non è membro del gruppo. Vuoi aggiungerlo e promuoverlo ad amministratore?";
|
||||
"lng_sure_add_admin_unban" = "Questo utente è limitato o bloccato nel gruppo. Sei sicuro di volerlo sbloccare e promuoverlo?";
|
||||
"lng_sure_ban_admin" = "Questo utente è un amministratore nel gruppo. Sei sicuro di voler proseguire e limitarlo?";
|
||||
"lng_sure_ban_user_group" = "Bloccare {user} nel gruppo?";
|
||||
"lng_sure_enable_socks" = "Sei sicuro di voler attivare questo proxy?\n\nServer: {server}\nPorta: {port}\n\nPuoi cambiare il tuo server proxy più tardi nelle Impostazioni (Tipo di connessione).";
|
||||
"lng_sure_enable" = "Attiva";
|
||||
|
||||
"lng_edit_deleted" = "Questo messaggio è stato eliminato";
|
||||
"lng_edit_too_long" = "Il tuo messaggio è troppo lungo";
|
||||
@@ -198,9 +223,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_signin_sure_reset" = "Attenzione!\n\nPerderai tutte le chat e i messaggi, insieme a tutti i media e i file condivisi!\n\nVuoi ripristinare il tuo account?";
|
||||
"lng_signin_reset" = "Ripristina";
|
||||
"lng_signin_reset_wait" = "Dato che l'account {phone_number} è attivo e protetto da una password, lo elimineremo tra 1 settimana per motivi di sicurezza. Puoi annullare questo processo in qualsiasi momento.\n\nPotrai ripristinare il tuo account tra:\n{when}";
|
||||
"lng_signin_reset_in_days" = "{count_days:0 giorni|# giorno|# giorni} {count_hours:0 ore|# ora|# ore} {count_minutes:0 minuti|# minuto|# minuti}";
|
||||
"lng_signin_reset_in_hours" = "{count_hours:0 ore|# ora|# ore} {count_minutes:0 minuti|# minuto|# minuti}";
|
||||
"lng_signin_reset_in_minutes" = "{count_minutes:0 minuti|# minuto|# minuti}";
|
||||
"lng_signin_reset_days#one" = "{count} giorno";
|
||||
"lng_signin_reset_days#other" = "{count} giorni";
|
||||
"lng_signin_reset_hours#one" = "{count} ora";
|
||||
"lng_signin_reset_hours#other" = "{count} ore";
|
||||
"lng_signin_reset_minutes#one" = "{count} minuto";
|
||||
"lng_signin_reset_minutes#other" = "{count} minuti";
|
||||
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
|
||||
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
|
||||
"lng_signin_reset_cancelled" = "I tuoi tentativi recenti di ripristinare questo account sono stati annullati dal suo utente attivo. Per favore riprova tra 7 giorni.";
|
||||
|
||||
"lng_signup_title" = "Le tue info";
|
||||
@@ -223,7 +253,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_settings_save" = "Salva";
|
||||
"lng_settings_upload" = "Imposta foto profilo";
|
||||
"lng_settings_crop_profile" = "Seleziona un riquadro per la tua foto profilo";
|
||||
"lng_settings_crop_profile" = "Seleziona un'area per la tua foto profilo";
|
||||
"lng_settings_uploading_photo" = "Carico foto...";
|
||||
"lng_settings_edit" = "Modifica";
|
||||
"lng_settings_drop_area_subtitle" = "per impostarla come foto profilo";
|
||||
@@ -241,10 +271,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_username_link" = "Questo link apre una chat con te:";
|
||||
"lng_username_copied" = "Link copiato negli appunti.";
|
||||
|
||||
"lng_bio_title" = "Modifica la tua bio";
|
||||
"lng_bio_placeholder" = "Bio";
|
||||
"lng_bio_about" = "Puoi aggiungere qualche riga su di te. Chiunque apra il tuo profilo vedrà questo testo.";
|
||||
|
||||
"lng_settings_section_info" = "Info";
|
||||
"lng_settings_phone_number" = "Numero di telefono:";
|
||||
"lng_settings_username" = "Username:";
|
||||
"lng_settings_choose_username" = "Scegli username";
|
||||
"lng_settings_empty_bio" = "Nessuna";
|
||||
|
||||
"lng_settings_section_notify" = "Notifiche";
|
||||
"lng_settings_desktop_notify" = "Notifiche desktop";
|
||||
@@ -303,7 +338,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_backgrounds_header" = "Scegli un nuovo sfondo per la chat";
|
||||
"lng_theme_sure_keep" = "Mantenere questo tema?";
|
||||
"lng_theme_reverting" = "Ripristino il vecchio tema tra {count:_not_used_|# secondo|# secondi}.";
|
||||
"lng_theme_reverting#one" = "Ripristino il vecchio tema tra {count} secondo.";
|
||||
"lng_theme_reverting#other" = "Ripristino il vecchio tema tra {count} secondi.";
|
||||
"lng_theme_keep_changes" = "Mantieni modifiche";
|
||||
"lng_theme_revert" = "Ripristina";
|
||||
|
||||
@@ -329,14 +365,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_local_storage_title" = "Archivio locale";
|
||||
"lng_settings_no_data_cached" = "Non ci sono dati nella cache!";
|
||||
"lng_settings_images_cached" = "{count:_not_used_|# immagine|# immagini}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|# messaggio vocale|# messaggi vocali}, {size}";
|
||||
"lng_settings_images_cached#one" = "{count} immagine, {size}";
|
||||
"lng_settings_images_cached#other" = "{count} immagini, {size}";
|
||||
"lng_settings_audios_cached#one" = "{count} messaggio vocale, {size}";
|
||||
"lng_settings_audios_cached#other" = "{count} messaggi vocali, {size}";
|
||||
"lng_local_storage_clear" = "Elimina tutto";
|
||||
"lng_local_storage_clearing" = "Elimino...";
|
||||
"lng_local_storage_cleared" = "Eliminato!";
|
||||
"lng_local_storage_clear_failed" = "Eliminazione fallita :(";
|
||||
|
||||
"lng_settings_section_advanced_settings" = "Impostazioni avanzate";
|
||||
"lng_settings_enable_night_theme" = "Attiva la modalità notte";
|
||||
"lng_settings_disable_night_theme" = "Disattiva la modalità notte";
|
||||
|
||||
"lng_passcode_remove_button" = "Rimuovi";
|
||||
|
||||
@@ -348,8 +388,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_passcode_autolock" = "Blocco automatico";
|
||||
"lng_passcode_autolock_away" = "Blocco automatico se lontano per:";
|
||||
"lng_passcode_autolock_inactive" = "Blocco automatico se inattivo per:";
|
||||
"lng_passcode_autolock_minutes" = "{count:_not_used_|# minuto|# minuti}";
|
||||
"lng_passcode_autolock_hours" = "{count:_not_used_|# ora|# ore}";
|
||||
"lng_passcode_autolock_minutes#one" = "{count} minuto";
|
||||
"lng_passcode_autolock_minutes#other" = "{count} minuti";
|
||||
"lng_passcode_autolock_hours#one" = "{count} ora";
|
||||
"lng_passcode_autolock_hours#other" = "{count} ore";
|
||||
"lng_passcode_enter_old" = "Inserisci il codice attuale";
|
||||
"lng_passcode_enter_first" = "Inserisci un codice";
|
||||
"lng_passcode_enter_new" = "Inserisci il nuovo codice";
|
||||
@@ -419,7 +461,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_settings_reset_one_sure" = "Vuoi terminare questa sessione?";
|
||||
"lng_settings_reset_button" = "Chiudi";
|
||||
"lng_settings_reset_done" = "Altre sessioni terminate";
|
||||
"lng_settings_manage_local_storage" = "Gestisci archivio locale";
|
||||
"lng_settings_manage_local_storage" = "Gestisci l'archivio locale";
|
||||
"lng_settings_ask_question" = "Fai una domanda";
|
||||
"lng_settings_ask_sure" = "Per favore nota che l'assistenza di Telegram è fornita da volontari. Proviamo a rispondere quanto prima, ma potrebbe volerci del tempo.\n\nDai un'occhiata alle domande frequenti di Telegram: contengono suggerimenti importanti per risolvere i problemi e risposte a quasi tutte le domande.";
|
||||
"lng_settings_faq_button" = "Domande frequenti";
|
||||
@@ -455,32 +497,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_privacy_lastseen_title" = "Ultimo accesso";
|
||||
"lng_edit_privacy_lastseen_description" = "Puoi decidere chi può vedere il tuo ultimo accesso:";
|
||||
"lng_edit_privacy_lastseen_warning" = "Importante: non potrai vedere l'ultimo accesso delle persone con cui non condividi l'ultimo accesso. Verrà mostrato un orario approssimativo (di recente, entro una settimana, entro un mese).";
|
||||
"lng_edit_privacy_lastseen_always" = "Condividi con{count:| # utente| # utenti}";
|
||||
"lng_edit_privacy_lastseen_never" = "Non condividere con{count:| # utente| # utenti}";
|
||||
"lng_edit_privacy_lastseen_always_empty" = "Condividi con";
|
||||
"lng_edit_privacy_lastseen_always#one" = "Condividi con {count} utente";
|
||||
"lng_edit_privacy_lastseen_always#other" = "Condividi con {count} utenti";
|
||||
"lng_edit_privacy_lastseen_never_empty" = "Non condividere con";
|
||||
"lng_edit_privacy_lastseen_never#one" = "Non condividere con {count} utente";
|
||||
"lng_edit_privacy_lastseen_never#other" = "Non condividere con {count} utenti";
|
||||
"lng_edit_privacy_lastseen_exceptions" = "Queste impostazioni annulleranno i valori precedenti.";
|
||||
"lng_edit_privacy_lastseen_always_title" = "Condividi con";
|
||||
"lng_edit_privacy_lastseen_never_title" = "Non condividere co";
|
||||
|
||||
"lng_edit_privacy_groups_title" = "Gruppi";
|
||||
"lng_edit_privacy_groups_description" = "Puoi decidere chi può aggiungerti a gruppi e canali con precisione granulare:";
|
||||
"lng_edit_privacy_groups_always" = "Consenti sempre{count:| # utente| # utenti}";
|
||||
"lng_edit_privacy_groups_never" = "Non consentire mai{count:| # utente| # utenti}";
|
||||
"lng_edit_privacy_groups_always_empty" = "Consenti sempre";
|
||||
"lng_edit_privacy_groups_always#one" = "Consenti sempre {count} utente";
|
||||
"lng_edit_privacy_groups_always#other" = "Consenti sempre {count} utenti";
|
||||
"lng_edit_privacy_groups_never_empty" = "Non consentire mai";
|
||||
"lng_edit_privacy_groups_never#one" = "Non consentire mai {count} utente";
|
||||
"lng_edit_privacy_groups_never#other" = "Non consentire mai {count} utenti";
|
||||
"lng_edit_privacy_groups_exceptions" = "Questi utenti potranno o non potranno aggiungerti a gruppi e canali indipendentemente dalle impostazioni precedenti.";
|
||||
"lng_edit_privacy_groups_always_title" = "Consenti sempre";
|
||||
"lng_edit_privacy_groups_never_title" = "Non consentire mai";
|
||||
|
||||
"lng_edit_privacy_calls_title" = "Privacy chiamate";
|
||||
"lng_edit_privacy_calls_description" = "Puoi decidere chi può chiamarti:";
|
||||
"lng_edit_privacy_calls_always" = "Consenti sempre{count:| # utente| # utenti}";
|
||||
"lng_edit_privacy_calls_never" = "Non consentire mai{count:| # utente| # utenti}";
|
||||
"lng_edit_privacy_calls_always_empty" = "Consenti sempre";
|
||||
"lng_edit_privacy_calls_always#one" = "Consenti sempre {count} utente";
|
||||
"lng_edit_privacy_calls_always#other" = "Consenti sempre {count} utenti";
|
||||
"lng_edit_privacy_calls_never_empty" = "Non consentire mai";
|
||||
"lng_edit_privacy_calls_never#one" = "Non consentire mai {count} utente";
|
||||
"lng_edit_privacy_calls_never#other" = "Non consentire mai {count} utenti";
|
||||
"lng_edit_privacy_calls_exceptions" = "Questi utenti potranno o non potranno chiamarti indipendentemente dalle impostazioni precedenti.";
|
||||
"lng_edit_privacy_calls_always_title" = "Consenti sempre";
|
||||
"lng_edit_privacy_calls_never_title" = "Non consentire mai";
|
||||
|
||||
"lng_self_destruct_title" = "Autodistruzione account";
|
||||
"lng_self_destruct_description" = "Se non ti connetti almeno una volta in questo periodo, il tuo account verrà eliminato insieme a tutti i gruppi, i messaggi e i contatti.";
|
||||
"lng_self_destruct_months" = "{count:_not_used_|# mese|# mesi}";
|
||||
"lng_self_destruct_years" = "{count:_not_used_|# anno|# anni}";
|
||||
"lng_self_destruct_months#one" = "{count} mese";
|
||||
"lng_self_destruct_months#other" = "{count} mesi";
|
||||
"lng_self_destruct_years#one" = "{count} anno";
|
||||
"lng_self_destruct_years#other" = "{count} anni";
|
||||
|
||||
"lng_change_phone_title" = "Cambia numero di telefono";
|
||||
"lng_change_phone_description" = "Puoi cambiare il tuo numero di telefono\nqui. Il tuo account e tutti i tuoi dati cloud\n— messaggi, file, contatti, etc. saranno\ntrasferiti sul nuovo numero.\n\n[b]Importante[/b]: a tutti i tuoi contatti di Telegram\nverrà aggiunto il tuo [b]nuovo numero[/b] ai contatti,\npurché abbiano il tuo vecchio numero e\ntu non li abbia bloccati su Telegram.";
|
||||
@@ -506,15 +562,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_link_section" = "Link d'invito";
|
||||
"lng_profile_create_public_link" = "Crea link pubblico";
|
||||
"lng_profile_edit_public_link" = "Modifica link pubblico";
|
||||
"lng_profile_manage_admins" = "Gestisci amministratori";
|
||||
"lng_profile_manage_blocklist" = "Gestisci utenti bloccati";
|
||||
"lng_profile_common_groups" = "{count:_not_used_|# gruppo|# gruppi} in comune";
|
||||
"lng_profile_search_members" = "Cerca membri";
|
||||
"lng_profile_manage_admins" = "Gestisci gli amministratori";
|
||||
"lng_profile_manage_blocklist" = "Gestisci gli utenti bloccati";
|
||||
"lng_profile_manage_restrictedlist" = "Gestisci gli utenti limitati";
|
||||
"lng_profile_recent_actions" = "Azioni recenti";
|
||||
"lng_profile_common_groups#one" = "{count} gruppo in comune";
|
||||
"lng_profile_common_groups#other" = "{count} gruppi in comune";
|
||||
"lng_profile_common_groups_section" = "Gruppi in comune";
|
||||
"lng_profile_participants_section" = "Membri";
|
||||
"lng_profile_info_section" = "Info";
|
||||
"lng_profile_mobile_number" = "Cellulare:";
|
||||
"lng_profile_username" = "Username:";
|
||||
"lng_profile_link" = "Link:";
|
||||
"lng_profile_bio" = "Bio:";
|
||||
"lng_profile_add_contact" = "Aggiungi contatto";
|
||||
"lng_profile_edit_contact" = "Modifica";
|
||||
"lng_profile_enable_notifications" = "Notifiche";
|
||||
@@ -542,23 +603,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_delete_and_exit" = "Esci";
|
||||
"lng_profile_kick" = "Rimuovi";
|
||||
"lng_profile_admin" = "amministratore";
|
||||
"lng_profile_edit_permissions" = "Modifica";
|
||||
"lng_profile_sure_kick" = "Rimuovere {user} dal gruppo?";
|
||||
"lng_profile_sure_kick_channel" = "Rimuovere {user} dal canale?";
|
||||
"lng_profile_sure_kick_admin" = "Rimuovere {user} dagli amministratori?";
|
||||
"lng_profile_loading" = "Carico...";
|
||||
"lng_profile_shared_media" = "Media condivisi";
|
||||
"lng_profile_no_media" = "Nessun media in questa chat.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# foto|# foto}";
|
||||
"lng_profile_photos#one" = "{count} foto";
|
||||
"lng_profile_photos#other" = "{count} foto";
|
||||
"lng_profile_photos_header" = "Foto";
|
||||
"lng_profile_videos" = "{count:_not_used_|# video|# video}";
|
||||
"lng_profile_videos#one" = "{count} video";
|
||||
"lng_profile_videos#other" = "{count} video";
|
||||
"lng_profile_videos_header" = "Video";
|
||||
"lng_profile_songs" = "{count:_not_used_|# file audio|# file audio}";
|
||||
"lng_profile_songs#one" = "{count} file audio";
|
||||
"lng_profile_songs#other" = "{count} file audio";
|
||||
"lng_profile_songs_header" = "File audio";
|
||||
"lng_profile_files" = "{count:_not_used_|# file|# file}";
|
||||
"lng_profile_files#one" = "{count} file";
|
||||
"lng_profile_files#other" = "{count} file";
|
||||
"lng_profile_files_header" = "File";
|
||||
"lng_profile_audios" = "{count:_not_used_|# messaggio vocale|# messaggi vocali}";
|
||||
"lng_profile_audios#one" = "{count} messaggio vocale";
|
||||
"lng_profile_audios#other" = "{count} messaggi vocali";
|
||||
"lng_profile_audios_header" = "Messaggi vocali";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# link condiviso|# link condivisi}";
|
||||
"lng_profile_shared_links#one" = "{count} link condiviso";
|
||||
"lng_profile_shared_links#other" = "{count} link condivisi";
|
||||
"lng_profile_shared_links_header" = "Link condivisi";
|
||||
"lng_profile_copy_phone" = "Copia numero di telefono";
|
||||
"lng_profile_copy_fullname" = "Copia nome";
|
||||
@@ -578,16 +646,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_report_button" = "Segnala";
|
||||
"lng_report_thanks" = "Grazie! La tua segnalazione sarà presto esaminata dal nostro team.";
|
||||
|
||||
"lng_channel_add_admins" = "Nuovo amministratore";
|
||||
"lng_channel_add_members" = "Aggiungi membri";
|
||||
"lng_channel_add_banned" = "Blocca utente";
|
||||
"lng_channel_add_restricted" = "Limita utente";
|
||||
"lng_channel_members" = "Membri";
|
||||
"lng_channel_only_last_shown" = "Solo {count:_not_used_|l'ultimo membro è mostrato|gli ultimi # membri sono mostrati} qui";
|
||||
"lng_channel_only_last_shown#one" = "Solo l'ultimo membro è mostrato qui";
|
||||
"lng_channel_only_last_shown#other" = "Solo gli ultimi {count} membri sono mostrati qui";
|
||||
"lng_channel_admins" = "Amministratori";
|
||||
"lng_channel_add_admin" = "Aggiungi amministratore";
|
||||
"lng_channel_admin_sure" = "Aggiungere {user} agli amministratori?";
|
||||
"lng_channel_admins_too_much" = "Spiacenti, hai raggiunto il limite di amministratori. Prima devi rimuoverne qualcuno.";
|
||||
"lng_channel_admin_status_creator" = "Creatore";
|
||||
"lng_channel_admin_status_promoted_by" = "Promosso da {user}";
|
||||
"lng_channel_admin_status_not_admin" = "Non amministratore";
|
||||
|
||||
"lng_group_blocked_list_about" = "Gli utenti bloccati sono rimossi dal gruppo\ne possono rientrare solo se\ninvitati da un amministratore.\nI link di invito non funzionano per loro.";
|
||||
"lng_group_blocked_list_about" = "Gli utenti bloccati sono rimossi dal gruppo e possono rientrare solo se invitati da un amministratore.\nI link di invito non funzionano per loro.";
|
||||
|
||||
"lng_chat_all_members_admins" = "Tutti sono amministratori";
|
||||
"lng_chat_about_all_admins" = "Tutti i membri possono aggiungere nuovi membri, modificare nome e foto del gruppo.";
|
||||
@@ -595,7 +667,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_participant_filter" = "Cerca";
|
||||
"lng_participant_invite" = "Invita";
|
||||
"lng_participant_invite_sorry" = "Spiacenti, puoi aggiungere solo {count:_not_used|il primo membro|i primi # membri} a un canale.\n\nDa adesso, le persone potranno unirsi tramite il tuo link d'invito.";
|
||||
"lng_participant_invite_sorry#one" = "Spiacenti, puoi aggiungere solo il primo membro a un canale.\n\nDa adesso, le persone potranno unirsi tramite il tuo link d'invito.";
|
||||
"lng_participant_invite_sorry#other" = "Spiacenti, puoi aggiungere solo i primi {count} membri a un canale.\n\nDa adesso, le persone potranno unirsi tramite il tuo link d'invito.";
|
||||
"lng_create_group_back" = "Indietro";
|
||||
"lng_create_group_next" = "Avanti";
|
||||
"lng_create_group_create" = "Crea";
|
||||
@@ -618,8 +691,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_create_channel_link_available" = "Questo link è disponibile";
|
||||
"lng_create_channel_link_copied" = "Link copiato negli appunti";
|
||||
|
||||
"lng_create_group_crop" = "Seleziona un riquadro per la foto del gruppo";
|
||||
"lng_create_channel_crop" = "Seleziona un riquadro per la foto del canale";
|
||||
"lng_create_group_crop" = "Seleziona un'area per la foto del gruppo";
|
||||
"lng_create_channel_crop" = "Seleziona un'area per la foto del canale";
|
||||
|
||||
"lng_failed_add_participant" = "Impossibile aggiungere l'utente. Riprova più tardi.";
|
||||
"lng_failed_add_not_mutual" = "Spiacenti, se una persona lascia un gruppo, solo un contatto reciproco può aggiungerla (chi ti invita deve avere il tuo numero, e viceversa).";
|
||||
@@ -637,8 +710,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_message_empty" = "Messaggio vuoto";
|
||||
"lng_message_unsupported" = "Questo messaggio non è supportato dalla tua versione di Telegram Desktop. Per favore, aggiorna all'ultima versione dalle Impostazioni o installalo da {link}";
|
||||
|
||||
"lng_duration_seconds" = "{count:_not_used_|# secondo|# secondi}";
|
||||
"lng_duration_minutes_seconds" = "{count_minutes:# min|# min|# min} {count_seconds:# sec|# sec|# sec}";
|
||||
"lng_duration_seconds#one" = "{count} secondo";
|
||||
"lng_duration_seconds#other" = "{count} secondi";
|
||||
"lng_duration_minsec_minutes#one" = "{count} min";
|
||||
"lng_duration_minsec_minutes#other" = "{count} min";
|
||||
"lng_duration_minsec_seconds#one" = "{count} sec";
|
||||
"lng_duration_minsec_seconds#other" = "{count} sec";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_add_user" = "{from} ha aggiunto {user}";
|
||||
"lng_action_add_users_many" = "{from} ha aggiunto {users}";
|
||||
@@ -676,18 +754,33 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_sticker" = "uno sticker";
|
||||
"lng_action_pinned_media_emoji_sticker" = "uno {emoji} sticker";
|
||||
"lng_action_pinned_media_game" = "il gioco «{game}»";
|
||||
"lng_action_game_score" = "{from} ha totalizzato {count:# punti|# punto|# punti} a {game}";
|
||||
"lng_action_game_you_scored" = "Hai totalizzato {count:# punti|# punto|# punti} a {game}";
|
||||
"lng_action_game_score_no_game" = "{from} ha totalizzato {count:# punti|# punto|# punti}";
|
||||
"lng_action_game_you_scored_no_game" = "Hai totalizzato {count:# punti|# punto|# punti}";
|
||||
"lng_action_game_score#one" = "{from} ha totalizzato {count} punto a {game}";
|
||||
"lng_action_game_score#other" = "{from} ha totalizzato {count} punti a {game}";
|
||||
"lng_action_game_you_scored#one" = "Hai totalizzato {count} punto a {game}";
|
||||
"lng_action_game_you_scored#other" = "Hai totalizzato {count} punti a {game}";
|
||||
"lng_action_game_score_no_game#one" = "{from} ha totalizzato {count} punto";
|
||||
"lng_action_game_score_no_game#other" = "{from} ha totalizzato {count} punti";
|
||||
"lng_action_game_you_scored_no_game#one" = "Hai totalizzato {count} punto";
|
||||
"lng_action_game_you_scored_no_game#other" = "Hai totalizzato {count} punti";
|
||||
"lng_action_payment_done" = "Hai appena trasferito con successo {amount} a {user}";
|
||||
"lng_action_payment_done_for" = "Hai appena trasferito con successo {amount} a {user} per {invoice}";
|
||||
"lng_action_took_screenshot" = "{from} ha fatto uno screenshot!";
|
||||
"lng_action_you_took_screenshot" = "Hai fatto uno screenshot!";
|
||||
|
||||
"lng_profile_migrate_reached" = "Limite di {count:_not_used_|# membro|# membri} raggiunto";
|
||||
"lng_ttl_photo_received" = "{from} ti inviato una foto con autodistruzione. Per favore visualizzala sul tuo cellulare.";
|
||||
"lng_ttl_photo_sent" = "Hai inviato una foto con autodistruzione.";
|
||||
"lng_ttl_photo_expired" = "La foto è scaduta";
|
||||
"lng_ttl_video_received" = "{from} ti inviato un video con autodistruzione. Per favore visualizzalo sul tuo cellulare.";
|
||||
"lng_ttl_video_sent" = "Hai inviato un video con autodistruzione.";
|
||||
"lng_ttl_video_expired" = "Il video è scaduto";
|
||||
|
||||
"lng_profile_migrate_reached#one" = "Limite di {count} membro raggiunto";
|
||||
"lng_profile_migrate_reached#other" = "Limite di {count} membri raggiunto";
|
||||
"lng_profile_migrate_body" = "Per superare questo limite, puoi aggiornare il gruppo a supergruppo.";
|
||||
"lng_profile_migrate_learn_more" = "Scopri di più »";
|
||||
"lng_profile_migrate_about" = "Se vuoi superare questo limite, puoi aggiornare il gruppo a supergruppo. Nei supergruppi:";
|
||||
"lng_profile_migrate_feature1" = "— I supergruppi hanno massimo {count:_not_used_|# membro|# membri}";
|
||||
"lng_profile_migrate_feature1#one" = "— I supergruppi hanno massimo {count} membro";
|
||||
"lng_profile_migrate_feature1#other" = "— I supergruppi hanno massimo {count} membri";
|
||||
"lng_profile_migrate_feature2" = "— I nuovi membri vedono tutta la cronologia";
|
||||
"lng_profile_migrate_feature3" = "— Gli admin eliminano i messaggi per tutti";
|
||||
"lng_profile_migrate_feature4" = "— Le notifiche sono disattivate di default";
|
||||
@@ -702,7 +795,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_convert_feature4" = "— Il creatore può creare un link pubblico per il gruppo";
|
||||
"lng_profile_convert_warning" = "{bold_start}Nota:{bold_end} Questa azione non può essere annullata";
|
||||
"lng_profile_convert_confirm" = "Converti";
|
||||
"lng_profile_add_more_after_upgrade" = "Potrai aggiungere fino a {count:_not_used_|# membro|# membri} dopo aver aggiornato a supergruppo.";
|
||||
"lng_profile_add_more_after_upgrade#one" = "Potrai aggiungere fino a {count} membro dopo aver aggiornato il tuo gruppo a supergruppo.";
|
||||
"lng_profile_add_more_after_upgrade#other" = "Potrai aggiungere fino a {count} membri dopo aver aggiornato il tuo gruppo a supergruppo.";
|
||||
|
||||
"lng_channel_not_accessible" = "Spiacenti, questo canale non è accessibile.";
|
||||
"lng_group_not_accessible" = "Spiacenti, questo gruppo non è accessibile.";
|
||||
@@ -717,7 +811,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_group_invite_want_join_channel" = "Vuoi unirti al canale «{title}»?";
|
||||
"lng_group_invite_join" = "Unisciti";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# membro|# membri}, tra cui:";
|
||||
"lng_group_invite_members#one" = "{count} membro, tra cui:";
|
||||
"lng_group_invite_members#other" = "{count} membri, tra cui:";
|
||||
|
||||
"lng_group_invite_link" = "Link d'invito:";
|
||||
"lng_group_invite_create" = "Crea un link d'invito";
|
||||
@@ -730,6 +825,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_channel_public_link_copied" = "Link copiato negli appunti.";
|
||||
|
||||
"lng_forwarded" = "Inoltrato da {user}";
|
||||
"lng_forwarded_date" = "Originale: {date}";
|
||||
"lng_forwarded_channel" = "Inoltrato da {channel}";
|
||||
"lng_forwarded_via" = "Inoltrato da {user} via {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Inoltrato da {channel} via {inline_bot}";
|
||||
@@ -809,7 +905,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_stickers_you_have" = "Organizza e riordina i set di sticker";
|
||||
"lng_stickers_featured" = "Sticker in primo piano";
|
||||
"lng_stickers_return" = "Annulla";
|
||||
"lng_stickers_count" = "{count:Carico...|# sticker|# sticker}";
|
||||
"lng_stickers_count#one" = "{count} sticker";
|
||||
"lng_stickers_count#other" = "{count} sticker";
|
||||
"lng_stickers_masks_pack" = "Questo è un set di maschere. Puoi usarle nell'editor fotografico sulle nostre app mobili.";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
@@ -839,6 +936,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_cant_invite_banned" = "Spiacenti, solo l'amministratore può aggiungere questo utente.";
|
||||
"lng_cant_invite_privacy" = "Spiacenti, non puoi aggiungere questo utente ai gruppi a causa delle sue impostazioni di privacy.";
|
||||
"lng_cant_invite_privacy_channel" = "Spiacenti, non puoi aggiungere questo utente ai canali a causa delle sue impostazioni di privacy.";
|
||||
"lng_cant_delete_group#one" = "Spiacenti, al momento non è possibile eliminare manualmente gruppi con più di {count} membro. Per favore contatta l'assistenza di Telegram se vuoi eliminare questo gruppo.";
|
||||
"lng_cant_delete_group#other" = "Spiacenti, al momento non è possibile eliminare manualmente gruppi con più di {count} membri. Per favore contatta l'assistenza di Telegram se vuoi eliminare questo gruppo.";
|
||||
"lng_cant_delete_channel#one" = "Spiacenti, al momento non è possibile eliminare manualmente canali con più di {count} membro. Per favore contatta l'assistenza di Telegram se vuoi eliminare questo canale.";
|
||||
"lng_cant_delete_channel#other" = "Spiacenti, al momento non è possibile eliminare manualmente canali con più di {count} membri. Per favore contatta l'assistenza di Telegram se vuoi eliminare questo canale.";
|
||||
"lng_cant_do_this" = "Spiacenti, questa azione non è disponibile.";
|
||||
|
||||
"lng_send_button" = "Invia";
|
||||
@@ -884,11 +985,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_typing" = "sta scrivendo";
|
||||
"lng_user_typing" = "{user} sta scrivendo";
|
||||
"lng_users_typing" = "{user} e {second_user} stanno scrivendo";
|
||||
"lng_many_typing" = "{count:_not_used_|# sta|# stanno} scrivendo";
|
||||
"lng_many_typing#one" = "{count} sta scrivendo";
|
||||
"lng_many_typing#other" = "{count} stanno scrivendo";
|
||||
"lng_playing_game" = "sta giocando a un gioco";
|
||||
"lng_user_playing_game" = "{user} sta giocando a un gioco";
|
||||
"lng_users_playing_game" = "{user} e {second_user} stanno giocando a un gioco";
|
||||
"lng_many_playing_game" = "{count:_not_used_|# sta|# stanno} giocando a un gioco";
|
||||
"lng_many_playing_game#one" = "{count} sta giocando a un gioco";
|
||||
"lng_many_playing_game#other" = "{count} stanno giocando a un gioco";
|
||||
"lng_send_action_record_video" = "sta registrando un video";
|
||||
"lng_user_action_record_video" = "{user} sta registrando un video";
|
||||
"lng_send_action_upload_video" = "sta inviando un video";
|
||||
@@ -909,7 +1012,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_geo_location" = "{user} sta scegliendo una posizione";
|
||||
"lng_send_action_choose_contact" = "scegliendo un contatto";
|
||||
"lng_user_action_choose_contact" = "{user} sta scegliendo un contatto";
|
||||
"lng_unread_bar" = "{count:_not_used_|# messaggio non letto|# messaggi non letti}";
|
||||
"lng_unread_bar#one" = "{count} messaggio non letto";
|
||||
"lng_unread_bar#other" = "{count} messaggi non letti";
|
||||
|
||||
"lng_maps_point" = "Posizione";
|
||||
"lng_save_photo" = "Salva immagine";
|
||||
@@ -932,7 +1036,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_from_top" = "Togli dall'alto";
|
||||
|
||||
"lng_context_promote_admin" = "Rendi amministratore";
|
||||
"lng_context_remove_admin" = "Rimuovi dagli amministratori";
|
||||
"lng_context_edit_permissions" = "Modifica autorizzazioni";
|
||||
"lng_context_restrict_user" = "Limita utente";
|
||||
"lng_context_remove_from_group" = "Rimuovi dal gruppo";
|
||||
|
||||
"lng_context_copy_link" = "Copia link";
|
||||
@@ -970,31 +1075,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_msg" = "Togli messaggio";
|
||||
"lng_context_cancel_upload" = "Annulla caricamento";
|
||||
"lng_context_copy_selected" = "Copia testo selezionato";
|
||||
"lng_context_copy_selected_items" = "Copia selezione come testo";
|
||||
"lng_context_forward_selected" = "Inoltra selezione";
|
||||
"lng_context_delete_selected" = "Elimina selezione";
|
||||
"lng_context_clear_selection" = "Annulla selezione";
|
||||
"lng_really_send_image" = "Vuoi inviare questa immagine?";
|
||||
"lng_really_send_file" = "Vuoi inviare questo file?";
|
||||
"lng_really_share_contact" = "Vuoi condividere questo contatto?";
|
||||
"lng_send_images_compress" = "Comprimi {count:_not_used_|immagine|immagini}";
|
||||
"lng_send_images_compress#one" = "Comprimi immagine";
|
||||
"lng_send_images_compress#other" = "Comprimi immagini";
|
||||
"lng_send_image_non_local" = "Impossibile inviare un file non locale: {name}";
|
||||
"lng_send_image_empty" = "Impossibile inviare un file vuoto: {name}";
|
||||
"lng_send_image_too_large" = "Impossibile inviare il file, perché è più grande di 1500 MB: {name}";
|
||||
"lng_send_folder" = "Impossibile inviare «{name}» perché è una cartella :(";
|
||||
"lng_send_images_selected" = "{count:_not_used_|# immagine selezionata|# immagini selezionate}";
|
||||
"lng_send_photos" = "Invia {count:_not_used_|# foto|# foto}";
|
||||
"lng_send_files_selected" = "{count:_not_used_|# file selezionato|# file selezionati}";
|
||||
"lng_send_files" = "Invia {count:_not_used_|# file|# file}";
|
||||
"lng_send_images_selected#one" = "{count} immagine selezionata";
|
||||
"lng_send_images_selected#other" = "{count} immagini selezionate";
|
||||
"lng_send_photos#one" = "Invia {count} foto";
|
||||
"lng_send_photos#other" = "Invia {count} foto";
|
||||
"lng_send_files_selected#one" = "{count} file selezionato";
|
||||
"lng_send_files_selected#other" = "{count} file selezionati";
|
||||
"lng_send_files#one" = "Invia {count} file";
|
||||
"lng_send_files#other" = "Invia {count} file";
|
||||
|
||||
"lng_forward_choose" = "Scegli destinatario...";
|
||||
"lng_forward_cant" = "Spiacenti, impossibile inoltrare qui :(";
|
||||
"lng_forward_confirm" = "Inoltra a {recipient}?";
|
||||
"lng_forward_share_contact" = "Condividi contatto con {recipient}?";
|
||||
"lng_forward_share_cant" = "Spiacenti, non è possibile condividere contatti qui :(";
|
||||
"lng_forward_send_file_confirm" = "Invia «{name}» a {recipient}?";
|
||||
"lng_forward_send_files_confirm" = "Invia i file selezionati a {recipient}?";
|
||||
"lng_forward_send_files_cant" = "Spiacenti, non è possibile inviare media qui :(";
|
||||
"lng_forward_send" = "Invia";
|
||||
"lng_forward_messages" = "{count:_not_used_|messaggio inoltrato|# messaggi inoltrati}";
|
||||
"lng_forwarding_from" = "{user} e {count:_not_used_|# altro|altri #}";
|
||||
"lng_forward_messages#one" = "{count} messaggio inoltrato";
|
||||
"lng_forward_messages#other" = "{count} messaggi inoltrati";
|
||||
"lng_forwarding_from#one" = "{user} e {count} altro";
|
||||
"lng_forwarding_from#other" = "{user} e {count} altri";
|
||||
"lng_forwarding_from_two" = "{user} e {second_user}";
|
||||
"lng_inline_switch_choose" = "Scegli conversazione...";
|
||||
"lng_inline_switch_cant" = "Spiacenti, impossibile scrivere qui :(";
|
||||
@@ -1016,6 +1131,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_contact_title" = "Modifica nome contatto";
|
||||
"lng_edit_channel_title" = "Modifica canale";
|
||||
"lng_edit_sign_messages" = "Firma messaggi";
|
||||
"lng_edit_group_who_invites" = "Chi può aggiungere membri";
|
||||
"lng_edit_group_invites_everybody" = "Tutti i membri";
|
||||
"lng_edit_group_invites_only_admins" = "Solo gli amministratori";
|
||||
"lng_edit_group" = "Modifica gruppo";
|
||||
"lng_edit_self_title" = "Modifica il tuo nome";
|
||||
"lng_confirm_contact_data" = "Nuovo contatto";
|
||||
@@ -1040,27 +1158,34 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_selected_clear" = "Annulla";
|
||||
"lng_selected_delete" = "Elimina";
|
||||
"lng_selected_forward" = "Inoltra";
|
||||
"lng_selected_count" = "{count:_not_used_|# messaggio|# messaggi}";
|
||||
"lng_selected_count#one" = "{count} messaggio";
|
||||
"lng_selected_count#other" = "{count} messaggi";
|
||||
"lng_selected_cancel_sure_this" = "Annullare il caricamento?";
|
||||
"lng_selected_upload_stop" = "Arresta ";
|
||||
"lng_selected_delete_sure_this" = "Vuoi eliminare questo messaggio?";
|
||||
"lng_selected_delete_sure" = "Vuoi eliminare {count:_not_used_|# messaggio|# messaggi}?";
|
||||
"lng_selected_delete_sure#one" = "Vuoi eliminare {count} messaggio?";
|
||||
"lng_selected_delete_sure#other" = "Vuoi eliminare {count} messaggi?";
|
||||
"lng_delete_photo_sure" = "Vuoi eliminare questa foto?";
|
||||
"lng_delete_for_everyone_hint" = "Questo {count:_not_used_|lo eliminerà|li eliminerà} per chiunque in questa chat.";
|
||||
"lng_delete_for_me_chat_hint" = "Questo {count:_not_used_|lo eliminerà|li eliminerà} solo per te, non per gli altri membri della chat.";
|
||||
"lng_delete_for_me_hint" = "Questo {count:_not_used_|lo eliminerà|li eliminerà} solo per te.";
|
||||
"lng_delete_for_everyone_hint#one" = "Questo lo eliminerà per chiunque in questa chat.";
|
||||
"lng_delete_for_everyone_hint#other" = "Questo li eliminerà per chiunque in questa chat.";
|
||||
"lng_delete_for_me_chat_hint#one" = "Questo lo eliminerà solo per te, non per gli altri membri della chat.";
|
||||
"lng_delete_for_me_chat_hint#other" = "Questo li eliminerà solo per te, non per gli altri membri della chat.";
|
||||
"lng_delete_for_me_hint#one" = "Questo lo eliminerà solo per te.";
|
||||
"lng_delete_for_me_hint#other" = "Questo li eliminerà solo per te.";
|
||||
"lng_delete_for_everyone_check" = "Elimina per tutti";
|
||||
"lng_delete_for_other_check" = "Elimina per {user}";
|
||||
"lng_box_delete" = "Elimina";
|
||||
"lng_box_leave" = "Lascia";
|
||||
|
||||
"lng_about_version" = "versione {version}";
|
||||
"lng_about_text_1" = "App ufficiale basata sulle [a href=\"https://core.telegram.org/api\"]API di Telegram[/a]\nper velocità e sicurezza.";
|
||||
"lng_about_text_1" = "App ufficiale basata sulle [a href=\"https://core.telegram.org/api\"]API di Telegram[/a]\nper offrire velocità e sicurezza.";
|
||||
"lng_about_text_2" = "Questo software è sotto licenza [a href=\"https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\"]GNU GPL[/a] versione 3.\nIl source code è disponibile su [a href=\"https://github.com/telegramdesktop/tdesktop\"]GitHub[/a].";
|
||||
"lng_about_text_3" = "Visita le {faq_open}domande frequenti{faq_close} per maggiori info.";
|
||||
"lng_about_done" = "Fatto";
|
||||
|
||||
"lng_search_found_results" = "{count:Nessun messaggio trovato|# messaggio trovato|# messaggi trovati}";
|
||||
"lng_search_no_results" = "Nessun messaggio trovato";
|
||||
"lng_search_found_results#one" = "Trovato {count} messaggio";
|
||||
"lng_search_found_results#other" = "Trovati {count} messaggi";
|
||||
"lng_search_global_results" = "Risultati ricerca globale";
|
||||
|
||||
"lng_media_save_progress" = "{ready} di {total} {mb}";
|
||||
@@ -1169,11 +1294,133 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_player_message_yesterday" = "Ieri alle {time}";
|
||||
"lng_player_message_date" = "{date} alle {time}";
|
||||
|
||||
"lng_rights_edit_admin" = "Modifica amministratore";
|
||||
"lng_rights_edit_admin_header" = "Cosa può fare questo amministratore?";
|
||||
"lng_rights_about_add_admins_yes" = "Questo amministratore sarà in grado di aggiungere nuovi amministratori con le stesse autorizzazioni (o più limitate) .";
|
||||
"lng_rights_about_add_admins_no" = "Questo amministratore non sarà in grado di aggiungere nuovi amministratori.";
|
||||
"lng_rights_about_admin_cant_edit" = "Non puoi modificare le autorizzazioni di questo amministratore.";
|
||||
"lng_rights_user_restrictions" = "Restrizioni utente";
|
||||
"lng_rights_user_restrictions_header" = "Cosa può fare questo utente?";
|
||||
|
||||
"lng_rights_channel_info" = "Cambiare le info del canale";
|
||||
"lng_rights_channel_post" = "Pubblicare messaggi";
|
||||
"lng_rights_channel_edit" = "Modificare i messaggi di altri";
|
||||
"lng_rights_channel_delete" = "Eliminare i messaggi di altri";
|
||||
"lng_rights_group_info" = "Cambiare le info del gruppo";
|
||||
"lng_rights_group_ban" = "Bloccare utenti";
|
||||
"lng_rights_group_invite_link" = "Invitare utenti tramite link";
|
||||
"lng_rights_group_invite" = "Aggiungere utenti";
|
||||
"lng_rights_group_pin" = "Fissare messaggi";
|
||||
"lng_rights_group_delete" = "Eliminare messaggi";
|
||||
"lng_rights_add_admins" = "Aggiungere amministratori";
|
||||
"lng_rights_chat_read" = "Leggere messaggi";
|
||||
"lng_rights_chat_send_text" = "Inviare messaggi";
|
||||
"lng_rights_chat_send_media" = "Inviare media";
|
||||
"lng_rights_chat_send_stickers" = "Inviare sticker e GIF";
|
||||
"lng_rights_chat_send_links" = "Inviare link con anteprima";
|
||||
"lng_rights_chat_banned_until_header" = "Limitato fino a";
|
||||
"lng_rights_chat_banned_forever" = "Sempre";
|
||||
"lng_rights_chat_banned_day#one" = "Per {count} giorno";
|
||||
"lng_rights_chat_banned_day#other" = "Per {count} giorni";
|
||||
"lng_rights_chat_banned_week#one" = "Per {count} settimana";
|
||||
"lng_rights_chat_banned_week#other" = "Per {count} settimane";
|
||||
"lng_rights_chat_banned_custom" = "Personalizzato";
|
||||
"lng_rights_chat_banned_custom_date" = "Fino a {date}";
|
||||
"lng_rights_chat_banned_block" = "Blocca e rimuovi dal gruppo";
|
||||
|
||||
"lng_restricted_send_message" = "Gli amministratori di questo gruppo ti hanno vietato di scrivere qui.";
|
||||
"lng_restricted_send_media" = "Spiacenti, gli amministratori di questo gruppo ti hanno vietato di inviare media.";
|
||||
"lng_restricted_send_stickers" = "Spiacenti, gli amministratori di questo gruppo ti hanno vietato di inviare sticker.";
|
||||
"lng_restricted_send_gifs" = "Spiacenti, gli amministratori di questo gruppo ti hanno vietato di inviare GIF.";
|
||||
"lng_restricted_send_inline" = "Gli amministratori di questo gruppo ti hanno vietato di inviare contenuti inline qui.";
|
||||
|
||||
"lng_restricted_list_title" = "Utenti limitati";
|
||||
"lng_banned_list_title" = "Utenti bloccati";
|
||||
|
||||
"lng_admin_log_title_all" = "Tutte le azioni";
|
||||
"lng_admin_log_title_selected" = "Azioni selezionate";
|
||||
"lng_admin_log_filter" = "Filtro";
|
||||
"lng_admin_log_filter_title" = "Filtro";
|
||||
"lng_admin_log_filter_all_actions" = "Tutte le azioni";
|
||||
"lng_admin_log_filter_restrictions" = "Nuove restrizioni";
|
||||
"lng_admin_log_filter_admins_new" = "Nuovi amministratori";
|
||||
"lng_admin_log_filter_members_new" = "Nuovi membri";
|
||||
"lng_admin_log_filter_info_group" = "Info gruppo";
|
||||
"lng_admin_log_filter_info_channel" = "Info canale";
|
||||
"lng_admin_log_filter_messages_deleted" = "Messaggi eliminati";
|
||||
"lng_admin_log_filter_messages_edited" = "Messaggi modificati";
|
||||
"lng_admin_log_filter_messages_pinned" = "Messaggi fissati";
|
||||
"lng_admin_log_filter_members_removed" = "Membri rimossi";
|
||||
"lng_admin_log_filter_all_admins" = "Tutti gli utenti e amministratori";
|
||||
"lng_admin_log_about" = "Cos'è questo?";
|
||||
"lng_admin_log_about_text" = "Questa è una lista di tutte le azioni di servizio eseguite dai membri e dagli amministratori del gruppo nelle ultime 48 ore.";
|
||||
"lng_admin_log_no_results_title" = "Nessuna azione trovata";
|
||||
"lng_admin_log_no_results_text" = "Non sono stati trovate azioni recenti che rispondono alla tua richiesta.";
|
||||
"lng_admin_log_no_results_search_text" = "Non sono state trovate azioni recenti contenenti '{query}'.";
|
||||
"lng_admin_log_no_events_title" = "Ancora nessuna azione";
|
||||
"lng_admin_log_no_events_text" = "Non ci sono state azioni di servizio\nda parte dei membri e degli amministratori\ndel gruppo nelle ultime 48 ore.";
|
||||
|
||||
"lng_admin_log_empty_text" = "Vuota";
|
||||
"lng_admin_log_changed_title_group" = "{from} ha cambiato il nome del gruppo in «{title}»";
|
||||
"lng_admin_log_changed_title_channel" = "{from} ha cambiato il nome del canale in «{title}»";
|
||||
"lng_admin_log_changed_description_group" = "{from} ha cambiato la descrizione del gruppo:";
|
||||
"lng_admin_log_removed_description_group" = "{from} ha rimosso la descrizione del gruppo";
|
||||
"lng_admin_log_changed_description_channel" = "{from} ha cambiato la descrizione del canale:";
|
||||
"lng_admin_log_removed_description_channel" = "{from} ha rimosso la descrizione del canale";
|
||||
"lng_admin_log_previous_description" = "Descrizione precedente";
|
||||
"lng_admin_log_changed_link_group" = "{from} ha cambiato il link del gruppo:";
|
||||
"lng_admin_log_removed_link_group" = "{from} ha rimosso il link del gruppo";
|
||||
"lng_admin_log_changed_link_channel" = "{from} ha cambiato il link del canale:";
|
||||
"lng_admin_log_removed_link_channel" = "{from} ha rimosso il link del canale";
|
||||
"lng_admin_log_previous_link" = "Link precedente";
|
||||
"lng_admin_log_changed_photo_group" = "{from} ha cambiato la foto del gruppo";
|
||||
"lng_admin_log_changed_photo_channel" = "{from} ha cambiato la foto del canale";
|
||||
"lng_admin_log_removed_photo_group" = "{from} ha rimosso la foto del gruppo";
|
||||
"lng_admin_log_removed_photo_channel" = "{from} ha rimosso la foto del canale";
|
||||
"lng_admin_log_invites_enabled" = "{from} ha attivato gli inviti del gruppo";
|
||||
"lng_admin_log_invites_disabled" = "{from} ha disattivato gli inviti del gruppo";
|
||||
"lng_admin_log_signatures_enabled" = "{from} ha attivato le firme";
|
||||
"lng_admin_log_signatures_disabled" = "{from} ha disattivato le firme";
|
||||
"lng_admin_log_pinned_message" = "{from} ha fissato un messaggio:";
|
||||
"lng_admin_log_unpinned_message" = "{from} ha tolto un messaggio";
|
||||
"lng_admin_log_edited_caption" = "{from} ha modificato la didascalia:";
|
||||
"lng_admin_log_removed_caption" = "{from} ha rimosso la didascalia";
|
||||
"lng_admin_log_previous_caption" = "Didascalia originale";
|
||||
"lng_admin_log_edited_message" = "{from} ha modificato un messaggio:";
|
||||
"lng_admin_log_previous_message" = "Messaggio originale";
|
||||
"lng_admin_log_deleted_message" = "{from} ha eliminato un messaggio:";
|
||||
"lng_admin_log_participant_joined" = "{from} si è unito al gruppo";
|
||||
"lng_admin_log_participant_joined_channel" = "{from} si è unito al canale";
|
||||
"lng_admin_log_participant_left" = "{from} ha lasciato il gruppo";
|
||||
"lng_admin_log_participant_left_channel" = "{from} ha lasciato il canale";
|
||||
"lng_admin_log_invited" = "ha invitato {user}";
|
||||
"lng_admin_log_banned" = "ha bloccato {user}";
|
||||
"lng_admin_log_restricted" = "ha cambiato le restrizioni di {user} {until}";
|
||||
"lng_admin_log_promoted" = "ha cambiato i privilegi di {user}";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_restricted_forever" = "indefinitamente";
|
||||
"lng_admin_log_restricted_until" = "fino a {date}";
|
||||
"lng_admin_log_banned_view_messages" = "Leggere messaggi";
|
||||
"lng_admin_log_banned_send_messages" = "Inviare messaggi";
|
||||
"lng_admin_log_banned_send_media" = "Inviare media";
|
||||
"lng_admin_log_banned_send_stickers" = "Inviare sticker e GIF";
|
||||
"lng_admin_log_banned_embed_links" = "Inviare link con anteprima";
|
||||
"lng_admin_log_admin_change_info" = "Cambiare le info";
|
||||
"lng_admin_log_admin_post_messages" = "Pubblicare messaggi";
|
||||
"lng_admin_log_admin_edit_messages" = "Modificare messaggi";
|
||||
"lng_admin_log_admin_delete_messages" = "Eliminare messaggi";
|
||||
"lng_admin_log_admin_ban_users" = "Bloccare utenti";
|
||||
"lng_admin_log_admin_invite_users" = "Aggiungere utenti";
|
||||
"lng_admin_log_admin_invite_link" = "Invitare utenti tramite link";
|
||||
"lng_admin_log_admin_pin_messages" = "Fissare messaggi";
|
||||
"lng_admin_log_admin_add_admins" = "Aggiungere amministratori";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "Info";
|
||||
"lng_profile_group_info" = "Info gruppo";
|
||||
"lng_profile_channel_info" = "Info canale";
|
||||
"lng_channel_add_admins" = "Nuovo amministratore";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ to link the code of portions of this program with the OpenSSL library.
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
"lng_language_name" = "한국어";
|
||||
"lng_switch_to_this" = "한국어로 변경";
|
||||
"lng_language_name" = "영어";
|
||||
"lng_switch_to_this" = "영어로 변경";
|
||||
|
||||
"lng_menu_contacts" = "주소록";
|
||||
"lng_menu_calls" = "전화";
|
||||
@@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_menu_update" = "업데이트";
|
||||
"lng_menu_restart" = "재시작";
|
||||
"lng_menu_back" = "뒤로가기";
|
||||
"lng_menu_night_mode" = "야간 모드";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "알림 해제";
|
||||
"lng_enable_notifications_from_tray" = "알림 사용";
|
||||
@@ -88,7 +89,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_continue" = "계속";
|
||||
"lng_close" = "닫기";
|
||||
"lng_connecting" = "연결중...";
|
||||
"lng_reconnecting" = "재연결중..{count:now|in # 초|in # 초}...";
|
||||
"lng_connecting_to_proxy" = "프록시 연결 중...";
|
||||
"lng_connecting_settings" = "설정";
|
||||
"lng_reconnecting#one" = "{count} 초 후 재연결...";
|
||||
"lng_reconnecting#other" = "{count} 초 후 재연결...";
|
||||
"lng_reconnecting_try_now" = "다시 시도";
|
||||
|
||||
"lng_status_service_notifications" = "서비스 알림";
|
||||
@@ -102,8 +106,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_last_month" = "한 달 이내 마지막으로 접속";
|
||||
"lng_status_invisible" = "숨김";
|
||||
"lng_status_lastseen_now" = "방금 접속";
|
||||
"lng_status_lastseen_minutes" = "{count:_not_used_|#분|#분}전 접속";
|
||||
"lng_status_lastseen_hours" = "{count:_not_used_|#시간|#시간}전 접속";
|
||||
"lng_status_lastseen_minutes#one" = "{count} 분전 접속";
|
||||
"lng_status_lastseen_minutes#other" = "{count} 분전 접속";
|
||||
"lng_status_lastseen_hours#one" = "{count} 시간전 접속";
|
||||
"lng_status_lastseen_hours#other" = "{count} 시간전 접속";
|
||||
"lng_status_lastseen_today" = "오늘 {time}에 마지막으로 접속";
|
||||
"lng_status_lastseen_yesterday" = "어제 {time}에 마지막으로 접속";
|
||||
"lng_status_lastseen_date" = "{date}에 마지막으로 접속";
|
||||
@@ -112,24 +118,43 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_connecting" = "연결중...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "그룹에 접근할 수 없습니다.";
|
||||
"lng_chat_status_members" = "{count:맴버 없음|#명|#명}";
|
||||
"lng_chat_status_members_online" = "{count:_not_used_|#명|#명}중 {count_online:_not_used_|#명 접속중|#명 접속중}";
|
||||
"lng_chat_status_no_members" = "대화상대가 없음";
|
||||
"lng_chat_status_members#one" = "대화상대 {count}명";
|
||||
"lng_chat_status_members#other" = "대화상대 {count}명";
|
||||
"lng_chat_status_online#one" = "온라인 {count}명";
|
||||
"lng_chat_status_online#other" = "온라인 {count}명";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
|
||||
"lng_channel_status" = "채널";
|
||||
"lng_group_status" = "그룹방";
|
||||
|
||||
"lng_channel_members_link" = "{count:_not_used_|#명|#명}";
|
||||
"lng_channel_admins_link" = "{count:_not_used_|# 관리자|# 관리자}";
|
||||
"lng_channel_members_link#one" = "대화상대 {count}명";
|
||||
"lng_channel_members_link#other" = "대화상대 {count}명";
|
||||
"lng_channel_admins_link#one" = "관리자 {count}명";
|
||||
"lng_channel_admins_link#other" = "관리자 {count}명";
|
||||
|
||||
"lng_server_error" = "내부 서버 오류";
|
||||
"lng_flood_error" = "시도가 너무 많습니다. 나중에 다시 시도해주세요.";
|
||||
"lng_gif_error" = "GIF 애니메이션을 읽는 동안 에러가 발생하였습니다.";
|
||||
"lng_gif_error" = "GIF 애니메이션을 불러올때 에러가 발생하였습니다 :(";
|
||||
"lng_edit_error" = "메시지를 수정 할 수 없습니다.";
|
||||
"lng_join_channel_error" = "너무 많은 채널과 슈퍼그룹에 참여하였습니다.\n기존 대화방을 나가주셔야 참여가 가능합니다.";
|
||||
"lng_error_phone_flood" = "죄송합니다, 너무 많이 계정 재가입이 최근에 이루어졌습니다. 다시 재가입까지 몇일 기다려주시기 바랍니다.";
|
||||
"lng_error_start_minimized_passcoded" = "잠금코드를 설정하였기 때문에 앱이 최소화된 상태에서 시작할 수 없습니다. 앱이 시작하기 전에 잠금코드 입력이 필요합니다.";
|
||||
"lng_error_pinned_max" = "죄송합니다, {count:_not_used_|# 대화|# 대화} 이상은 맨위 고정을 할 수 없습니다.";
|
||||
"lng_error_pinned_max#one" = "죄송합니다, {count}개 이상의 대화를 고정할 수 없습니다.";
|
||||
"lng_error_pinned_max#other" = "죄송합니다, {count}개 이상의 대화를 고정할 수 없습니다.";
|
||||
"lng_error_public_groups_denied" = "죄송하지만, 회원님은 공개그룹 참여에 제한 되었습니다.\n{more_info}";
|
||||
"lng_error_cant_edit_admin" = "죄송합니다, 이 관리자의 권한을 변경 할 수 없습니다.";
|
||||
"lng_error_cant_add_member" = "죄송합니다, 이 봇을 그룹에 추가할 수 없습니다. 관리자에게 추가 문의해주세요.";
|
||||
"lng_error_cant_add_bot" = "죄송합니다, 이 봇은 그룹에 추가할 수 없습니다.";
|
||||
"lng_error_cant_add_admin_invite" = "죄송합니다, 이 사용자는 이 그룹에 속해있지 않으며 초대가 되지 않기 때문에 관리자로 추가할 수 없습니다.";
|
||||
"lng_error_cant_add_admin_unban" = "죄송합니다, 이 사용자는 블랙리스트에 있으며 해제가 가능하지 않기 떄문에 관리자로 추가할 수 없습니다.";
|
||||
"lng_error_cant_ban_admin" = "죄송합니다, 이 사용자는 그룹의 관리자이며 해제권한이 없으시기 떄문에 차단할 수 없습니다.";
|
||||
"lng_sure_add_admin_invite" = "이 사용자는 그룹에 참여하고 있지 않습니다. 그룹에 초대하고 관리자로 추가하시겠습니까?";
|
||||
"lng_sure_add_admin_unban" = "이 사용자는 제한되어져 있으며 그룹에서 차단당한 상태입니다. 정말로 차단을 해제하고 추가하시겠습니까?";
|
||||
"lng_sure_ban_admin" = "이 사용자는 그룹의 관리자입니다. 정말로 제한을 하시겠습니까?";
|
||||
"lng_sure_ban_user_group" = "{user} 를 그룹에서 차단하시겠습니까?";
|
||||
"lng_sure_enable_socks" = "프록시 설정을 하시겠습니까?\n\n서버: {server}\n포트: {port}\n\n나중에 설정에서 프록시 서버를 변경 할 수 있습니다. (연결유형)";
|
||||
"lng_sure_enable" = "활성";
|
||||
|
||||
"lng_edit_deleted" = "메시지는 삭제 되었습니다.";
|
||||
"lng_edit_too_long" = "메시지 길이가 너무 깁니다.";
|
||||
@@ -198,9 +223,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_signin_sure_reset" = "경고!\n\n계정 초기화 진행시 모든 대화,\n메시지 및 공유받은 미디어와 파일이 삭제가 됩니다.\n\n계정 초기화를 진행하시겠습니까?";
|
||||
"lng_signin_reset" = "초기화";
|
||||
"lng_signin_reset_wait" = "{phone_number} 계정이 사용중이고 비밀번호 설정이 되어져 있어, 보안을 위하여 1주일 이후에 삭제가 될 예정입니다. 이 설정은 언제든지 취소 할 수 있습니다.\n\n계정은 다음시간 이후에 초기화가 됩니다:\n{when}";
|
||||
"lng_signin_reset_in_days" = "{count_days:0 일|# 일|# 일} {count_hours:0 시간|# 시간|# 시간} {count_minutes:0 분|# 분|# 분}";
|
||||
"lng_signin_reset_in_hours" = "{count_hours:0 시간|# 시간|# 시간} {count_minutes:0 분|# 분|# 분}";
|
||||
"lng_signin_reset_in_minutes" = "{count_minutes:0 분|# 분|# 분}";
|
||||
"lng_signin_reset_days#one" = "{count} 일";
|
||||
"lng_signin_reset_days#other" = "{count} 일";
|
||||
"lng_signin_reset_hours#one" = "{count} 시간";
|
||||
"lng_signin_reset_hours#other" = "{count} 시간";
|
||||
"lng_signin_reset_minutes#one" = "{count} 분";
|
||||
"lng_signin_reset_minutes#other" = "{count} 분";
|
||||
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
|
||||
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
|
||||
"lng_signin_reset_cancelled" = "현재 사용중인 사용자가 요청하신 계정 초기화를 취소 하였습니다.\n7일 이후에 다시 시도해주세요.";
|
||||
|
||||
"lng_signup_title" = "정보";
|
||||
@@ -223,7 +253,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_settings_save" = "저장";
|
||||
"lng_settings_upload" = "프로필 이미지 선택";
|
||||
"lng_settings_crop_profile" = "프로필 사진으로 사용할 사각영역을 선택하세요";
|
||||
"lng_settings_crop_profile" = "프로필 사진으로 설정할 영역을 선택해주세요.";
|
||||
"lng_settings_uploading_photo" = "사진 업로드 중...";
|
||||
"lng_settings_edit" = "수정";
|
||||
"lng_settings_drop_area_subtitle" = "프로필 사진으로 설정";
|
||||
@@ -241,10 +271,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_username_link" = "회원님과 대화를 할 수 있는 링크입니다.";
|
||||
"lng_username_copied" = "클립보드에 링크가 복사되었습니다.";
|
||||
|
||||
"lng_bio_title" = "자기소개 수정";
|
||||
"lng_bio_placeholder" = "자기속";
|
||||
"lng_bio_about" = "소개하고 싶은 내용을 적어주세요. 다른 분이 회원님의 프로필을 확인했을 경우 노출됩니다.";
|
||||
|
||||
"lng_settings_section_info" = "정보";
|
||||
"lng_settings_phone_number" = "전화번호";
|
||||
"lng_settings_username" = "아이디:";
|
||||
"lng_settings_choose_username" = "아이디 설정하기";
|
||||
"lng_settings_empty_bio" = "없음";
|
||||
|
||||
"lng_settings_section_notify" = "알림";
|
||||
"lng_settings_desktop_notify" = "데스크탑 알림";
|
||||
@@ -303,7 +338,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_backgrounds_header" = "새로운 대화창 배경화면을 선택";
|
||||
"lng_theme_sure_keep" = "이 테마 색상을 유지하시겠습니까?";
|
||||
"lng_theme_reverting" = " {count:_not_used_|# 초|# 초} 후에 이전 테마 색상으로 원복합니다.";
|
||||
"lng_theme_reverting#one" = "{count}초 후에 이전 테마색으로 돌아갑니다.";
|
||||
"lng_theme_reverting#other" = "{count}초 후에 이전 테마색으로 돌아갑니다.";
|
||||
"lng_theme_keep_changes" = "변화 유지";
|
||||
"lng_theme_revert" = "원복";
|
||||
|
||||
@@ -329,14 +365,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_local_storage_title" = "로컬 저장소";
|
||||
"lng_settings_no_data_cached" = "캐시 데이터가 없습니다!";
|
||||
"lng_settings_images_cached" = "{count:_not_used_|이미지 #개|이미지 #개}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|음성 메시지 #개|음성 메시지 #개}, {size}";
|
||||
"lng_settings_images_cached#one" = "이미지 {count}개, {size}";
|
||||
"lng_settings_images_cached#other" = "이미지 {count}개, {size}";
|
||||
"lng_settings_audios_cached#one" = "음성메시지 {count}개, {size}";
|
||||
"lng_settings_audios_cached#other" = "음성메시지 {count}개, {size}";
|
||||
"lng_local_storage_clear" = "전체 정리";
|
||||
"lng_local_storage_clearing" = "초기화 중..";
|
||||
"lng_local_storage_cleared" = "초기화 완료!";
|
||||
"lng_local_storage_clear_failed" = "초기화 실패 :(";
|
||||
|
||||
"lng_settings_section_advanced_settings" = "고급 설정";
|
||||
"lng_settings_enable_night_theme" = "야간 모드 활성화";
|
||||
"lng_settings_disable_night_theme" = "야간 모드 비활성화";
|
||||
|
||||
"lng_passcode_remove_button" = "삭제";
|
||||
|
||||
@@ -348,8 +388,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_passcode_autolock" = "자동-잠금";
|
||||
"lng_passcode_autolock_away" = "미사용시 자동잠금 설정";
|
||||
"lng_passcode_autolock_inactive" = "메신져 미사용시 자동잠금 설정";
|
||||
"lng_passcode_autolock_minutes" = "{count:_not_used_|#분|#분} ";
|
||||
"lng_passcode_autolock_hours" = "{count:_not_used_|#시간|#시간} ";
|
||||
"lng_passcode_autolock_minutes#one" = "{count} 분";
|
||||
"lng_passcode_autolock_minutes#other" = "{count} 분";
|
||||
"lng_passcode_autolock_hours#one" = "{count} 시간";
|
||||
"lng_passcode_autolock_hours#other" = "{count} 시간";
|
||||
"lng_passcode_enter_old" = "현재 잠금코드 입력";
|
||||
"lng_passcode_enter_first" = "잠금코드 입력";
|
||||
"lng_passcode_enter_new" = "신규 비밀번호 입력";
|
||||
@@ -455,32 +497,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_privacy_lastseen_title" = "접속 시간 개인설정";
|
||||
"lng_edit_privacy_lastseen_description" = "내 접속시간을 볼 수 있는 사람 설정:";
|
||||
"lng_edit_privacy_lastseen_warning" = "중요: 접속시간을 공유하지 않는 사람의 접속 시간은 볼 수 없습니다. 대신 대략적으로 접속 시간이 표시 됩니다. (최근에, 일주일 이내, 한달 이내)";
|
||||
"lng_edit_privacy_lastseen_always" = "항상 공유 {count:| # user| # users}";
|
||||
"lng_edit_privacy_lastseen_never" = "공유 안함{count:| # user| # users}";
|
||||
"lng_edit_privacy_lastseen_always_empty" = "항상 공유";
|
||||
"lng_edit_privacy_lastseen_always#one" = "항상 {count}명의 대화상대와 공유";
|
||||
"lng_edit_privacy_lastseen_always#other" = "항상 {count}명의 대화상대와 공유";
|
||||
"lng_edit_privacy_lastseen_never_empty" = "항상 공유 안함";
|
||||
"lng_edit_privacy_lastseen_never#one" = "항상 {count}명의 대화상대와 공유하지 않음";
|
||||
"lng_edit_privacy_lastseen_never#other" = "항상 {count}명의 대화상대와 공유하지 않음";
|
||||
"lng_edit_privacy_lastseen_exceptions" = "이 설정은 위 값을 무효화합니다";
|
||||
"lng_edit_privacy_lastseen_always_title" = "항상 공유";
|
||||
"lng_edit_privacy_lastseen_never_title" = "항상 공유 안함";
|
||||
|
||||
"lng_edit_privacy_groups_title" = "그룹 초대 설정";
|
||||
"lng_edit_privacy_groups_description" = "그룹과 채널로 초대가 가능한 사람을 세세하게 설정 할 수 있습니다:";
|
||||
"lng_edit_privacy_groups_always" = "항상 허용{count:| # user| # users}";
|
||||
"lng_edit_privacy_groups_never" = "허용 안함{count:| # user| # users}";
|
||||
"lng_edit_privacy_groups_always_empty" = "항상 허용";
|
||||
"lng_edit_privacy_groups_always#one" = "항상 {count}명의 대화상대를 허용";
|
||||
"lng_edit_privacy_groups_always#other" = "항상 {count}명의 대화상대를 허용";
|
||||
"lng_edit_privacy_groups_never_empty" = "허용 안함";
|
||||
"lng_edit_privacy_groups_never#one" = "항상 {count}명의 대화상대와 허용하지 않음";
|
||||
"lng_edit_privacy_groups_never#other" = "항상 {count}명의 대화상대와 허용하지 않음";
|
||||
"lng_edit_privacy_groups_exceptions" = "위의 설정과 무관하여 이 사용자는 회원님을 그룹이나 채널로 초대할 수 없습니다.";
|
||||
"lng_edit_privacy_groups_always_title" = "항상 허용";
|
||||
"lng_edit_privacy_groups_never_title" = "허용 안함";
|
||||
|
||||
"lng_edit_privacy_calls_title" = "전화 보안";
|
||||
"lng_edit_privacy_calls_description" = "전화대상을 제한할 수 있습니다";
|
||||
"lng_edit_privacy_calls_always" = "항상 허용{count:| # user| # users}";
|
||||
"lng_edit_privacy_calls_never" = "허용 안함{count:| # user| # users}";
|
||||
"lng_edit_privacy_calls_always_empty" = "항상 허용";
|
||||
"lng_edit_privacy_calls_always#one" = "항상 {count}명의 대화상대를 허용";
|
||||
"lng_edit_privacy_calls_always#other" = "항상 {count}명의 대화상대를 허용";
|
||||
"lng_edit_privacy_calls_never_empty" = "허용 안함";
|
||||
"lng_edit_privacy_calls_never#one" = "항상 {count}명의 대화상대와 허용하지 않음";
|
||||
"lng_edit_privacy_calls_never#other" = "항상 {count}명의 대화상대와 허용하지 않음";
|
||||
"lng_edit_privacy_calls_exceptions" = "위의 설정과 무관하여 이 사용자는 회원님을 전화를 하거나 할 수 없게 됩니다.";
|
||||
"lng_edit_privacy_calls_always_title" = "항상 허용";
|
||||
"lng_edit_privacy_calls_never_title" = "허용 안함";
|
||||
|
||||
"lng_self_destruct_title" = "계정 자동탈퇴";
|
||||
"lng_self_destruct_description" = "이 기간동안 최소한 한번도 온라인이 안될 경우 이 계정은 그룹대화, 일반대화 및 연락처 모두가 삭제됩니다.";
|
||||
"lng_self_destruct_months" = "{count:_not_used_|# 월|# 월}";
|
||||
"lng_self_destruct_years" = "{count:_not_used_|# 년|# 년}";
|
||||
"lng_self_destruct_months#one" = "{count} 월";
|
||||
"lng_self_destruct_months#other" = "{count} 월";
|
||||
"lng_self_destruct_years#one" = "{count} 년";
|
||||
"lng_self_destruct_years#other" = "{count} 년";
|
||||
|
||||
"lng_change_phone_title" = "전화번호 변경";
|
||||
"lng_change_phone_description" = "텔레그램 번호 변경이 가능합니다.\n대화내용, 미디어, 연락처등 클라우드 데이터와\n모든 계정 정보는 새로운 번호로 이관됩니다.\n\n[b]중요[/b]:회원님 텔레그램 연락처에 있는 \n친구분들이회원님의 이전 전화번호가\n저장되어있고 차단을 하지 않았을 경우 \n[b]새로운 전화번호[/b]로 주소록에 저장이 됩니다.";
|
||||
@@ -506,15 +562,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_link_section" = "초대링크";
|
||||
"lng_profile_create_public_link" = "공개 링크 생성";
|
||||
"lng_profile_edit_public_link" = "공개링크 수정";
|
||||
"lng_profile_search_members" = "사용자 검색";
|
||||
"lng_profile_manage_admins" = "관리자 관리";
|
||||
"lng_profile_manage_blocklist" = "차단된 사용자 관리";
|
||||
"lng_profile_common_groups" = "{count:_not_used_|# 그룹|# 그룹} 공통";
|
||||
"lng_profile_manage_restrictedlist" = "제한된 사용자 관리";
|
||||
"lng_profile_recent_actions" = "최근 활동";
|
||||
"lng_profile_common_groups#one" = "공통그룹 {count}개";
|
||||
"lng_profile_common_groups#other" = "공통그룹 {count}개";
|
||||
"lng_profile_common_groups_section" = "공통 그룹";
|
||||
"lng_profile_participants_section" = "사용자";
|
||||
"lng_profile_info_section" = "정보";
|
||||
"lng_profile_mobile_number" = "전화번호:";
|
||||
"lng_profile_username" = "아이디:";
|
||||
"lng_profile_link" = "링크:";
|
||||
"lng_profile_bio" = "자기소개:";
|
||||
"lng_profile_add_contact" = "연락처 추가";
|
||||
"lng_profile_edit_contact" = "수정";
|
||||
"lng_profile_enable_notifications" = "알림";
|
||||
@@ -536,29 +597,36 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_to_group" = "그룹에 추가";
|
||||
"lng_profile_delete_contact" = "삭제";
|
||||
"lng_profile_set_group_photo" = "사진 설정";
|
||||
"lng_profile_add_participant" = "구성원 추가";
|
||||
"lng_profile_add_participant" = "대화상대 추가";
|
||||
"lng_profile_view_channel" = "채널 보기";
|
||||
"lng_profile_join_channel" = "참여";
|
||||
"lng_profile_delete_and_exit" = "나가기";
|
||||
"lng_profile_kick" = "삭제";
|
||||
"lng_profile_admin" = "관리자";
|
||||
"lng_profile_edit_permissions" = "수정";
|
||||
"lng_profile_sure_kick" = "{user}를 내보내시겠습니까?";
|
||||
"lng_profile_sure_kick_channel" = "{user}를 내보내시겠습니까?";
|
||||
"lng_profile_sure_kick_admin" = "{user}를 관리자에서 제외 하시겠습니까?";
|
||||
"lng_profile_loading" = "로드중..";
|
||||
"lng_profile_shared_media" = "공유된 미디어";
|
||||
"lng_profile_no_media" = "대화에 미디어가 존재하지 않습니다.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# 사진|# 사진} ";
|
||||
"lng_profile_photos#one" = "사진 {count}개";
|
||||
"lng_profile_photos#other" = "사진 {count}개";
|
||||
"lng_profile_photos_header" = "사진";
|
||||
"lng_profile_videos" = "{count:_not_used_|# 동영상|# 동영상}";
|
||||
"lng_profile_videos#one" = "비디오 {count}개";
|
||||
"lng_profile_videos#other" = "비디오 {count}개";
|
||||
"lng_profile_videos_header" = "동영상";
|
||||
"lng_profile_songs" = "{count:_not_used_|# 음성|# 음성}";
|
||||
"lng_profile_songs#one" = "음성파일 {count}개";
|
||||
"lng_profile_songs#other" = "음성파일 {count}개";
|
||||
"lng_profile_songs_header" = "음성 파일";
|
||||
"lng_profile_files" = "{count:_not_used_|# 파일|# 파일}";
|
||||
"lng_profile_files#one" = "파일 {count}개";
|
||||
"lng_profile_files#other" = "파일 {count}개";
|
||||
"lng_profile_files_header" = "파일";
|
||||
"lng_profile_audios" = "{count:_not_used_|# 음성메시지|# 음성메시지}";
|
||||
"lng_profile_audios#one" = "음성메시지 {count}개";
|
||||
"lng_profile_audios#other" = "음성메시지 {count}개";
|
||||
"lng_profile_audios_header" = "음성 메시지";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# 공유된 링크|# 공유된 링크}";
|
||||
"lng_profile_shared_links#one" = "공유링크 {count}개";
|
||||
"lng_profile_shared_links#other" = "공유링크 {count}개";
|
||||
"lng_profile_shared_links_header" = "공유된 링크";
|
||||
"lng_profile_copy_phone" = "전화번호 복사";
|
||||
"lng_profile_copy_fullname" = "이름 복사";
|
||||
@@ -578,24 +646,29 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_report_button" = "신고";
|
||||
"lng_report_thanks" = "감사합니다! 신고내용은 신속하게 팀내에서 확인하겠습니다.";
|
||||
|
||||
"lng_channel_add_admins" = "새로운 관리자";
|
||||
"lng_channel_add_members" = "구성원 추가";
|
||||
"lng_channel_members" = "구성원";
|
||||
"lng_channel_only_last_shown" = "마지막 {count:_not_used_|# 구성원|# 구성원} 들이 표시가 됩니다.";
|
||||
"lng_channel_add_members" = "대화상대 추가";
|
||||
"lng_channel_add_banned" = "사용자 차단";
|
||||
"lng_channel_add_restricted" = "사용자 제한";
|
||||
"lng_channel_members" = "대화상대";
|
||||
"lng_channel_only_last_shown#one" = "마지막 {count}명의 대화상대가 표시됩니다.";
|
||||
"lng_channel_only_last_shown#other" = "마지막 {count}명의 대화상대가 표시됩니다.";
|
||||
"lng_channel_admins" = "관리자";
|
||||
"lng_channel_add_admin" = "관리자 추가";
|
||||
"lng_channel_admin_sure" = "{user}를 관리자로 추가하시겠습니까?";
|
||||
"lng_channel_admins_too_much" = "죄송합니다, 관리자의 최대허용치입니다. 다른 관리자를 삭제해주세요";
|
||||
"lng_channel_admin_status_creator" = "생성자";
|
||||
"lng_channel_admin_status_promoted_by" = "{user} 님이 승인함";
|
||||
"lng_channel_admin_status_not_admin" = "관리자가 아님";
|
||||
|
||||
"lng_group_blocked_list_about" = "차단된 사용자들은 그룹에서 추방이 되며 관리자의 초대로만 재입장이 가능합니다.\n초대링크는 작동되지 않습니다.";
|
||||
|
||||
"lng_chat_all_members_admins" = "모든 구성원이 관리자입니다";
|
||||
"lng_chat_about_all_admins" = "그룹에 있는 모든 구성원은 상대 초대, 이름 및 사진을 수정할 수 있습니다.";
|
||||
"lng_chat_all_members_admins" = "모든 대화상대가 관리자입니다";
|
||||
"lng_chat_about_all_admins" = "그룹에 있는 모든 대화상대는 상대 초대, 이름 및 사진을 수정할 수 있습니다.";
|
||||
"lng_chat_about_admins" = "그룹에 있는 관리자는 상대 초대, 이름 및 사진을 수정할 수 있습니다.";
|
||||
|
||||
"lng_participant_filter" = "검색";
|
||||
"lng_participant_invite" = "초대";
|
||||
"lng_participant_invite_sorry" = "죄송합니다, 초기 {count:_not_used|# 구성원|# 구성원} 명만 채널에 개별적으로 추가 할 수 있습니다. \n\n이후로는 초대링크를 통하여 입장해야합니다.";
|
||||
"lng_participant_invite_sorry#one" = "죄송합니다, 초기 {count}명의 대화상대만 채널에 개별적으로 추가 할 수 있습니다.\n\n이후로는 초대링크를 통하여 입장해야합니다.";
|
||||
"lng_participant_invite_sorry#other" = "죄송합니다, 초기 {count}명의 대화상대만 채널에 개별적으로 추가 할 수 있습니다.\n\n이후로는 초대링크를 통하여 입장해야합니다.";
|
||||
"lng_create_group_back" = "뒤로가기";
|
||||
"lng_create_group_next" = "다음";
|
||||
"lng_create_group_create" = "만들기";
|
||||
@@ -618,8 +691,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_create_channel_link_available" = "사용 가능한 링크입니다.";
|
||||
"lng_create_channel_link_copied" = "링크가 클립보드에 복사되었습니다.";
|
||||
|
||||
"lng_create_group_crop" = "그룹프로필 사진으로 사용할 사각영역을 선택하세요";
|
||||
"lng_create_channel_crop" = "채널프로필 사진으로 사용할 사각영역을 선택하세요";
|
||||
"lng_create_group_crop" = "그룹프로필 사진으로 사용할 영역을 선택하세요";
|
||||
"lng_create_channel_crop" = "채널프로필 사진으로 사용할 영역을 선택하세요";
|
||||
|
||||
"lng_failed_add_participant" = "사용자를 추가 하지 못하였습니다. 나중에 다시 시도해주세요";
|
||||
"lng_failed_add_not_mutual" = "죄송합니다. 그룹방에서 대화상대방이 나갔을 경우, 상대 전화번호가 있는 분만 초대가 가능합니다. (서로 전화번호가 등록되어져 있어야만 가능)";
|
||||
@@ -630,15 +703,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_sure_delete_group_history" = "그룹<<{group}>> 방의 모든 메시지 기록을 삭제하시겠습니까?\n\n이 작업은 취소가 불가능합니다.";
|
||||
"lng_sure_delete_and_exit" = "그룹 «{group}» 방에서 모든 메시지를 \n삭제하시고 퇴장하시겠습니까?\n\n삭제 하실 경우 취소가 불가능합니다.";
|
||||
"lng_sure_leave_channel" = "채널에서 나가시겠습니까?";
|
||||
"lng_sure_delete_channel" = "채널을 삭제하시겠습니까? 모든 구성원과 메시지가 삭제됩니다.";
|
||||
"lng_sure_delete_channel" = "채널을 삭제하시겠습니까? 모든 대화상대와 메시지가 삭제됩니다.";
|
||||
"lng_sure_leave_group" = "정말로 그룹방에서 나가시겠습니까?\n이 작업은 취소가 불가능합니다.";
|
||||
"lng_sure_delete_group" = "정말로 그룹방을 삭제하시겠습니까? 모든 구성원 및 메시지가 삭제됩니다.";
|
||||
"lng_sure_delete_group" = "정말로 그룹방을 삭제하시겠습니까? 모든 대화상대 및 메시지가 삭제됩니다.";
|
||||
|
||||
"lng_message_empty" = "메시지 없음";
|
||||
"lng_message_unsupported" = "이 메시지는 텔레그램 데스크탑에서 호환이 되지 않습니다. 설정에서 최신 버전으로 업데이트를 하던가 {link}를 통하여 설치해주세요.";
|
||||
|
||||
"lng_duration_seconds" = "{count:_not_used_|# 초|# 초}";
|
||||
"lng_duration_minutes_seconds" = "{count_minutes:# 분|# 분|# 분} {count_seconds:# 초|# 초|# 초}";
|
||||
"lng_duration_seconds#one" = "{count} 초";
|
||||
"lng_duration_seconds#other" = "{count} 초";
|
||||
"lng_duration_minsec_minutes#one" = "{count} 분";
|
||||
"lng_duration_minsec_minutes#other" = "{count} 분";
|
||||
"lng_duration_minsec_seconds#one" = "{count} 초";
|
||||
"lng_duration_minsec_seconds#other" = "{count} 초";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_add_user" = "{from} 님께서 {user} 님을 초대하셨습니다.";
|
||||
"lng_action_add_users_many" = "{from}님께서 {users}명을 초대하였습니다.";
|
||||
@@ -676,33 +754,49 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_sticker" = "스티커";
|
||||
"lng_action_pinned_media_emoji_sticker" = " {emoji} 스티커";
|
||||
"lng_action_pinned_media_game" = " «{game}» 게임";
|
||||
"lng_action_game_score" = "{game} 에서 {from} 님이 {count:#|#|#} 점 획득";
|
||||
"lng_action_game_you_scored" = "{game} 에서 {count:#|#|#} 점 획득";
|
||||
"lng_action_game_score_no_game" = "{from} 에서 {count:#|#|#} 점 획득";
|
||||
"lng_action_game_you_scored_no_game" = "{count:#|#|#} 점 획득";
|
||||
"lng_action_game_score#one" = "{game} 에서 {from} 님이 {count} 점 획득";
|
||||
"lng_action_game_score#other" = "{game} 에서 {from} 님이 {count} 점 획득";
|
||||
"lng_action_game_you_scored#one" = "회원님이 {game}에서 {count}점 획득";
|
||||
"lng_action_game_you_scored#other" = "회원님이 {game}에서 {count}점 획득";
|
||||
"lng_action_game_score_no_game#one" = "{from}님이 {count}점 획득";
|
||||
"lng_action_game_score_no_game#other" = "{from}님이 {count}점 획득";
|
||||
"lng_action_game_you_scored_no_game#one" = "회원님이 {count}점 획득";
|
||||
"lng_action_game_you_scored_no_game#other" = "회원님이 {count}점 획득";
|
||||
"lng_action_payment_done" = "{amount}만큼 {user}에게 성공적으로 전송하였습니다.";
|
||||
"lng_action_payment_done_for" = "{invoice}에 대하여 {user}에게 {amount}만큼 전송하였습니다.";
|
||||
"lng_action_took_screenshot" = "{from} 님이 화면을 캡춰했습니다!";
|
||||
"lng_action_you_took_screenshot" = "화면을 캡춰했습니다!";
|
||||
|
||||
"lng_profile_migrate_reached" = "{count:_not_used_|# 명|# 명} 한계치에 도달 되었습니다.";
|
||||
"lng_ttl_photo_received" = "{from} 님이 자동삭제되는 사진을 전송했습니다. 휴대폰에서 확인해주세요.";
|
||||
"lng_ttl_photo_sent" = "자동삭제되는 사진을 전송했습니다.";
|
||||
"lng_ttl_photo_expired" = "사진 유효기간이 만료되었습니다.";
|
||||
"lng_ttl_video_received" = "{from} 님이 자동삭제되는 동영상을 전송했습니다. 휴대폰에서 확인해주세요.";
|
||||
"lng_ttl_video_sent" = "자동삭제되는 동영상을 전송했습니다.";
|
||||
"lng_ttl_video_expired" = "동영상 유효기간이 만료되었습니다.";
|
||||
|
||||
"lng_profile_migrate_reached#one" = "대화상대 한계치인 {count}명에 도달했습니다.";
|
||||
"lng_profile_migrate_reached#other" = "대화상대 한계치인 {count}명에 도달했습니다.";
|
||||
"lng_profile_migrate_body" = "제한을 초과하고 싶으실 경우, 슈퍼그룹으로 그룹 업그레이드가 가능합니다.";
|
||||
"lng_profile_migrate_learn_more" = "자세히 »";
|
||||
"lng_profile_migrate_about" = "최대허용치를 초과하시고 싶으실 경우, 슈퍼그룹방으로 업그레이드해주세요. 슈퍼그룹방은 :";
|
||||
"lng_profile_migrate_feature1" = "— 최대 {count:_not_used_|# 명|# 명} 까지 허용 가능합니다.";
|
||||
"lng_profile_migrate_feature2" = "— 모든 구성원이 전체 내용을 볼 수 있습니다.";
|
||||
"lng_profile_migrate_feature3" = "— 관리자는 구성원으로 부터 메시지 삭제가 가능합니다.";
|
||||
"lng_profile_migrate_feature1#one" = "— 최대 {count}명까지 허용 가능합니다.";
|
||||
"lng_profile_migrate_feature1#other" = "— 최대 {count}명까지 허용 가능합니다.";
|
||||
"lng_profile_migrate_feature2" = "— 모든 대화상대가 전체 내용을 볼 수 있습니다.";
|
||||
"lng_profile_migrate_feature3" = "— 관리자는 대화상대로 부터 메시지 삭제가 가능합니다.";
|
||||
"lng_profile_migrate_feature4" = "— 기본값으로 알림이 무음으로 처리됩니다";
|
||||
"lng_profile_migrate_button" = "슈퍼그룹방으로 업그레이드하기";
|
||||
"lng_profile_migrate_sure" = "정말로 그룹방을 슈퍼그룹방으로 변환하시겠습니까? 이 작업은 취소가 불가능합니다.";
|
||||
"lng_profile_convert_button" = "슈퍼그룹으로 전환";
|
||||
"lng_profile_convert_title" = "슈퍼그룹으로 전환";
|
||||
"lng_profile_convert_about" = "슈퍼그룹:";
|
||||
"lng_profile_convert_feature1" = "— 모든 구성원이 이전 대화 내용 조회";
|
||||
"lng_profile_convert_feature1" = "— 모든 대화상대가 이전 대화 내용 조회";
|
||||
"lng_profile_convert_feature2" = "— 메시지 삭제시 모두에게 삭제";
|
||||
"lng_profile_convert_feature3" = "— 관리자는 중요한 메시지 고정 가능";
|
||||
"lng_profile_convert_feature4" = "— 방 생성자가 그룹 공개링크 생성가능";
|
||||
"lng_profile_convert_warning" = "{bold_start}주의:{bold_end} 이 작업은 되돌릴 수 없습니다.";
|
||||
"lng_profile_convert_confirm" = "변환";
|
||||
"lng_profile_add_more_after_upgrade" = "그룹에서 슈퍼그룹으로 업그레이드시 {count:_not_used_|# 명|# 명} 까지 추가 가능합니다.";
|
||||
"lng_profile_add_more_after_upgrade#one" = "그룹에서 슈퍼그룹으로 업그레이드시 {count}명까지 추가 가능합니다.";
|
||||
"lng_profile_add_more_after_upgrade#other" = "그룹에서 슈퍼그룹으로 업그레이드시 {count}명까지 추가 가능합니다.";
|
||||
|
||||
"lng_channel_not_accessible" = "채널에 접근 할 수 없습니다.";
|
||||
"lng_group_not_accessible" = "죄송합니다. 그룹방에 접근 할 수 없습니다.";
|
||||
@@ -717,7 +811,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_group_invite_want_join_channel" = "«{title}» 채널에 참여하시겠습니까?";
|
||||
"lng_group_invite_join" = "참여";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# 회원|# 회원}, 참여자 현황:";
|
||||
"lng_group_invite_members#one" = "대화상대 {count}명, 참여자 현황:";
|
||||
"lng_group_invite_members#other" = "대화상대 {count}명, 참여자 현황:";
|
||||
|
||||
"lng_group_invite_link" = "초대링크: ";
|
||||
"lng_group_invite_create" = "초대링크 생성";
|
||||
@@ -730,6 +825,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_channel_public_link_copied" = "클립보드에 링크가 복사되었습니다.";
|
||||
|
||||
"lng_forwarded" = "{user}님으로 부터 전달 받음";
|
||||
"lng_forwarded_date" = "원본: {date}";
|
||||
"lng_forwarded_channel" = "{channel}로 부터 전달 받음";
|
||||
"lng_forwarded_via" = "{inline_bot}을 {user}로 부터 전달 받음";
|
||||
"lng_forwarded_channel_via" = "{inline_bot}을 {channel}로 부터 전달 받음";
|
||||
@@ -809,7 +905,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_stickers_you_have" = "스티커팩 관리 및 변경";
|
||||
"lng_stickers_featured" = "인기 스티커";
|
||||
"lng_stickers_return" = "실행취소";
|
||||
"lng_stickers_count" = "{count:Loading...|# 스티커|# 스티커}";
|
||||
"lng_stickers_count#one" = "스티커 {count}개";
|
||||
"lng_stickers_count#other" = "스티커 {count}개";
|
||||
"lng_stickers_masks_pack" = "마스크 스티커 팩입니다. 모바일 기기에 있는 사진 에디터에서 사용 가능합니다.";
|
||||
|
||||
"lng_in_dlg_photo" = "사진";
|
||||
@@ -839,6 +936,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_cant_invite_banned" = "죄송하지만, 관리자만 회원 추가가 가능합니다.";
|
||||
"lng_cant_invite_privacy" = "죄송합니다, 개인설정으로 인하여 이 사용자를 그룹에 초대할 수 없습니다.";
|
||||
"lng_cant_invite_privacy_channel" = "죄송합니다, 개인설정으로 인하여 이 사용자를 채널에 초대할 수 없습니다.";
|
||||
"lng_cant_delete_group#one" = "죄송합니다, 현재 {count}명 이상 사용자가 있는 그룹일 경우 삭제할 수 없습니다. 삭제하고 싶으실 경우 텔레그램 질문하기로 문의해주세요";
|
||||
"lng_cant_delete_group#other" = "죄송합니다, 현재 {count}명 이상 사용자가 있는 그룹일 경우 삭제할 수 없습니다. 삭제하고 싶으실 경우 텔레그램 질문하기로 문의해주세요";
|
||||
"lng_cant_delete_channel#one" = "죄송합니다, 현재 {count}명 이상 사용자가 있는 채널일 경우 삭제할 수 없습니다. 삭제하고 싶으실 경우 텔레그램 질문하기로 문의해주세요.";
|
||||
"lng_cant_delete_channel#other" = "죄송합니다, 현재 {count}명 이상 사용자가 있는 채널일 경우 삭제할 수 없습니다. 삭제하고 싶으실 경우 텔레그램 질문하기로 문의해주세요.";
|
||||
"lng_cant_do_this" = "죄송하지만, 할 수 없는 기능입니다.";
|
||||
|
||||
"lng_send_button" = "보내기";
|
||||
@@ -846,8 +947,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_broadcast_ph" = "단체메시지 쓰기...";
|
||||
"lng_broadcast_silent_ph" = "음소거 메시지...";
|
||||
"lng_record_cancel" = "이 영역 밖에서 마우스 클릭을 해제하시면 취소가 됩니다.";
|
||||
"lng_will_be_notified" = "메시지 작성시 구성원들에게 알림이 갑니다.";
|
||||
"lng_wont_be_notified" = "메시지 작성시 구성원들에게 알림이 가지 않습니다.";
|
||||
"lng_will_be_notified" = "메시지 작성시 대화상대에게 알림이 갑니다.";
|
||||
"lng_wont_be_notified" = "메시지 작성시 대화상대에게 알림이 가지 않습니다.";
|
||||
"lng_willbe_history" = "대화하실 방을 선택해주세요.";
|
||||
"lng_from_you" = "회원님";
|
||||
"lng_from_draft" = "임시저장";
|
||||
@@ -884,11 +985,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_typing" = "입력중";
|
||||
"lng_user_typing" = "{user}님이 입력중입니다.";
|
||||
"lng_users_typing" = "{user}님과 {second_user}님이 입력중입니다.";
|
||||
"lng_many_typing" = "{count:_not_used_|#명이|#명이} 입력중입니다";
|
||||
"lng_many_typing#one" = "{count}명이 입력중";
|
||||
"lng_many_typing#other" = "{count}명이 입력중";
|
||||
"lng_playing_game" = "게임 중";
|
||||
"lng_user_playing_game" = "{user}님이 게임 중입니다.";
|
||||
"lng_users_playing_game" = "{user}님과 {second_user}님이 게임 중입니다.";
|
||||
"lng_many_playing_game" = "{count:_not_used_|#명이|#명이} 게임 중입니다";
|
||||
"lng_many_playing_game#one" = "{count}명이 게임 중";
|
||||
"lng_many_playing_game#other" = "{count}명이 게임 중";
|
||||
"lng_send_action_record_video" = "비디오 녹화 중";
|
||||
"lng_user_action_record_video" = "{user}님이 녹화중입니다";
|
||||
"lng_send_action_upload_video" = "비디오 전송 중";
|
||||
@@ -909,7 +1012,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_geo_location" = "{user}님이 위치를 선택 중입닏";
|
||||
"lng_send_action_choose_contact" = "연락처 선택 중";
|
||||
"lng_user_action_choose_contact" = "{user}님이 연락처를 선택 중입니다";
|
||||
"lng_unread_bar" = "{count:_not_used_|#개의 읽지 않은 메시지|#개의 읽지 않은 메시지}";
|
||||
"lng_unread_bar#one" = "안 읽은 메시지 {count}개";
|
||||
"lng_unread_bar#other" = "안 읽은 메시지 {count}개";
|
||||
|
||||
"lng_maps_point" = "위치";
|
||||
"lng_save_photo" = "사진 저장";
|
||||
@@ -932,7 +1036,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_from_top" = "상단에서 고정해제";
|
||||
|
||||
"lng_context_promote_admin" = "관리자로 지정";
|
||||
"lng_context_remove_admin" = "관리자에서 제외";
|
||||
"lng_context_edit_permissions" = "권한 변경";
|
||||
"lng_context_restrict_user" = "사용자 제한";
|
||||
"lng_context_remove_from_group" = "그룹에서 추방";
|
||||
|
||||
"lng_context_copy_link" = "링크 복사";
|
||||
@@ -969,32 +1074,42 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_pin_msg" = "메시지 고정";
|
||||
"lng_context_unpin_msg" = "메시지 고정해제";
|
||||
"lng_context_cancel_upload" = "업로드 취소";
|
||||
"lng_context_copy_selected" = "선택한 메시지 복사";
|
||||
"lng_context_copy_selected" = "선택한 텍스트 복사";
|
||||
"lng_context_copy_selected_items" = "선택한 내용 텍스트 복사";
|
||||
"lng_context_forward_selected" = "선택된 메시지 전달";
|
||||
"lng_context_delete_selected" = "선택된 메시지 삭제";
|
||||
"lng_context_clear_selection" = "선택된 메시지 초기화";
|
||||
"lng_really_send_image" = "선택한 이미지를 전송하시겠습니까?";
|
||||
"lng_really_send_file" = "선택한 파일을 전송하시겠습니까?";
|
||||
"lng_really_share_contact" = "선택한 연락처를 공유하시겠습니까?";
|
||||
"lng_send_images_compress" = "압축 {count:_not_used_|이미지|이미지}";
|
||||
"lng_send_images_compress#one" = "압축된 이미지";
|
||||
"lng_send_images_compress#other" = "압축된 이미지";
|
||||
"lng_send_image_non_local" = "로컬이 아닌 파일을 전송 할 수 없습니다 : {name}";
|
||||
"lng_send_image_empty" = "빈 파일을 전송 할 수 없습니다 : {name}";
|
||||
"lng_send_image_too_large" = "파일이 1500MB 이상이기 때문에 전송 할 수 없습니다: {name}";
|
||||
"lng_send_folder" = " «{name}»은 폴더이기 때문에 전송 할 수 없습니다 :(";
|
||||
"lng_send_images_selected" = "{count:_not_used_|# 이미지|# 이미지} 선택";
|
||||
"lng_send_photos" = "전송 {count:_not_used_|# 사진|# 사진}";
|
||||
"lng_send_files_selected" = "{count:_not_used_|# 파일|# 파일} 선택";
|
||||
"lng_send_files" = "전송 {count:_not_used_|# 파일|# 파일}";
|
||||
"lng_send_images_selected#one" = "이미지 {count}개가 선택됨";
|
||||
"lng_send_images_selected#other" = "이미지 {count}개가 선택됨";
|
||||
"lng_send_photos#one" = "{count}개의 사진 전송";
|
||||
"lng_send_photos#other" = "{count}개의 사진 전송";
|
||||
"lng_send_files_selected#one" = "파일 {count}개 선택됨";
|
||||
"lng_send_files_selected#other" = "파일 {count}개 선택됨";
|
||||
"lng_send_files#one" = "{count}개의 파일 전송";
|
||||
"lng_send_files#other" = "{count}개의 파일 전송";
|
||||
|
||||
"lng_forward_choose" = "수신자를 선택..";
|
||||
"lng_forward_cant" = "이쪽으로 전달 할 수 없습니다 :(";
|
||||
"lng_forward_confirm" = "{recipient} 님에게 전달하시겠습니까?";
|
||||
"lng_forward_share_contact" = "{recipient} 님에게 연락처를 공유하시겠습니까?";
|
||||
"lng_forward_share_cant" = "죄송합니다, 여기서 연락처를 공유할 수 없습니다 :(";
|
||||
"lng_forward_send_file_confirm" = "«{name}» 을 {recipient} 님에게 보내시겠습니까?";
|
||||
"lng_forward_send_files_confirm" = "선택한 파일을 {recipient} 님에게 보내시겠습니까?";
|
||||
"lng_forward_send_files_cant" = "죄송합니다, 여기서 미디어를 공유할 수 없습니다 :(";
|
||||
"lng_forward_send" = "보내기";
|
||||
"lng_forward_messages" = "{count:_not_used_|전달받은 메시지|# 개의 전달받은 메시지}";
|
||||
"lng_forwarding_from" = "{user} 님과 {count:_not_used_|# 명|# 명}";
|
||||
"lng_forward_messages#one" = "전달된 메시지 {count}개";
|
||||
"lng_forward_messages#other" = "전달된 메시지 {count}개";
|
||||
"lng_forwarding_from#one" = "{user}님 이외 {count}명";
|
||||
"lng_forwarding_from#other" = "{user}님 이외 {count}명";
|
||||
"lng_forwarding_from_two" = "{user} 님과 {second_user}";
|
||||
"lng_inline_switch_choose" = "대화 선택...";
|
||||
"lng_inline_switch_cant" = "죄송합니다. 이쪽으로 글을 쓸 수 없습니다 :(";
|
||||
@@ -1016,6 +1131,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_contact_title" = "연락처 이름 수정";
|
||||
"lng_edit_channel_title" = "채널 수정";
|
||||
"lng_edit_sign_messages" = "서명 메시지";
|
||||
"lng_edit_group_who_invites" = "초대가 가능한 사용자";
|
||||
"lng_edit_group_invites_everybody" = "모든 사용자";
|
||||
"lng_edit_group_invites_only_admins" = "관리자만 가능";
|
||||
"lng_edit_group" = "그룹방 수정";
|
||||
"lng_edit_self_title" = "이름 수정";
|
||||
"lng_confirm_contact_data" = "새로운 연락처";
|
||||
@@ -1040,15 +1158,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_selected_clear" = "취소";
|
||||
"lng_selected_delete" = "삭제";
|
||||
"lng_selected_forward" = "전달";
|
||||
"lng_selected_count" = "{count:_not_used_|# 메시지|# 메시지}";
|
||||
"lng_selected_count#one" = "메시지 {count}개";
|
||||
"lng_selected_count#other" = "메시지 {count}개";
|
||||
"lng_selected_cancel_sure_this" = "업로드를 취소하시겠습니까?";
|
||||
"lng_selected_upload_stop" = "정지";
|
||||
"lng_selected_delete_sure_this" = "메시지를 삭제하시겠습니까?";
|
||||
"lng_selected_delete_sure" = "{count:_not_used_|# 메시지|# 메시지}를 삭제하시겠습니까?";
|
||||
"lng_selected_delete_sure#one" = "{count}개의 메시지를 삭제하시겠습니까?";
|
||||
"lng_selected_delete_sure#other" = "{count}개의 메시지를 삭제하시겠습니까?";
|
||||
"lng_delete_photo_sure" = "사진을 삭제하시겠습니까?";
|
||||
"lng_delete_for_everyone_hint" = "This will delete {count:_not_used_|it|them} for everyone in this chat.";
|
||||
"lng_delete_for_me_chat_hint" = "이 작업은 다른분들이 아닌 회원님에게만 {count:_not_used_|이것|이것들} 을 삭제하게됩니다.";
|
||||
"lng_delete_for_me_hint" = "이 작업은 회원님에게만 {count:_not_used_|이것|이것들} 을 삭제하게됩니다.";
|
||||
"lng_delete_for_everyone_hint#one" = "이 메시지는 이 대화방에 있는 모두에게 삭제됩니다.";
|
||||
"lng_delete_for_everyone_hint#other" = "이 메시지는 이 대화방에 있는 모두에게 삭제됩니다.";
|
||||
"lng_delete_for_me_chat_hint#one" = "이 메시지는 다른 대화상대에게는 삭제가 되지 않고, 회원님에게만 삭제됩니다.";
|
||||
"lng_delete_for_me_chat_hint#other" = "이 메시지는 다른 대화상대에게는 삭제가 되지 않고, 회원님에게만 삭제됩니다.";
|
||||
"lng_delete_for_me_hint#one" = "이 메시지는 회원님에게만 삭제됩니다.";
|
||||
"lng_delete_for_me_hint#other" = "이 메시지는 회원님에게만 삭제됩니다.";
|
||||
"lng_delete_for_everyone_check" = "모두에게 삭제";
|
||||
"lng_delete_for_other_check" = "{user}에게 메시지 삭제";
|
||||
"lng_box_delete" = "삭제";
|
||||
@@ -1060,7 +1183,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_about_text_3" = "자세한 사항은 {faq_open}Telegram FAQ{faq_close} 에서 확인해주세요.";
|
||||
"lng_about_done" = "완료";
|
||||
|
||||
"lng_search_found_results" = "{count:메시지를 찾을 수 없습니다.|# 개의 메시지를 찾았습니다.|# 개의 메시지를 찾았습니다.}";
|
||||
"lng_search_no_results" = "메시지를 찾을 수 없습니다.";
|
||||
"lng_search_found_results#one" = "{count}개의 메시지를 찾았습니다.";
|
||||
"lng_search_found_results#other" = "{count}개의 메시지를 찾았습니다.";
|
||||
"lng_search_global_results" = "아이디 검색 결과";
|
||||
|
||||
"lng_media_save_progress" = "{ready} / {total} {mb}";
|
||||
@@ -1169,11 +1294,133 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_player_message_yesterday" = "어제 {time}";
|
||||
"lng_player_message_date" = "{date} {time}";
|
||||
|
||||
"lng_rights_edit_admin" = "관리가 변경";
|
||||
"lng_rights_edit_admin_header" = "이 관리자가 할 수 있는 것은?";
|
||||
"lng_rights_about_add_admins_yes" = "이 관리자는 동일한 권한 (혹은 더 제한된) 으로만 관리자 추가가 가능합니다.";
|
||||
"lng_rights_about_add_admins_no" = "이 관리자는 새로운 관리자 설정을 할 수 없습니다.";
|
||||
"lng_rights_about_admin_cant_edit" = "이 관리자의 권한을 변경 할 수 없습니다.";
|
||||
"lng_rights_user_restrictions" = "사용자 제한";
|
||||
"lng_rights_user_restrictions_header" = "이 사용자가 할 수 있는 것은?";
|
||||
|
||||
"lng_rights_channel_info" = "채널 정보 변경";
|
||||
"lng_rights_channel_post" = "메시지 작성";
|
||||
"lng_rights_channel_edit" = "다른 사용자 메시지 수정";
|
||||
"lng_rights_channel_delete" = "다른 사용자 메시지 삭제";
|
||||
"lng_rights_group_info" = "그룹 정보 변경";
|
||||
"lng_rights_group_ban" = "사용자 차단";
|
||||
"lng_rights_group_invite_link" = "링크를 통하여 사용자 초대";
|
||||
"lng_rights_group_invite" = "사용자 추가";
|
||||
"lng_rights_group_pin" = "메시지 고정";
|
||||
"lng_rights_group_delete" = "메시지 삭제";
|
||||
"lng_rights_add_admins" = "새 관리자 추가";
|
||||
"lng_rights_chat_read" = "메시지 읽기";
|
||||
"lng_rights_chat_send_text" = "메시지 전송";
|
||||
"lng_rights_chat_send_media" = "미디어 전송";
|
||||
"lng_rights_chat_send_stickers" = "스티커 & GIF 전송";
|
||||
"lng_rights_chat_send_links" = "링크 저장";
|
||||
"lng_rights_chat_banned_until_header" = "다음까지 제한";
|
||||
"lng_rights_chat_banned_forever" = "영원히";
|
||||
"lng_rights_chat_banned_day#one" = "{count} 일 까지";
|
||||
"lng_rights_chat_banned_day#other" = "{count} 일 까지";
|
||||
"lng_rights_chat_banned_week#one" = "{count} 주 까지";
|
||||
"lng_rights_chat_banned_week#other" = "{count} 주 까지";
|
||||
"lng_rights_chat_banned_custom" = "커스텀";
|
||||
"lng_rights_chat_banned_custom_date" = "{date} 일까지";
|
||||
"lng_rights_chat_banned_block" = "그룹에서 차단 후 추방";
|
||||
|
||||
"lng_restricted_send_message" = "그룹 관리자가 회원님의 메시지 작성을 제한했습니다.";
|
||||
"lng_restricted_send_media" = "그룹 관리자가 회원님의 미디어 전송을 제한했습니다.";
|
||||
"lng_restricted_send_stickers" = "그룹 관리자가 회원님의 스티커 전송을 제한했습니다.";
|
||||
"lng_restricted_send_gifs" = "그룹 관리자가 회원님의 GIF 전송을 제한했습니다.";
|
||||
"lng_restricted_send_inline" = "그룹 관리자가 회원님의 인라인 명령어를 제한했습니다.";
|
||||
|
||||
"lng_restricted_list_title" = "제한된 사용자";
|
||||
"lng_banned_list_title" = "차단된 사용자";
|
||||
|
||||
"lng_admin_log_title_all" = "모든 활동";
|
||||
"lng_admin_log_title_selected" = "선택한 활동";
|
||||
"lng_admin_log_filter" = "필터";
|
||||
"lng_admin_log_filter_title" = "필터";
|
||||
"lng_admin_log_filter_all_actions" = "모든 활동";
|
||||
"lng_admin_log_filter_restrictions" = "새 제한";
|
||||
"lng_admin_log_filter_admins_new" = "새 관리자";
|
||||
"lng_admin_log_filter_members_new" = "새 사용자";
|
||||
"lng_admin_log_filter_info_group" = "그룹 정보";
|
||||
"lng_admin_log_filter_info_channel" = "채널 정보";
|
||||
"lng_admin_log_filter_messages_deleted" = "삭제된 메시지";
|
||||
"lng_admin_log_filter_messages_edited" = "수정된 메시지";
|
||||
"lng_admin_log_filter_messages_pinned" = "고정된 메시지";
|
||||
"lng_admin_log_filter_members_removed" = "추방된 사용자";
|
||||
"lng_admin_log_filter_all_admins" = "모든 사용자 및 관리자";
|
||||
"lng_admin_log_about" = "이것은 무엇인가요?";
|
||||
"lng_admin_log_about_text" = "그룹 사용자와 관리자의 지난 48시간동안 활동 리스트입니다.";
|
||||
"lng_admin_log_no_results_title" = "활동내역을 찾을 수 없습니다.";
|
||||
"lng_admin_log_no_results_text" = "검색한 내용의 활동을 찾을 수 없습니다.";
|
||||
"lng_admin_log_no_results_search_text" = "검색한 '{query}'을/를 포함한 활동을 찾을 수 없습니다.";
|
||||
"lng_admin_log_no_events_title" = "아직 활동내역이 없습니다.";
|
||||
"lng_admin_log_no_events_text" = "그룹 사용자와 관리자의\n지난 48시간동안\n활동 리스트입니다.";
|
||||
|
||||
"lng_admin_log_empty_text" = "없음";
|
||||
"lng_admin_log_changed_title_group" = "{from} 님이 그룹이름을 «{title}» 로 바꾸셨습니다.";
|
||||
"lng_admin_log_changed_title_channel" = "{from} 님이 채널이름을 «{title}» 로 바꾸셨습니다.";
|
||||
"lng_admin_log_changed_description_group" = "{from} 님이 그룹정보을 변경했습니다:";
|
||||
"lng_admin_log_removed_description_group" = "{from} 님이 그룹정보을 삭제했습니다.";
|
||||
"lng_admin_log_changed_description_channel" = "{from} 님이 채널정보을 변경했습니다:";
|
||||
"lng_admin_log_removed_description_channel" = "{from} 님이 그룹정보을 삭제했습니다.";
|
||||
"lng_admin_log_previous_description" = "기존 정보";
|
||||
"lng_admin_log_changed_link_group" = "{from} 님이 그룹링크을 변경했습니다:";
|
||||
"lng_admin_log_removed_link_group" = "{from} 님이 그룹링크를 삭제했습니다.";
|
||||
"lng_admin_log_changed_link_channel" = "{from} 님이 채널링크를 변경했습니다:";
|
||||
"lng_admin_log_removed_link_channel" = "{from} 님이 채널링크를 삭제했습니다.";
|
||||
"lng_admin_log_previous_link" = "기존 링크";
|
||||
"lng_admin_log_changed_photo_group" = "{from} 님이 그룹사진을 변경했습니다.";
|
||||
"lng_admin_log_changed_photo_channel" = "{from} 님이 채널사진을 변경했습니다.";
|
||||
"lng_admin_log_removed_photo_group" = "{from} 님이 그룹사진을 삭제했습니다.";
|
||||
"lng_admin_log_removed_photo_channel" = "{from} 님이 채널사진을 삭제했습니다.";
|
||||
"lng_admin_log_invites_enabled" = "{from} 님이 그룹 초대를 허용했습니다.";
|
||||
"lng_admin_log_invites_disabled" = "{from} 님이 그룹 초대를 금지했습니다.";
|
||||
"lng_admin_log_signatures_enabled" = "{from} 님이 서명을 허용했습니다.";
|
||||
"lng_admin_log_signatures_disabled" = "{from} 님이 서명을 금지했습니다.";
|
||||
"lng_admin_log_pinned_message" = "{from} 님이 메시지를 고정했습니다:";
|
||||
"lng_admin_log_unpinned_message" = "{from} 님이 메시지 고정을 해제했습니다.";
|
||||
"lng_admin_log_edited_caption" = "{from} 님이 자막을 변경했습니다:";
|
||||
"lng_admin_log_removed_caption" = "{from} 님이 자막은 삭제했습니다";
|
||||
"lng_admin_log_previous_caption" = "원본 자막";
|
||||
"lng_admin_log_edited_message" = "{from} 님이 메시지를 수정했습니다:";
|
||||
"lng_admin_log_previous_message" = "원본 메시지";
|
||||
"lng_admin_log_deleted_message" = "{from} 님이 메시지를 삭제했습니다:";
|
||||
"lng_admin_log_participant_joined" = "{from} 님이 그룹에 들어왔습니다.";
|
||||
"lng_admin_log_participant_joined_channel" = "{from} 님이 채널에 들어오셨습니다.";
|
||||
"lng_admin_log_participant_left" = "{from} 님이 그룹을 나갔습니다.";
|
||||
"lng_admin_log_participant_left_channel" = "{from} 님이 채널을 나가셨습니다.";
|
||||
"lng_admin_log_invited" = "{user} 님을 초대함";
|
||||
"lng_admin_log_banned" = "{user} 님을 차단함";
|
||||
"lng_admin_log_restricted" = "{until}까지 {user}에 대한 제한을 변경함";
|
||||
"lng_admin_log_promoted" = "{user}님에 대한 권한을 변경함";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_restricted_forever" = "기한 없음";
|
||||
"lng_admin_log_restricted_until" = "{date} 까지";
|
||||
"lng_admin_log_banned_view_messages" = "메시지 읽기";
|
||||
"lng_admin_log_banned_send_messages" = "메시지 전송";
|
||||
"lng_admin_log_banned_send_media" = "미디어 전송";
|
||||
"lng_admin_log_banned_send_stickers" = "스티커 & GIF 전송";
|
||||
"lng_admin_log_banned_embed_links" = "링크 저장";
|
||||
"lng_admin_log_admin_change_info" = "채널 정보";
|
||||
"lng_admin_log_admin_post_messages" = "메시지 작성";
|
||||
"lng_admin_log_admin_edit_messages" = "메시지 수정";
|
||||
"lng_admin_log_admin_delete_messages" = "메시지 삭제";
|
||||
"lng_admin_log_admin_ban_users" = "사용자 차단";
|
||||
"lng_admin_log_admin_invite_users" = "사용자 추가";
|
||||
"lng_admin_log_admin_invite_link" = "링크를 통하여 사용자 초대";
|
||||
"lng_admin_log_admin_pin_messages" = "메시지 고정";
|
||||
"lng_admin_log_admin_add_admins" = "새 관리자 추가";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "정보";
|
||||
"lng_profile_group_info" = "그룹 정보";
|
||||
"lng_profile_channel_info" = "채널 정보";
|
||||
"lng_channel_add_admins" = "새로운 관리자";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_menu_update" = "Bijwerken";
|
||||
"lng_menu_restart" = "Herstarten";
|
||||
"lng_menu_back" = "Vorige";
|
||||
"lng_menu_night_mode" = "Nachtmodus";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Meldingen uitschakelen";
|
||||
"lng_enable_notifications_from_tray" = "Meldingen inschakelen";
|
||||
@@ -88,7 +89,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_continue" = "Doorgaan";
|
||||
"lng_close" = "Sluiten";
|
||||
"lng_connecting" = "Verbinden...";
|
||||
"lng_reconnecting" = "Opnieuw verbinden {count:nu|over # s|over # s}...";
|
||||
"lng_connecting_to_proxy" = "Verbinden via proxy...";
|
||||
"lng_connecting_settings" = "Instellingen";
|
||||
"lng_reconnecting#one" = "Opnieuw verbinden over {count}s...";
|
||||
"lng_reconnecting#other" = "Opnieuw verbinden over {count}s...";
|
||||
"lng_reconnecting_try_now" = "Probeer nu";
|
||||
|
||||
"lng_status_service_notifications" = "servicemeldingen";
|
||||
@@ -102,8 +106,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_last_month" = "afgelopen maand gezien";
|
||||
"lng_status_invisible" = "onzichtbaar";
|
||||
"lng_status_lastseen_now" = "laatst gezien zojuist";
|
||||
"lng_status_lastseen_minutes" = "laatst gezien {count:_not_used_|# min|# min} geleden";
|
||||
"lng_status_lastseen_hours" = "laatst gezien {count:_not_used_|# uur|# uur} geleden";
|
||||
"lng_status_lastseen_minutes#one" = "laatst gezien {count} minuut geleden";
|
||||
"lng_status_lastseen_minutes#other" = "laatst gezien {count} minuten geleden";
|
||||
"lng_status_lastseen_hours#one" = "laatst gezien {count} uur geleden";
|
||||
"lng_status_lastseen_hours#other" = "laatst gezien {count} uur geleden";
|
||||
"lng_status_lastseen_today" = "laatst gezien vandaag om {time}";
|
||||
"lng_status_lastseen_yesterday" = "laatst gezien gisteren om {time}";
|
||||
"lng_status_lastseen_date" = "laatst gezien {date}";
|
||||
@@ -112,24 +118,43 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_connecting" = "verbinden...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "Groep is ontoegankelijk";
|
||||
"lng_chat_status_members" = "{count:geen leden|# lid|# leden}";
|
||||
"lng_chat_status_members_online" = "{count:_not_used_|# lid|# leden}, {count_online:_not_used_|# online|# online}";
|
||||
"lng_chat_status_no_members" = "geen leden";
|
||||
"lng_chat_status_members#one" = "{count} lid";
|
||||
"lng_chat_status_members#other" = "{count} leden";
|
||||
"lng_chat_status_online#one" = "{count} online";
|
||||
"lng_chat_status_online#other" = "{count} online";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
|
||||
"lng_channel_status" = "kanaal";
|
||||
"lng_group_status" = "groep";
|
||||
|
||||
"lng_channel_members_link" = "{count:_not_used_|# lid|# leden}";
|
||||
"lng_channel_admins_link" = "{count:_not_used_|# beheerder|# beheerders}";
|
||||
"lng_channel_members_link#one" = "{count} lid";
|
||||
"lng_channel_members_link#other" = "{count} leden";
|
||||
"lng_channel_admins_link#one" = "{count} beheerder";
|
||||
"lng_channel_admins_link#other" = "{count} beheerders";
|
||||
|
||||
"lng_server_error" = "Interne serverfout.";
|
||||
"lng_flood_error" = "Teveel pogingen. Probeer het later opnieuw.";
|
||||
"lng_gif_error" = "Er is iets een fout opgetreden bij het lezen van de GIF :(";
|
||||
"lng_gif_error" = "Er is iets misgegaan bij het lezen van deze GIF :(";
|
||||
"lng_edit_error" = "Je mag dit bericht niet wijzigen";
|
||||
"lng_join_channel_error" = "Je bent lid van teveel kanalen of supergroepen, verlaat er wat om hier lid te worden.";
|
||||
"lng_error_phone_flood" = "Je hebt in korte tijd je account veelvuldig verwijderd en opnieuw aangemaakt. Probeer het over een aantal dagen nog eens.";
|
||||
"lng_error_start_minimized_passcoded" = "Je hebt een toegangscode ingesteld, deze zal ingegeven moeten worden na het starten, geminimaliseerd starten kan daarom niet.";
|
||||
"lng_error_pinned_max" = "Sorry, je kunt niet meer dan {count:_not_used_|# chat|# chats} vastzetten.";
|
||||
"lng_error_pinned_max#one" = "Sorry, je kunt niet meer dan {count} chat vastzetten.";
|
||||
"lng_error_pinned_max#other" = "Sorry, je kunt niet meer dan {count} chats vastzetten.";
|
||||
"lng_error_public_groups_denied" = "Sorry, je mag niet meer deelnemen aan publieke groepen.\n{more_info}";
|
||||
"lng_error_cant_edit_admin" = "Je kunt de machtigingen van deze beheerder niet wijzigen.";
|
||||
"lng_error_cant_add_member" = "Je kunt deze bot niet toevoegen aan de groep, vraag een beheerder om dit te doen.";
|
||||
"lng_error_cant_add_bot" = "Deze bot kan geen lid worden van groepen.";
|
||||
"lng_error_cant_add_admin_invite" = "Je mag geen leden toevoegen, deze gebruiker is nog geen lid en kan daarom niet worden toegevoegd als beheerder.";
|
||||
"lng_error_cant_add_admin_unban" = "Je mag geen leden deblokkeren, deze gebruiker is geblokkeerd en kan daarom niet worden toegevoegd als beheerder.";
|
||||
"lng_error_cant_ban_admin" = "Je mag geen leden degraderen, deze gebruiker is een beheerder en kan daarom niet worden geblokkeerd.";
|
||||
"lng_sure_add_admin_invite" = "Deze gebruiker is geen lid, gebruiker toevoegen als beheerder?";
|
||||
"lng_sure_add_admin_unban" = "Deze gebruiker is geblokkeerd of beperkt, wil je dit ongedaan maken en de gebruiker promoveren?";
|
||||
"lng_sure_ban_admin" = "Deze gebruiker is een beheerder, gebruiker echt beperken?";
|
||||
"lng_sure_ban_user_group" = "{user} blokkeren en verwijderen?";
|
||||
"lng_sure_enable_socks" = "Proxy echt inschakelen? \n\nHost: {server}\nPoort: {port}\n\nJe kunt de proxy-server aanpassen via Instellingen (Verbindingstype).";
|
||||
"lng_sure_enable" = "Inschakelen";
|
||||
|
||||
"lng_edit_deleted" = "Bericht is gewist";
|
||||
"lng_edit_too_long" = "Je bericht is te lang";
|
||||
@@ -198,9 +223,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_signin_sure_reset" = "Let op:\n\nAl je chats, berichten en alle andere data gaan verloren als je verder gaat!\n\nEcht je account resetten?";
|
||||
"lng_signin_reset" = "Reset";
|
||||
"lng_signin_reset_wait" = "Account {phone_number} is actief en beveiligd met een wachtwoord, het verwijderen stellen we daarom 1 week uit.\nJe kunt dit proces ieder moment annuleren.\n\nJe account kan gereset worden over:\n{when}";
|
||||
"lng_signin_reset_in_days" = "{count_days:0 dagen|# dag|# dagen} {count_hours:0 uur|# uur|# uur} {count_minutes:0 minuten|# minuut|# minuten}";
|
||||
"lng_signin_reset_in_hours" = "{count_hours:0 uur|# uur|# uur} {count_minutes:0 minuten|# minuut|# minuten}";
|
||||
"lng_signin_reset_in_minutes" = "{count_minutes:0 minuten|# minuut|# minuten}";
|
||||
"lng_signin_reset_days#one" = "{count} dag";
|
||||
"lng_signin_reset_days#other" = "{count} dagen";
|
||||
"lng_signin_reset_hours#one" = "{count} uur";
|
||||
"lng_signin_reset_hours#other" = "{count} uur";
|
||||
"lng_signin_reset_minutes#one" = "{count} minuut";
|
||||
"lng_signin_reset_minutes#other" = "{count} minuten";
|
||||
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
|
||||
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
|
||||
"lng_signin_reset_cancelled" = "De actieve gebruiker heeft de recente poging om dit account te resetten geannuleerd. Probeer het over 7 dagen nog eens.";
|
||||
|
||||
"lng_signup_title" = "Jouw Informatie";
|
||||
@@ -223,7 +253,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_settings_save" = "Opslaan";
|
||||
"lng_settings_upload" = "Profielfoto instellen";
|
||||
"lng_settings_crop_profile" = "Kies een vierkant voor je profielfoto";
|
||||
"lng_settings_crop_profile" = "Kies een gebied voor je profielfoto";
|
||||
"lng_settings_uploading_photo" = "Foto uploaden...";
|
||||
"lng_settings_edit" = "Wijzig";
|
||||
"lng_settings_drop_area_subtitle" = "om als foto in te stellen";
|
||||
@@ -241,15 +271,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_username_link" = "Deze link opent een chat met jou:";
|
||||
"lng_username_copied" = "Link gekopieerd naar klembord.";
|
||||
|
||||
"lng_bio_title" = "Bio wijzigen";
|
||||
"lng_bio_placeholder" = "Bio";
|
||||
"lng_bio_about" = "Je kunt hier wat over jezelf vertellen. Iedereen die je profiel opent kan deze tekst zien.";
|
||||
|
||||
"lng_settings_section_info" = "Info";
|
||||
"lng_settings_phone_number" = "Telefoonnummer:";
|
||||
"lng_settings_username" = "Gebruikersnaam:";
|
||||
"lng_settings_choose_username" = "gebruikersnaam kiezen";
|
||||
"lng_settings_empty_bio" = "Niets";
|
||||
|
||||
"lng_settings_section_notify" = "Meldingen";
|
||||
"lng_settings_desktop_notify" = "Desktopmeldingen";
|
||||
"lng_settings_show_name" = "Afzender weergeven";
|
||||
"lng_settings_show_preview" = "Voorvertoning weergeven";
|
||||
"lng_settings_show_preview" = "Voorbeeld weergeven";
|
||||
"lng_settings_use_windows" = "Windows-berichtgeving gebruiken";
|
||||
"lng_settings_use_native_notifications" = "Linux-berichtgeving gebruiken";
|
||||
"lng_settings_advanced_notifications" = "Plaats en teller voor meldingen";
|
||||
@@ -303,7 +338,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_backgrounds_header" = "Kies je nieuwe achtergrond";
|
||||
"lng_theme_sure_keep" = "Dit thema behouden?";
|
||||
"lng_theme_reverting" = "Ongedaan maken over {count:_not_used_|# seconde|# seconden}.";
|
||||
"lng_theme_reverting#one" = "Ongedaan maken over {count} seconde.";
|
||||
"lng_theme_reverting#other" = "Ongedaan maken over {count} seconden.";
|
||||
"lng_theme_keep_changes" = "Behouden";
|
||||
"lng_theme_revert" = "Herstellen";
|
||||
|
||||
@@ -329,14 +365,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_local_storage_title" = "Lokale opslag";
|
||||
"lng_settings_no_data_cached" = "Geen cache-data gevonden!";
|
||||
"lng_settings_images_cached" = "{count:_not_used_|# afbeelding|# afbeeldingen}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|# spraakbericht|# spraakberichten}, {size}";
|
||||
"lng_settings_images_cached#one" = "{count} afbeelding, {size}";
|
||||
"lng_settings_images_cached#other" = "{count} afbeeldingen, {size}";
|
||||
"lng_settings_audios_cached#one" = "{count} spraakbericht, {size}";
|
||||
"lng_settings_audios_cached#other" = "{count} spraakberichten, {size}";
|
||||
"lng_local_storage_clear" = "Alles wissen";
|
||||
"lng_local_storage_clearing" = "Wissen...";
|
||||
"lng_local_storage_cleared" = "Gewist!";
|
||||
"lng_local_storage_clear_failed" = "Wissen mislukt";
|
||||
|
||||
"lng_settings_section_advanced_settings" = "Geavanceerde instellingen";
|
||||
"lng_settings_enable_night_theme" = "Nachtmodus inschakelen";
|
||||
"lng_settings_disable_night_theme" = "Nachtmodus uitschakelen";
|
||||
|
||||
"lng_passcode_remove_button" = "Verwijder";
|
||||
|
||||
@@ -348,8 +388,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_passcode_autolock" = "Automatisch vergrendelen";
|
||||
"lng_passcode_autolock_away" = "Vergrendelen indien langer afwezig dan:";
|
||||
"lng_passcode_autolock_inactive" = "Vergrendelen indien langer inactief dan:";
|
||||
"lng_passcode_autolock_minutes" = "{count:_not_used_|# minuut|# minuten}";
|
||||
"lng_passcode_autolock_hours" = "{count:_not_used_|# uur|# uur}";
|
||||
"lng_passcode_autolock_minutes#one" = "{count} minuut";
|
||||
"lng_passcode_autolock_minutes#other" = "{count} minuten";
|
||||
"lng_passcode_autolock_hours#one" = "{count} uur";
|
||||
"lng_passcode_autolock_hours#other" = "{count} uur";
|
||||
"lng_passcode_enter_old" = "Toegangscode invoeren";
|
||||
"lng_passcode_enter_first" = "Toegangscode invoeren";
|
||||
"lng_passcode_enter_new" = "Nieuwe toegangscode invoeren";
|
||||
@@ -402,7 +444,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_connection_try_ipv6" = "Verbinden via IPV6";
|
||||
"lng_connection_host_ph" = "Hostnaam";
|
||||
"lng_connection_port_ph" = "Poort";
|
||||
"lng_connection_user_ph" = "Gebruikersnaam";
|
||||
"lng_connection_user_ph" = "Gebruiker";
|
||||
"lng_connection_password_ph" = "Wachtwoord";
|
||||
"lng_connection_save" = "Opslaan";
|
||||
|
||||
@@ -455,32 +497,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_privacy_lastseen_title" = "Laatst gezien";
|
||||
"lng_edit_privacy_lastseen_description" = "Je kunt instellen wie je \"laatst gezien\" mag zien:";
|
||||
"lng_edit_privacy_lastseen_warning" = "Let op: van mensen waarmee je je laatst gezien tijd niet deelt is deze voor jou ook niet zichtbaar. In plaats daarvan krijg je tijden bij benadering te zien.";
|
||||
"lng_edit_privacy_lastseen_always" = "Altijd delen met{count:| # gebruiker| # gebruikers}";
|
||||
"lng_edit_privacy_lastseen_never" = "Nooit delen met{count:| # gebruiker| # gebruikers}";
|
||||
"lng_edit_privacy_lastseen_always_empty" = "Altijd delen met";
|
||||
"lng_edit_privacy_lastseen_always#one" = "Altijd delen met {count} gebruiker";
|
||||
"lng_edit_privacy_lastseen_always#other" = "Altijd delen met {count} gebruikers";
|
||||
"lng_edit_privacy_lastseen_never_empty" = "Nooit delen met";
|
||||
"lng_edit_privacy_lastseen_never#one" = "Nooit delen met {count} gebruiker";
|
||||
"lng_edit_privacy_lastseen_never#other" = "Nooit delen met {count} gebruikers";
|
||||
"lng_edit_privacy_lastseen_exceptions" = "Deze instelling overschrijft de bovenstaande.";
|
||||
"lng_edit_privacy_lastseen_always_title" = "Altijd delen met";
|
||||
"lng_edit_privacy_lastseen_never_title" = "Nooit delen met";
|
||||
|
||||
"lng_edit_privacy_groups_title" = "Wie kan mij toevoegen?";
|
||||
"lng_edit_privacy_groups_description" = "Je kunt nauwkeurig bepalen wie je aan groepen en kanalen mag toevoegen.";
|
||||
"lng_edit_privacy_groups_always" = "Altijd toestaan{count:| # gebruiker| # gebruikers}";
|
||||
"lng_edit_privacy_groups_never" = "Nooit toestaan{count:| # gebruiker| # gebruikers}";
|
||||
"lng_edit_privacy_groups_always_empty" = "Altijd toestaan";
|
||||
"lng_edit_privacy_groups_always#one" = "Altijd toestaan {count} gebruiker";
|
||||
"lng_edit_privacy_groups_always#other" = "Altijd toestaan {count} gebruikers";
|
||||
"lng_edit_privacy_groups_never_empty" = "Nooit toestaan";
|
||||
"lng_edit_privacy_groups_never#one" = "Nooit toestaan {count} gebruiker";
|
||||
"lng_edit_privacy_groups_never#other" = "Nooit toestaan {count} gebruikers";
|
||||
"lng_edit_privacy_groups_exceptions" = "Deze gebruikers altijd toestaan of verbieden je aan groepen en kanalen toe te voegen.";
|
||||
"lng_edit_privacy_groups_always_title" = "Altijd toestaan";
|
||||
"lng_edit_privacy_groups_never_title" = "Nooit toestaan";
|
||||
|
||||
"lng_edit_privacy_calls_title" = "Oproepen";
|
||||
"lng_edit_privacy_calls_description" = "Je kunt bepalen wie jou mag bellen:";
|
||||
"lng_edit_privacy_calls_always" = "Altijd toestaan{count:| # gebruiker| # gebruikers}";
|
||||
"lng_edit_privacy_calls_never" = "Nooit toestaan{count:| # gebruiker| # gebruikers}";
|
||||
"lng_edit_privacy_calls_always_empty" = "Altijd toestaan";
|
||||
"lng_edit_privacy_calls_always#one" = "Altijd toestaan {count} gebruiker";
|
||||
"lng_edit_privacy_calls_always#other" = "Altijd toestaan {count} gebruikers";
|
||||
"lng_edit_privacy_calls_never_empty" = "Nooit toestaan";
|
||||
"lng_edit_privacy_calls_never#one" = "Nooit toestaan {count} gebruiker";
|
||||
"lng_edit_privacy_calls_never#other" = "Nooit toestaan {count} gebruikers";
|
||||
"lng_edit_privacy_calls_exceptions" = "Deze gebruikers altijd toestaan of verbieden om je te bellen.";
|
||||
"lng_edit_privacy_calls_always_title" = "Altijd toestaan";
|
||||
"lng_edit_privacy_calls_never_title" = "Nooit toestaan";
|
||||
|
||||
"lng_self_destruct_title" = "Account verwijderen";
|
||||
"lng_self_destruct_description" = "Als je binnen deze periode niet minimaal één keer ingelogd bent geweest zal je account worden verwijderd, inclusief alle data.";
|
||||
"lng_self_destruct_months" = "{count:_not_used_|# maand|# maanden}";
|
||||
"lng_self_destruct_years" = "{count:_not_used_|# jaar|# jaar}";
|
||||
"lng_self_destruct_months#one" = "{count} maand";
|
||||
"lng_self_destruct_months#other" = "{count} maanden";
|
||||
"lng_self_destruct_years#one" = "{count} jaar";
|
||||
"lng_self_destruct_years#other" = "{count} jaar";
|
||||
|
||||
"lng_change_phone_title" = "Telefoonnummer wijzigen";
|
||||
"lng_change_phone_description" = "Je kan je telefoonnummer hier wijzigen.\nAl je clouddata — berichten, bestanden, \ngroepen, contacten, etc. zullen worden \ngekopieërd naar je nieuwe nummer.\n\n[b]Let op[/b]: al je Telegram-contacten krijgen \nje [b]nieuwe nummer[/b] in hun adresboek, ervan \nuitgaande dat ze je oude nummer hadden en \nje hen niet had geblokkeerd in Telegram.";
|
||||
@@ -506,15 +562,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_link_section" = "Uitnodigingslink";
|
||||
"lng_profile_create_public_link" = "Publieke link maken";
|
||||
"lng_profile_edit_public_link" = "Publieke link wijzigen";
|
||||
"lng_profile_search_members" = "Zoek leden";
|
||||
"lng_profile_manage_admins" = "Beheerders wijzigen";
|
||||
"lng_profile_manage_blocklist" = "Geblokkeerde gebruikers";
|
||||
"lng_profile_common_groups" = "gedeelde {count:_not_used_|# groep|# groepen}";
|
||||
"lng_profile_manage_blocklist" = "Beheer geblokkeerde gebruikers";
|
||||
"lng_profile_manage_restrictedlist" = "Beheer beperkte gebruikers";
|
||||
"lng_profile_recent_actions" = "Recente gebeurtenissen";
|
||||
"lng_profile_common_groups#one" = "{count} gedeelde groep";
|
||||
"lng_profile_common_groups#other" = "{count} gedeelde groepen";
|
||||
"lng_profile_common_groups_section" = "Gedeelde groepen";
|
||||
"lng_profile_participants_section" = "Leden";
|
||||
"lng_profile_info_section" = "Informatie";
|
||||
"lng_profile_mobile_number" = "Mobiel:";
|
||||
"lng_profile_username" = "Gebruikersnaam:";
|
||||
"lng_profile_link" = "Link:";
|
||||
"lng_profile_bio" = "Bio:";
|
||||
"lng_profile_add_contact" = "Contact toevoegen";
|
||||
"lng_profile_edit_contact" = "Wijzig";
|
||||
"lng_profile_enable_notifications" = "Meldingen";
|
||||
@@ -542,23 +603,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_delete_and_exit" = "Verlaat";
|
||||
"lng_profile_kick" = "Verwijder";
|
||||
"lng_profile_admin" = "beheerder";
|
||||
"lng_profile_edit_permissions" = "Wijzig";
|
||||
"lng_profile_sure_kick" = "{user} uit de groep verwijderen?";
|
||||
"lng_profile_sure_kick_channel" = "{user} uit het kanaal verwijderen?";
|
||||
"lng_profile_sure_kick_admin" = "{user} ontslaan als beheerder?";
|
||||
"lng_profile_loading" = "Laden...";
|
||||
"lng_profile_shared_media" = "Gedeelde media";
|
||||
"lng_profile_no_media" = "Geen media in deze chat.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# foto|# foto's}";
|
||||
"lng_profile_photos#one" = "{count} foto";
|
||||
"lng_profile_photos#other" = "{count} foto's";
|
||||
"lng_profile_photos_header" = "Foto's";
|
||||
"lng_profile_videos" = "{count:_not_used_|# video|# video's}";
|
||||
"lng_profile_videos#one" = "{count} video";
|
||||
"lng_profile_videos#other" = "{count} video's";
|
||||
"lng_profile_videos_header" = "Video's";
|
||||
"lng_profile_songs" = "{count:_not_used_|# audiobestand|# audiobestanden}";
|
||||
"lng_profile_songs#one" = "{count} audiobestand";
|
||||
"lng_profile_songs#other" = "{count} audiobestanden";
|
||||
"lng_profile_songs_header" = "Audiobestanden";
|
||||
"lng_profile_files" = "{count:_not_used_|# bestand|# bestanden}";
|
||||
"lng_profile_files#one" = "{count} bestand";
|
||||
"lng_profile_files#other" = "{count} bestanden";
|
||||
"lng_profile_files_header" = "Bestanden";
|
||||
"lng_profile_audios" = "{count:_not_used_|# spraakbericht|# spraakberichten}";
|
||||
"lng_profile_audios#one" = "{count} spraakbericht";
|
||||
"lng_profile_audios#other" = "{count} spraakberichten";
|
||||
"lng_profile_audios_header" = "Spraakberichten";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# gedeelde link|# gedeelde links}";
|
||||
"lng_profile_shared_links#one" = "{count} gedeelde link";
|
||||
"lng_profile_shared_links#other" = "{count} gedeelde links";
|
||||
"lng_profile_shared_links_header" = "Gedeelde links";
|
||||
"lng_profile_copy_phone" = "Telefoonnummer kopiëren";
|
||||
"lng_profile_copy_fullname" = "Naam kopiëren";
|
||||
@@ -578,16 +646,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_report_button" = "Melden";
|
||||
"lng_report_thanks" = "Bedankt! Je melding zal zo spoedig mogen worden gecontroleerd.";
|
||||
|
||||
"lng_channel_add_admins" = "Beheerder toevoegen";
|
||||
"lng_channel_add_members" = "Leden toevoegen";
|
||||
"lng_channel_add_banned" = "Blokkeer gebruiker";
|
||||
"lng_channel_add_restricted" = "Beperk gebruiker";
|
||||
"lng_channel_members" = "Leden";
|
||||
"lng_channel_only_last_shown" = "De laatste {count:_not_used_|# lid|# leden} worden hier weergegeven";
|
||||
"lng_channel_only_last_shown#one" = "Het laatste {count} lid wordt hier weergegeven";
|
||||
"lng_channel_only_last_shown#other" = "De laatste {count} leden worden hier weergegeven";
|
||||
"lng_channel_admins" = "Beheerders";
|
||||
"lng_channel_add_admin" = "Beheerder toevoegen";
|
||||
"lng_channel_admin_sure" = "{user} aan beheerders toevoegen?";
|
||||
"lng_channel_admins_too_much" = "Je hebt het maximum aantal beheerders voor deze groep bereikt, Verwijder er eerst één.";
|
||||
"lng_channel_admin_status_creator" = "Maker";
|
||||
"lng_channel_admin_status_promoted_by" = "Gepromoveerd door {user}";
|
||||
"lng_channel_admin_status_not_admin" = "Geen beheerder";
|
||||
|
||||
"lng_group_blocked_list_about" = "Geblokkeerde gebruikers worden verwijderd uit de groep, terugkeren kan alleen op uitnodiging van een beheerder.\nUitnodigingslinks werken niet voor hen.";
|
||||
"lng_group_blocked_list_about" = "Geblokkeerde gebruikers kunnen alleen worden uitgenodigd door beheerders. \nUitnodigingslinks werken niet voor hen.";
|
||||
|
||||
"lng_chat_all_members_admins" = "Iedereen is beheerder";
|
||||
"lng_chat_about_all_admins" = "Iedereen mag leden toevoegen en de groepsfoto of naam wijzigen.";
|
||||
@@ -595,7 +667,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_participant_filter" = "Zoeken";
|
||||
"lng_participant_invite" = "Uitnodigen";
|
||||
"lng_participant_invite_sorry" = "De eerste {count:_not_used|# lid|# leden} kun je persoonlijk uitnodigen.\n\nVanaf nu kunnen mensen lid worden via de uitnodigingslink.";
|
||||
"lng_participant_invite_sorry#one" = "Het {count}e lid kun je persoonlijk uitnodigen.\n\nVanaf nu kunnen mensen lid worden via de uitnodigingslink.";
|
||||
"lng_participant_invite_sorry#other" = "De eerste {count} leden kun je persoonlijk uitnodigen.\n\nVanaf nu kunnen mensen lid worden via de uitnodigingslink.";
|
||||
"lng_create_group_back" = "Vorige";
|
||||
"lng_create_group_next" = "Volgende";
|
||||
"lng_create_group_create" = "Maak";
|
||||
@@ -618,8 +691,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_create_channel_link_available" = "Deze naam is beschikbaar.";
|
||||
"lng_create_channel_link_copied" = "Link gekopieerd naar klembord";
|
||||
|
||||
"lng_create_group_crop" = "Kies een vierkant voor de groepsfoto";
|
||||
"lng_create_channel_crop" = "Kies een vierkant voor de kanaalfoto";
|
||||
"lng_create_group_crop" = "Kies een gebied voor de groepsfoto";
|
||||
"lng_create_channel_crop" = "Kies een gebied voor de kanaalfoto";
|
||||
|
||||
"lng_failed_add_participant" = "Gebruiker toevoegen mislukt. Probeer het later.";
|
||||
"lng_failed_add_not_mutual" = "Iemand die de groep verlaat kan alleen door een wederzijds contact worden toegevoegd (opgeslagen nummers)";
|
||||
@@ -637,8 +710,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_message_empty" = "Leeg bericht";
|
||||
"lng_message_unsupported" = "Dit bericht wordt niet ondersteund door jouw versie van Telegram Desktop. Werk bij naar de laatste versie via de instellingen of installeer vanuit {link}";
|
||||
|
||||
"lng_duration_seconds" = "{count:_not_used_|# seconde|# seconden}";
|
||||
"lng_duration_minutes_seconds" = "{count_minutes:# min|# min|# min} {count_seconds:# sec|# sec|# sec}";
|
||||
"lng_duration_seconds#one" = "{count} seconde";
|
||||
"lng_duration_seconds#other" = "{count} seconden";
|
||||
"lng_duration_minsec_minutes#one" = "{count} min";
|
||||
"lng_duration_minsec_minutes#other" = "{count} min";
|
||||
"lng_duration_minsec_seconds#one" = "{count} sec";
|
||||
"lng_duration_minsec_seconds#other" = "{count} sec";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_add_user" = "{from} heeft {user} toegevoegd";
|
||||
"lng_action_add_users_many" = "{from} heeft {users} toegevoegd";
|
||||
@@ -676,18 +754,33 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_sticker" = "een sticker";
|
||||
"lng_action_pinned_media_emoji_sticker" = "een {emoji} sticker";
|
||||
"lng_action_pinned_media_game" = "het spel «{game}»";
|
||||
"lng_action_game_score" = "{from} heeft met {game} {count:# punten|# punt|# punten} behaald";
|
||||
"lng_action_game_you_scored" = "Je hebt met {game} {count:# punten|# punt|# punten} behaald";
|
||||
"lng_action_game_score_no_game" = "{from} heeft {count:# punten|# punt|# punten} behaald";
|
||||
"lng_action_game_you_scored_no_game" = "Je hebt {count:# punten|# punt|# punten} behaald";
|
||||
"lng_action_game_score#one" = "{from} heeft met {game} {count} punt behaald";
|
||||
"lng_action_game_score#other" = "{from} heeft met {game} {count} punten behaald";
|
||||
"lng_action_game_you_scored#one" = "Je hebt met {game} {count} punt behaald";
|
||||
"lng_action_game_you_scored#other" = "Je hebt met {game} {count} punten behaald";
|
||||
"lng_action_game_score_no_game#one" = "{from} heeft {count} punt behaald";
|
||||
"lng_action_game_score_no_game#other" = "{from} heeft {count} punten behaald";
|
||||
"lng_action_game_you_scored_no_game#one" = "Je hebt {count} punt behaald";
|
||||
"lng_action_game_you_scored_no_game#other" = "Je hebt {count} punten behaald";
|
||||
"lng_action_payment_done" = "Je hebt een bedrag van {amount} overgemaakt naar {user}";
|
||||
"lng_action_payment_done_for" = "Je hebt een bedrag van {amount} overgemaakt naar {user} voor {invoice}";
|
||||
"lng_action_took_screenshot" = "{from} heeft een schermafdruk gemaakt!";
|
||||
"lng_action_you_took_screenshot" = "Schermafdruk gemaakt!";
|
||||
|
||||
"lng_profile_migrate_reached" = "{count:_not_used_|# lid |# leden} limiet bereikt";
|
||||
"lng_ttl_photo_received" = "{from} heeft een zelfvernietigende foto gestuurd, bekijk deze op je mobiel.";
|
||||
"lng_ttl_photo_sent" = "Je hebt een zelfvernietigende foto gestuurd";
|
||||
"lng_ttl_photo_expired" = "Foto is verlopen";
|
||||
"lng_ttl_video_received" = "{from} heeft een zelfvernietigende video gestuurd, bekijk deze op je mobiel.";
|
||||
"lng_ttl_video_sent" = "Je hebt een zelfvernietigende video gestuurd";
|
||||
"lng_ttl_video_expired" = "Video is verlopen";
|
||||
|
||||
"lng_profile_migrate_reached#one" = "{count} ledenlimiet bereikt";
|
||||
"lng_profile_migrate_reached#other" = "{count} ledenlimiet bereikt";
|
||||
"lng_profile_migrate_body" = "Wil je een hogere limiet? Waardeer op naar een supergroep.";
|
||||
"lng_profile_migrate_learn_more" = "Meer informatie »";
|
||||
"lng_profile_migrate_about" = "Wil je extra functies en een hogere limiet? Waardeer op naar een supergroep:";
|
||||
"lng_profile_migrate_feature1" = "— Supergroepen hebben tot {count:_not_used_|# lid|# leden}";
|
||||
"lng_profile_migrate_feature1#one" = "— De ledenlimiet is {count} lid";
|
||||
"lng_profile_migrate_feature1#other" = "— De ledenlimiet is {count} leden";
|
||||
"lng_profile_migrate_feature2" = "— Nieuwe leden zien de hele geschiedenis";
|
||||
"lng_profile_migrate_feature3" = "— Beheerder wist berichten voor iedereen";
|
||||
"lng_profile_migrate_feature4" = "— Meldingen staan standaard uit";
|
||||
@@ -702,7 +795,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_convert_feature4" = "— Maker kan een publieke groepslink instellen";
|
||||
"lng_profile_convert_warning" = "{bold_start}Let op:{bold_end} Je kunt dit niet ongedaan maken.";
|
||||
"lng_profile_convert_confirm" = "Opwaarderen";
|
||||
"lng_profile_add_more_after_upgrade" = "Waardeer op naar een supergroep om tot {count:_not_used_|# lid|# leden} toe te voegen";
|
||||
"lng_profile_add_more_after_upgrade#one" = "Waardeer op naar een supergroep om tot {count} lid toe te voegen";
|
||||
"lng_profile_add_more_after_upgrade#other" = "Waardeer op naar een supergroep om tot {count} leden toe te voegen";
|
||||
|
||||
"lng_channel_not_accessible" = "Sorry, dit kanaal is privé.";
|
||||
"lng_group_not_accessible" = "Sorry, deze groep is niet beschikbaar.";
|
||||
@@ -717,19 +811,21 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_group_invite_want_join_channel" = "Wil je lid worden van het kanaal \"{title}\"?";
|
||||
"lng_group_invite_join" = "Lid worden";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# lid|# leden}, waaronder:";
|
||||
"lng_group_invite_members#one" = "{count} lid, waaronder:";
|
||||
"lng_group_invite_members#other" = "{count} leden, waaronder:";
|
||||
|
||||
"lng_group_invite_link" = "Uitnodigingslink:";
|
||||
"lng_group_invite_create" = "Uitnodigingslink maken";
|
||||
"lng_group_invite_about" = "Gebruikers kunnen lid worden\nvan je groep via deze link.";
|
||||
"lng_group_invite_create_new" = "Intrekken";
|
||||
"lng_group_invite_about_new" = "Je uitnodigingslink zal inactief worden een nieuwe link zal worden gegenereerd.";
|
||||
"lng_group_invite_create_new" = "Uitnodigingslink intrekken";
|
||||
"lng_group_invite_about_new" = "Je uitnodigingslink zal inactief worden, een nieuwe link zal worden gegenereerd.";
|
||||
"lng_group_invite_copied" = "Link gekopieerd naar klembord.";
|
||||
"lng_group_invite_no_room" = "De ledenlimiet van de groep is bereikt.";
|
||||
|
||||
"lng_channel_public_link_copied" = "Link gekopieerd naar klembord";
|
||||
|
||||
"lng_forwarded" = "Doorgestuurd van {user}";
|
||||
"lng_forwarded_date" = "Origineel: {date}";
|
||||
"lng_forwarded_channel" = "Doorgestuurd van {channel}";
|
||||
"lng_forwarded_via" = "Doorgestuurd van {user} via {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Doorgestuurd van {channel} via {inline_bot}";
|
||||
@@ -809,7 +905,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_stickers_you_have" = "Beheer en sorteer stickerbundels";
|
||||
"lng_stickers_featured" = "Populaire stickers";
|
||||
"lng_stickers_return" = "Ongedaan maken";
|
||||
"lng_stickers_count" = "{count:Laden..|# sticker|# stickers}";
|
||||
"lng_stickers_count#one" = "{count} sticker";
|
||||
"lng_stickers_count#other" = "{count} stickers";
|
||||
"lng_stickers_masks_pack" = "Dit een set met maskers. Je kunt ze gebruiken als je een foto bewerkt in onze mobiele apps.";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
@@ -822,7 +919,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_in_dlg_sticker" = "Sticker";
|
||||
"lng_in_dlg_sticker_emoji" = "{emoji} Sticker";
|
||||
|
||||
"lng_ban_user" = "Blacklist gebruiker";
|
||||
"lng_ban_user" = "Blokkeer gebruiker";
|
||||
"lng_delete_all_from" = "Verwijder alles van gebruiker";
|
||||
"lng_report_spam" = "Spam melden";
|
||||
"lng_report_spam_hide" = "Verbergen";
|
||||
@@ -839,6 +936,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_cant_invite_banned" = "Alleen beheerders kunnen deze gebruiker toevoegen.";
|
||||
"lng_cant_invite_privacy" = "Je kunt deze gebruiker niet toevoegen aan groepen door zijn/haar privacyinstellingen.";
|
||||
"lng_cant_invite_privacy_channel" = "Je kunt deze gebruiker niet toevoegen aan kanalen door zijn/haar privacyinstellingen.";
|
||||
"lng_cant_delete_group#one" = "Het is momenteel niet mogelijk om via de app groepen te verwijderen met meer dan {count} lid. Neem contact op met de ondersteuning van Telegram om deze groep te verwijderen.";
|
||||
"lng_cant_delete_group#other" = "Het is momenteel niet mogelijk om via de app groepen te verwijderen met meer dan {count} leden. Neem contact op met de ondersteuning van Telegram om deze groep te verwijderen.";
|
||||
"lng_cant_delete_channel#one" = "Het is momenteel niet mogelijk om via de app kanalen te verwijderen met meer dan {count} lid. Neem contact op met de ondersteuning van Telegram om dit kanaal te verwijderen.";
|
||||
"lng_cant_delete_channel#other" = "Het is momenteel niet mogelijk om via de app kanalen te verwijderen met meer dan {count} leden. Neem contact op met de ondersteuning van Telegram om dit kanaal te verwijderen.";
|
||||
"lng_cant_do_this" = "Deze actie is niet beschikbaar.";
|
||||
|
||||
"lng_send_button" = "Stuur";
|
||||
@@ -884,11 +985,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_typing" = "aan het typen";
|
||||
"lng_user_typing" = "{user} is aan het typen";
|
||||
"lng_users_typing" = "{user} en {second_user} zijn aan het typen";
|
||||
"lng_many_typing" = "{count:_not_used_|# is|# zijn} aan het typen";
|
||||
"lng_many_typing#one" = "{count} is aan het typen";
|
||||
"lng_many_typing#other" = "{count} zijn aan het typen";
|
||||
"lng_playing_game" = "speelt een spel";
|
||||
"lng_user_playing_game" = "{user} speelt een spel";
|
||||
"lng_users_playing_game" = "{user} en {second_user} spelen een spel";
|
||||
"lng_many_playing_game" = "{count:_not_used_|# is|# zijn} een spel aan het spelen";
|
||||
"lng_many_playing_game#one" = "{count} speelt een spel";
|
||||
"lng_many_playing_game#other" = "{count} spelen een spel";
|
||||
"lng_send_action_record_video" = "video opnemen";
|
||||
"lng_user_action_record_video" = "{user} neemt video op";
|
||||
"lng_send_action_upload_video" = "video versturen";
|
||||
@@ -909,7 +1012,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_geo_location" = "{user} kiest een locatie";
|
||||
"lng_send_action_choose_contact" = "contact kiezen";
|
||||
"lng_user_action_choose_contact" = "{user} kiest een contact";
|
||||
"lng_unread_bar" = "{count:_not_used_|# ongelezen bericht|# ongelezen berichten}";
|
||||
"lng_unread_bar#one" = "{count} ongelezen bericht";
|
||||
"lng_unread_bar#other" = "{count} ongelezen berichten";
|
||||
|
||||
"lng_maps_point" = "Locatie";
|
||||
"lng_save_photo" = "Afbeelding opslaan";
|
||||
@@ -932,7 +1036,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_from_top" = "Losmaken";
|
||||
|
||||
"lng_context_promote_admin" = "Beheerder maken";
|
||||
"lng_context_remove_admin" = "Ontslaan als beheerder";
|
||||
"lng_context_edit_permissions" = "Machtigingen aanpassen";
|
||||
"lng_context_restrict_user" = "Beperk gebruiker";
|
||||
"lng_context_remove_from_group" = "Uit de groep verwijderen";
|
||||
|
||||
"lng_context_copy_link" = "Link kopiëren";
|
||||
@@ -970,31 +1075,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_msg" = "Bericht losmaken";
|
||||
"lng_context_cancel_upload" = "Upload annuleren";
|
||||
"lng_context_copy_selected" = "Tekstselectie kopiëren";
|
||||
"lng_context_copy_selected_items" = "Selectie als tekst kopiëren";
|
||||
"lng_context_forward_selected" = "Selectie doorsturen";
|
||||
"lng_context_delete_selected" = "Selectie verwijderen";
|
||||
"lng_context_clear_selection" = "Selectie wissen";
|
||||
"lng_really_send_image" = "Wil je deze afbeeldingen versturen?";
|
||||
"lng_really_send_file" = "Wil je dit bestand versturen?";
|
||||
"lng_really_share_contact" = "Wil je dit contact delen?";
|
||||
"lng_send_images_compress" = "{count:_not_used_|afbeelding|afbeeldingen} comprimeren";
|
||||
"lng_send_images_compress#one" = "Afbeelding comprimeren";
|
||||
"lng_send_images_compress#other" = "Afbeeldingen comprimeren";
|
||||
"lng_send_image_non_local" = "Verzenden mislukt, {name} is een netwerk-bestand.";
|
||||
"lng_send_image_empty" = "Verzenden mislukt, {name} is leeg.";
|
||||
"lng_send_image_too_large" = "Verzenden mislukt, {name} is groter dan 1500 MB.";
|
||||
"lng_send_folder" = "Kan de map «{name}» niet versturen, kies een bestand. :(";
|
||||
"lng_send_images_selected" = "{count:_not_used_|# afbeelding|# afbeeldingen} gekozen";
|
||||
"lng_send_photos" = "{count:_not_used_|# foto|# foto's} versturen";
|
||||
"lng_send_files_selected" = "{count:_not_used_|# bestand|# bestanden} gekozen";
|
||||
"lng_send_files" = "{count:_not_used_|# bestand|# bestanden} versturen";
|
||||
"lng_send_images_selected#one" = "{count} afbeelding gekozen";
|
||||
"lng_send_images_selected#other" = "{count} afbeeldingen gekozen";
|
||||
"lng_send_photos#one" = "Stuur {count} foto";
|
||||
"lng_send_photos#other" = "Stuur {count} foto's";
|
||||
"lng_send_files_selected#one" = "{count} bestand gekozen";
|
||||
"lng_send_files_selected#other" = "{count} bestanden gekozen";
|
||||
"lng_send_files#one" = "Stuur {count} bestand";
|
||||
"lng_send_files#other" = "Stuur {count} bestanden";
|
||||
|
||||
"lng_forward_choose" = "Ontvanger kiezen...";
|
||||
"lng_forward_cant" = "Sorry, doorsturen hierheen kan niet :(";
|
||||
"lng_forward_confirm" = "Doorsturen naar {recipient}?";
|
||||
"lng_forward_share_contact" = "Contact delen met {recipient}?";
|
||||
"lng_forward_share_cant" = "Sorry, een contact hier delen kan niet :(";
|
||||
"lng_forward_send_file_confirm" = " \"{name}\" naar {recipient} versturen?";
|
||||
"lng_forward_send_files_confirm" = "Gekozen bestanden naar {recipient} sturen?";
|
||||
"lng_forward_send_files_cant" = "Sorry, media sturen hierheen kan niet :(";
|
||||
"lng_forward_send" = "Stuur";
|
||||
"lng_forward_messages" = "{count:_not_used_|Doorgestuurd bericht|# doorgestuurde berichten}";
|
||||
"lng_forwarding_from" = "{user} en {count:_not_used_|# andere|# anderen}";
|
||||
"lng_forward_messages#one" = "bijlage: {count} bericht";
|
||||
"lng_forward_messages#other" = "bijlage: {count} berichten";
|
||||
"lng_forwarding_from#one" = "{user} en {count} andere";
|
||||
"lng_forwarding_from#other" = "{user} en {count} anderen";
|
||||
"lng_forwarding_from_two" = "{user} en {second_user}";
|
||||
"lng_inline_switch_choose" = "Kies chat...";
|
||||
"lng_inline_switch_cant" = "Sorry, je kunt hier niets delen :(";
|
||||
@@ -1016,6 +1131,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_contact_title" = "Naam wijzigen";
|
||||
"lng_edit_channel_title" = "Kanaal wijzigen";
|
||||
"lng_edit_sign_messages" = "Ondertekenen";
|
||||
"lng_edit_group_who_invites" = "Wie mag leden toevoegen";
|
||||
"lng_edit_group_invites_everybody" = "Alle leden";
|
||||
"lng_edit_group_invites_only_admins" = "Beheerders";
|
||||
"lng_edit_group" = "Groep wijzigen";
|
||||
"lng_edit_self_title" = "Je naam wijzigen";
|
||||
"lng_confirm_contact_data" = "Nieuw contact";
|
||||
@@ -1040,15 +1158,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_selected_clear" = "Annuleren";
|
||||
"lng_selected_delete" = "Verwijder";
|
||||
"lng_selected_forward" = "Doorsturen";
|
||||
"lng_selected_count" = "{count:_not_used_|# bericht|# berichten}";
|
||||
"lng_selected_count#one" = "{count} bericht";
|
||||
"lng_selected_count#other" = "{count} berichten";
|
||||
"lng_selected_cancel_sure_this" = "Upload annuleren?";
|
||||
"lng_selected_upload_stop" = "Stoppen";
|
||||
"lng_selected_delete_sure_this" = "Wil je dit bericht verwijderen?";
|
||||
"lng_selected_delete_sure" = "Wil je {count:_not_used_|# bericht|# berichten} verwijderen?";
|
||||
"lng_selected_delete_sure#one" = "{count} bericht verwijderen?";
|
||||
"lng_selected_delete_sure#other" = "{count} berichten verwijderen?";
|
||||
"lng_delete_photo_sure" = "Wil je deze foto verwijderen?";
|
||||
"lng_delete_for_everyone_hint" = "Hiermee verwijder je {count:_not_used_|dit|deze} voor iedereen in de chat.";
|
||||
"lng_delete_for_me_chat_hint" = "Hiermee verwijder je {count:_not_used_|dit|deze} alleen voor jezelf, niet voor andere leden.";
|
||||
"lng_delete_for_me_hint" = "Hiermee verwijder je {count:_not_used_|dit|deze} alleen voor jezelf.";
|
||||
"lng_delete_for_everyone_hint#one" = "Hiermee verwijder je dit voor iedereen in de chat.";
|
||||
"lng_delete_for_everyone_hint#other" = "Hiermee verwijder je deze voor iedereen in de chat.";
|
||||
"lng_delete_for_me_chat_hint#one" = "Hiermee verwijder je dit alleen voor jezelf, niet voor andere leden.";
|
||||
"lng_delete_for_me_chat_hint#other" = "Hiermee verwijder je deze alleen voor jezelf, niet voor andere leden.";
|
||||
"lng_delete_for_me_hint#one" = "Hiermee verwijder je dit alleen voor jezelf.";
|
||||
"lng_delete_for_me_hint#other" = "Hiermee verwijder je deze alleen voor jezelf.";
|
||||
"lng_delete_for_everyone_check" = "Verwijder voor iedereen";
|
||||
"lng_delete_for_other_check" = "Verwijder voor {user}";
|
||||
"lng_box_delete" = "Verwijder";
|
||||
@@ -1060,7 +1183,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_about_text_3" = "Bezoek de {faq_open}Telegram FAQ{faq_close} voor meer informatie.";
|
||||
"lng_about_done" = "Gereed";
|
||||
|
||||
"lng_search_found_results" = "{count:geen berichten gevonden|# berichten gevonden|# berichten gevonden}";
|
||||
"lng_search_no_results" = "Geen berichten gevonden";
|
||||
"lng_search_found_results#one" = "{count} berichten gevonden";
|
||||
"lng_search_found_results#other" = "{count} berichten gevonden";
|
||||
"lng_search_global_results" = "Wereldwijde zoekresultaten";
|
||||
|
||||
"lng_media_save_progress" = "{ready} van {total} {mb}";
|
||||
@@ -1083,8 +1208,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_mediaview_saved" = "Het bestand is opgeslagen in je [c]Downloads[/c]-map";
|
||||
|
||||
"lng_theme_preview_title" = "Thema-voorvertoning";
|
||||
"lng_theme_preview_generating" = "Voorvertoning van thema maken...";
|
||||
"lng_theme_preview_title" = "Thema-voorbeeld";
|
||||
"lng_theme_preview_generating" = "Voorbeeld van thema maken...";
|
||||
"lng_theme_preview_invalid" = "Thema bevat ongeldige data.";
|
||||
"lng_theme_preview_apply" = "Thema toepassen";
|
||||
|
||||
@@ -1169,11 +1294,133 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_player_message_yesterday" = "Gisteren om {time}";
|
||||
"lng_player_message_date" = "{date} om {time}";
|
||||
|
||||
"lng_rights_edit_admin" = "Beheerder wijzigen";
|
||||
"lng_rights_edit_admin_header" = "Wat mag deze beheerder?";
|
||||
"lng_rights_about_add_admins_yes" = "Deze beheerder mag nieuwe beheerders toevoegen met gelijkwaardige machtigingen (of minder) als zichzelf.";
|
||||
"lng_rights_about_add_admins_no" = "Deze beheerder mag geen beheerders toevoegen";
|
||||
"lng_rights_about_admin_cant_edit" = "Je kunt de machtigingen van deze beheerder niet wijzigen.";
|
||||
"lng_rights_user_restrictions" = "Gebruikersbeperkingen";
|
||||
"lng_rights_user_restrictions_header" = "Wat mag deze gebruiker";
|
||||
|
||||
"lng_rights_channel_info" = "Informatie aanpassen";
|
||||
"lng_rights_channel_post" = "Berichten plaatsen";
|
||||
"lng_rights_channel_edit" = "Berichten van anderen wijzigen";
|
||||
"lng_rights_channel_delete" = "Berichten van anderen verwijderen";
|
||||
"lng_rights_group_info" = "Informatie aanpassen";
|
||||
"lng_rights_group_ban" = "Leden blokkeren";
|
||||
"lng_rights_group_invite_link" = "Uitnodigen via link";
|
||||
"lng_rights_group_invite" = "Leden toevoegen";
|
||||
"lng_rights_group_pin" = "Berichten vastzetten";
|
||||
"lng_rights_group_delete" = "Berichten verwijderen";
|
||||
"lng_rights_add_admins" = "Beheerders toevoegen";
|
||||
"lng_rights_chat_read" = "Berichten lezen";
|
||||
"lng_rights_chat_send_text" = "Berichten sturen";
|
||||
"lng_rights_chat_send_media" = "Media sturen";
|
||||
"lng_rights_chat_send_stickers" = "GIF's en stickers sturen";
|
||||
"lng_rights_chat_send_links" = "Link-voorbeeld sturen";
|
||||
"lng_rights_chat_banned_until_header" = "Beperkt tot";
|
||||
"lng_rights_chat_banned_forever" = "Voor altijd";
|
||||
"lng_rights_chat_banned_day#one" = "{count} dag";
|
||||
"lng_rights_chat_banned_day#other" = "{count} dagen";
|
||||
"lng_rights_chat_banned_week#one" = "{count} week";
|
||||
"lng_rights_chat_banned_week#other" = "{count} weken";
|
||||
"lng_rights_chat_banned_custom" = "Aangepast";
|
||||
"lng_rights_chat_banned_custom_date" = "Tot {date}";
|
||||
"lng_rights_chat_banned_block" = "Blokkeer en verwijder uit groep";
|
||||
|
||||
"lng_restricted_send_message" = "Je bent beperkt in het plaatsen van berichten door de beheerders.";
|
||||
"lng_restricted_send_media" = "Je bent beperkt in het sturen van media door de beheerders.";
|
||||
"lng_restricted_send_stickers" = "Je bent beperkt in het sturen van stickers door de beheerders.";
|
||||
"lng_restricted_send_gifs" = "Je bent beperkt in het sturen van GIF's door de beheerders.";
|
||||
"lng_restricted_send_inline" = "Je bent beperkt in het sturen van inline-content door de beheerders.";
|
||||
|
||||
"lng_restricted_list_title" = "Beperkte gebruikers";
|
||||
"lng_banned_list_title" = "Geblokkeerde gebruikers";
|
||||
|
||||
"lng_admin_log_title_all" = "Alle gebeurtenissen";
|
||||
"lng_admin_log_title_selected" = "Geselecteerde gebeurtenissen";
|
||||
"lng_admin_log_filter" = "Filteren";
|
||||
"lng_admin_log_filter_title" = "Filteren";
|
||||
"lng_admin_log_filter_all_actions" = "Alle gebeurtenissen";
|
||||
"lng_admin_log_filter_restrictions" = "Nieuwe beperkingen";
|
||||
"lng_admin_log_filter_admins_new" = "Nieuwe beheerders";
|
||||
"lng_admin_log_filter_members_new" = "Nieuwe leden";
|
||||
"lng_admin_log_filter_info_group" = "Groepsinformatie";
|
||||
"lng_admin_log_filter_info_channel" = "Kanaalinformatie";
|
||||
"lng_admin_log_filter_messages_deleted" = "Verwijderd berichten";
|
||||
"lng_admin_log_filter_messages_edited" = "Gewijzigde berichten";
|
||||
"lng_admin_log_filter_messages_pinned" = "Vastgezette berichten";
|
||||
"lng_admin_log_filter_members_removed" = "Vertrokken leden";
|
||||
"lng_admin_log_filter_all_admins" = "Alle gebruikers";
|
||||
"lng_admin_log_about" = "Wat is dit?";
|
||||
"lng_admin_log_about_text" = "Dit is een lijst met alle acties van de groepsleden en beheerders in de afgelopen 48 uur.";
|
||||
"lng_admin_log_no_results_title" = "Geen gebeurtenissen";
|
||||
"lng_admin_log_no_results_text" = "Geen recente gebeurtenissen gevonden voor je zoekopdracht.";
|
||||
"lng_admin_log_no_results_search_text" = "Geen recente gebeurtenissen voor '{query}' gevonden.";
|
||||
"lng_admin_log_no_events_title" = "Nog geen gebeurtenissen";
|
||||
"lng_admin_log_no_events_text" = "Beheerders en leden hebben\ngeen acties uitgevoerd in \nde afgelopen 48 uur.";
|
||||
|
||||
"lng_admin_log_empty_text" = "Leeg";
|
||||
"lng_admin_log_changed_title_group" = "{from} heeft de groepsnaam gewijzigd naar «{title}»";
|
||||
"lng_admin_log_changed_title_channel" = "{from} heeft de kanaalnaam gewijzigd naar «{title}»";
|
||||
"lng_admin_log_changed_description_group" = "beschrijving door {from} gewijzigd:";
|
||||
"lng_admin_log_removed_description_group" = "beschrijving door {from} verwijderd";
|
||||
"lng_admin_log_changed_description_channel" = "beschrijving door {from} gewijzigd:";
|
||||
"lng_admin_log_removed_description_channel" = "beschrijving door {from} verwijderd";
|
||||
"lng_admin_log_previous_description" = "Vorige beschrijving";
|
||||
"lng_admin_log_changed_link_group" = "link door {from} gewijzigd:";
|
||||
"lng_admin_log_removed_link_group" = "link door {from} verwijderd:";
|
||||
"lng_admin_log_changed_link_channel" = "link door {from} gewijzigd:";
|
||||
"lng_admin_log_removed_link_channel" = "link door {from} verwijderd:";
|
||||
"lng_admin_log_previous_link" = "Vorige link";
|
||||
"lng_admin_log_changed_photo_group" = "Groepsafbeelding door {from} gewijzigd";
|
||||
"lng_admin_log_changed_photo_channel" = "Kanaalfoto door {from} gewijzigd";
|
||||
"lng_admin_log_removed_photo_group" = "{from} heeft de groepsfoto verwijderd";
|
||||
"lng_admin_log_removed_photo_channel" = "{from} heeft de kanaalfoto verwijderd";
|
||||
"lng_admin_log_invites_enabled" = "uitnodigingen door {from} ingeschakeld";
|
||||
"lng_admin_log_invites_disabled" = "uitnodigingen door {from} uitgeschakeld";
|
||||
"lng_admin_log_signatures_enabled" = "ondertekenen door {from} ingeschakeld";
|
||||
"lng_admin_log_signatures_disabled" = "ondertekenen door {from} uitgeschakeld";
|
||||
"lng_admin_log_pinned_message" = "Bericht door {from} vastgezet:";
|
||||
"lng_admin_log_unpinned_message" = "Bericht door {from} losgemaakt";
|
||||
"lng_admin_log_edited_caption" = "Onderschrift door {from} gewijzigd:";
|
||||
"lng_admin_log_removed_caption" = "Onderschrift door {from} verwijderd";
|
||||
"lng_admin_log_previous_caption" = "Origineel onderschrift";
|
||||
"lng_admin_log_edited_message" = "Bericht door {from} gewijzigd";
|
||||
"lng_admin_log_previous_message" = "Origineel bericht";
|
||||
"lng_admin_log_deleted_message" = "Bericht door {from} verwijderd";
|
||||
"lng_admin_log_participant_joined" = "{from} is nu lid van de groep";
|
||||
"lng_admin_log_participant_joined_channel" = "{from} is nu lid van het kanaal";
|
||||
"lng_admin_log_participant_left" = "{from} heeft de groep verlaten";
|
||||
"lng_admin_log_participant_left_channel" = "{from} heeft het kanaal verlaten";
|
||||
"lng_admin_log_invited" = "{user} uitgenodigd";
|
||||
"lng_admin_log_banned" = "{user} geblokkeerd";
|
||||
"lng_admin_log_restricted" = "beperkingen van {user} aangepast tot {until}";
|
||||
"lng_admin_log_promoted" = "privileges van {user} aangepast";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_restricted_forever" = "Voor altijd";
|
||||
"lng_admin_log_restricted_until" = "tot {date}";
|
||||
"lng_admin_log_banned_view_messages" = "Berichten lezen";
|
||||
"lng_admin_log_banned_send_messages" = "Berichten sturen";
|
||||
"lng_admin_log_banned_send_media" = "Media sturen";
|
||||
"lng_admin_log_banned_send_stickers" = "Stickers & GIF's sturen";
|
||||
"lng_admin_log_banned_embed_links" = "Link-voorbeeld sturen";
|
||||
"lng_admin_log_admin_change_info" = "Informatie aanpassen";
|
||||
"lng_admin_log_admin_post_messages" = "Berichten plaatsen";
|
||||
"lng_admin_log_admin_edit_messages" = "Berichten wijzigen";
|
||||
"lng_admin_log_admin_delete_messages" = "Berichten verwijderen";
|
||||
"lng_admin_log_admin_ban_users" = "Leden blokkeren";
|
||||
"lng_admin_log_admin_invite_users" = "Leden toevoegen";
|
||||
"lng_admin_log_admin_invite_link" = "Uitnodigen via link";
|
||||
"lng_admin_log_admin_pin_messages" = "Berichten vastzetten";
|
||||
"lng_admin_log_admin_add_admins" = "Beheerders toevoegen";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "Info";
|
||||
"lng_profile_group_info" = "Groepsinformatie";
|
||||
"lng_profile_channel_info" = "Kanaalinformatie";
|
||||
"lng_channel_add_admins" = "Beheerder toevoegen";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_menu_update" = "Atualizar";
|
||||
"lng_menu_restart" = "Reiniciar";
|
||||
"lng_menu_back" = "Voltar";
|
||||
"lng_menu_night_mode" = "Modo noturno";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Desabilitar notificações";
|
||||
"lng_enable_notifications_from_tray" = "Habilitar notificações";
|
||||
@@ -88,7 +89,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_continue" = "Continuar";
|
||||
"lng_close" = "Fechar";
|
||||
"lng_connecting" = "Conectando...";
|
||||
"lng_reconnecting" = "Reconectar {count:agora|em # s|em # s}...";
|
||||
"lng_connecting_to_proxy" = "Conectando ao proxy...";
|
||||
"lng_connecting_settings" = "Configurações";
|
||||
"lng_reconnecting#one" = "Reconectar em {count} s...";
|
||||
"lng_reconnecting#other" = "Reconectar em {count} s...";
|
||||
"lng_reconnecting_try_now" = "Tentar agora";
|
||||
|
||||
"lng_status_service_notifications" = "notificações de serviço";
|
||||
@@ -102,8 +106,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_last_month" = "visto há um mês";
|
||||
"lng_status_invisible" = "invisível";
|
||||
"lng_status_lastseen_now" = "visto agora ";
|
||||
"lng_status_lastseen_minutes" = "visto há {count:_not_used_|# minuto|# minutos}";
|
||||
"lng_status_lastseen_hours" = "visto há {count:_not_used_|# hora|# horas} ";
|
||||
"lng_status_lastseen_minutes#one" = "visto há {count} minuto";
|
||||
"lng_status_lastseen_minutes#other" = "visto há {count} minutos";
|
||||
"lng_status_lastseen_hours#one" = "visto há {count} hora";
|
||||
"lng_status_lastseen_hours#other" = "visto há {count} horas";
|
||||
"lng_status_lastseen_today" = "visto hoje às {time}";
|
||||
"lng_status_lastseen_yesterday" = "visto ontem às {time}";
|
||||
"lng_status_lastseen_date" = "visto por último {date}";
|
||||
@@ -112,24 +118,43 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_status_connecting" = "conectando...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "grupo inacessível";
|
||||
"lng_chat_status_members" = "{count:nenhum membro|# membro|# membros}";
|
||||
"lng_chat_status_members_online" = "{count:_not_used_|# membro|# membros}, {count_online:_not_used_|# online|# online}";
|
||||
"lng_chat_status_no_members" = "nenhum membro";
|
||||
"lng_chat_status_members#one" = "{count} membro";
|
||||
"lng_chat_status_members#other" = "{count} membros";
|
||||
"lng_chat_status_online#one" = "{count} online";
|
||||
"lng_chat_status_online#other" = "{count} online";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
|
||||
"lng_channel_status" = "canal";
|
||||
"lng_group_status" = "grupo";
|
||||
|
||||
"lng_channel_members_link" = "{count:_not_used_|# membro|# membros}";
|
||||
"lng_channel_admins_link" = "{count:_not_used_|# administrador|# administradores}";
|
||||
"lng_channel_members_link#one" = "{count} membro";
|
||||
"lng_channel_members_link#other" = "{count} membros";
|
||||
"lng_channel_admins_link#one" = "{count} administrador";
|
||||
"lng_channel_admins_link#other" = "{count} administradores";
|
||||
|
||||
"lng_server_error" = "Erro interno do servidor.";
|
||||
"lng_flood_error" = "Muitas tentativas. Tente novamente mais tarde.";
|
||||
"lng_gif_error" = "Um erro ocorreu com a animação do GIF :(";
|
||||
"lng_gif_error" = "Um erro ocorreu ao ler a animação do GIF :(";
|
||||
"lng_edit_error" = "Você não pode editar essa mensagem";
|
||||
"lng_join_channel_error" = "Desculpe, você já entrou em muitos canais e supergrupos. Por favor, saia de alguns antes de entrar.";
|
||||
"lng_error_phone_flood" = "Desculpe, você apagou e recriou sua conta muitas vezes recentemente. Aguarde alguns dias antes de tentar novamente.";
|
||||
"lng_error_start_minimized_passcoded" = "Você tem uma senha de bloqueio, então o aplicativo não pode iniciar minimizado. O app precisa de sua senha para iniciar.";
|
||||
"lng_error_pinned_max" = "Você não pode fixar mais de {count:_not_used_|# conversa|# conversas} no topo.";
|
||||
"lng_error_pinned_max#one" = "Você não pode fixar mais de {count} conversa no topo.";
|
||||
"lng_error_pinned_max#other" = "Você não pode fixar mais de {count} conversas no topo.";
|
||||
"lng_error_public_groups_denied" = "Infelizmente, você foi banido de participar em grupos públicos.\n{more_info}";
|
||||
"lng_error_cant_edit_admin" = "Desculpe, você não pode editar permissões para esse admin.";
|
||||
"lng_error_cant_add_member" = "Você não pode adicionar bots à esse grupo. Peça para um admin fazer isso.";
|
||||
"lng_error_cant_add_bot" = "Esse bot não pode ser adicionado à grupos";
|
||||
"lng_error_cant_add_admin_invite" = "Você não pode adicionar esse usuário como admin porque ele não é um membro do grupo e você não possui permissão para convidá-lo.";
|
||||
"lng_error_cant_add_admin_unban" = "Você não pode adicionar esse usuário como admin porque ele está na lista negra e você não pode desbaní-lo.";
|
||||
"lng_error_cant_ban_admin" = "Você não pode banir esse usuário porque ele é um admin do grupo e você não possui permissão para rebaixá-lo.";
|
||||
"lng_sure_add_admin_invite" = "Esse usuário não é um membro do grupo. Adicioná-lo ao grupo e promover à administrador?";
|
||||
"lng_sure_add_admin_unban" = "Esse usuário está restrito ou banido do grupo. Você tem certeza que quer o desbanir e o promovê-lo?";
|
||||
"lng_sure_ban_admin" = "Esse usuário é um administrador do grupo. Você tem certeza que deseja restringi-lo?";
|
||||
"lng_sure_ban_user_group" = "Banir {user} do grupo?";
|
||||
"lng_sure_enable_socks" = "Você tem certeza que deseja habilitar esse proxy?\n\nServidor: {server}\nPorta: {port}\n\nVocê pode alterar seu servidor proxy depois em Configurações (Tipo de Conexão).";
|
||||
"lng_sure_enable" = "Habilitar";
|
||||
|
||||
"lng_edit_deleted" = "Essa mensagem foi apagada";
|
||||
"lng_edit_too_long" = "Sua mensagem está muito longa";
|
||||
@@ -198,9 +223,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_signin_sure_reset" = "Atenção!\n\nVocê perderá todos seus chats e mensagens, juntamente com quaisquer mídias e arquivos!\n\nVocê deseja apagar sua conta?";
|
||||
"lng_signin_reset" = "Apagar";
|
||||
"lng_signin_reset_wait" = "Uma vez que a conta {phone_number} está ativa e protegida por senha, nós iremos desativá-la em 1 semana, por questões de segurança. Você pode cancelar esse processo a qualquer momento.\n\nVocê poderá restaurar sua conta em:\n{when}";
|
||||
"lng_signin_reset_in_days" = "{count_days:0 dia|# dia|# dias} {count_hours:0 hora|# hora|# horas} {count_minutes:0 minuto|# minuto|# minutos}";
|
||||
"lng_signin_reset_in_hours" = "{count_hours:0 hora|# hora|# horas} {count_minutes:0 minuto|# minuto|# minutos}";
|
||||
"lng_signin_reset_in_minutes" = "{count_minutes:0 minuto|# minuto|# minutos}";
|
||||
"lng_signin_reset_days#one" = "{count} dia";
|
||||
"lng_signin_reset_days#other" = "{count} dias";
|
||||
"lng_signin_reset_hours#one" = "{count} hora";
|
||||
"lng_signin_reset_hours#other" = "{count} horas";
|
||||
"lng_signin_reset_minutes#one" = "{count} minuto";
|
||||
"lng_signin_reset_minutes#other" = "{count} minutos";
|
||||
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
|
||||
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
|
||||
"lng_signin_reset_cancelled" = "Suas tentativas recentes de restaurar essa conta foram canceladas pelo usuário ativo. Tente novamente em 7 dias.";
|
||||
|
||||
"lng_signup_title" = "Suas Informações";
|
||||
@@ -223,7 +253,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_settings_save" = "Salvar";
|
||||
"lng_settings_upload" = "Definir Foto de Perfil";
|
||||
"lng_settings_crop_profile" = "Selecione uma área para a foto do perfil";
|
||||
"lng_settings_crop_profile" = "Selecione uma área para sua foto de perfil";
|
||||
"lng_settings_uploading_photo" = "Carregando foto...";
|
||||
"lng_settings_edit" = "Editar";
|
||||
"lng_settings_drop_area_subtitle" = "para defini-la como sua foto";
|
||||
@@ -241,10 +271,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_username_link" = "Esse link abre um chat com você:";
|
||||
"lng_username_copied" = "Link copiado para área de transferência.";
|
||||
|
||||
"lng_bio_title" = "Editar sua bio";
|
||||
"lng_bio_placeholder" = "Bio";
|
||||
"lng_bio_about" = "Você pode adicionar algumas linhas sobre você. Qualquer um que ver seu perfil poderá ver esse texto.";
|
||||
|
||||
"lng_settings_section_info" = "Info";
|
||||
"lng_settings_phone_number" = "Número de telefone:";
|
||||
"lng_settings_username" = "Nome de usuário:";
|
||||
"lng_settings_choose_username" = "Escolher nome de usuário";
|
||||
"lng_settings_empty_bio" = "Nenhum";
|
||||
|
||||
"lng_settings_section_notify" = "Notificações";
|
||||
"lng_settings_desktop_notify" = "Notificações na área de trabalho";
|
||||
@@ -303,7 +338,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_backgrounds_header" = "Escolha o seu novo papel de parede";
|
||||
"lng_theme_sure_keep" = "Manter esse tema de cores?";
|
||||
"lng_theme_reverting" = "Revertendo ao antigo tema em {count:_not_used_|# segundo|# segundos}.";
|
||||
"lng_theme_reverting#one" = "Revertendo ao antigo tema em {count} segundo.";
|
||||
"lng_theme_reverting#other" = "Revertendo ao antigo tema em {count} segundos.";
|
||||
"lng_theme_keep_changes" = "Manter alterações";
|
||||
"lng_theme_revert" = "Reverter";
|
||||
|
||||
@@ -329,14 +365,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_local_storage_title" = "Armazenamento local";
|
||||
"lng_settings_no_data_cached" = "Nada encontrado no cache!";
|
||||
"lng_settings_images_cached" = "{count:_not_used_|# imagem|# imagens}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|# mensagem de voz|# mensagens de voz}, {size}";
|
||||
"lng_settings_images_cached#one" = "{count} imagem, {size}";
|
||||
"lng_settings_images_cached#other" = "{count} imagens, {size}";
|
||||
"lng_settings_audios_cached#one" = "{count} mensagem de voz, {size}";
|
||||
"lng_settings_audios_cached#other" = "{count} mensagens de voz, {size}";
|
||||
"lng_local_storage_clear" = "Limpar tudo";
|
||||
"lng_local_storage_clearing" = "Limpando...";
|
||||
"lng_local_storage_cleared" = "Concluído!";
|
||||
"lng_local_storage_clear_failed" = "Limpeza falhou :(";
|
||||
|
||||
"lng_settings_section_advanced_settings" = "Configurações Avançadas";
|
||||
"lng_settings_enable_night_theme" = "Habilitar modo noturno";
|
||||
"lng_settings_disable_night_theme" = "Desabilitar modo noturno";
|
||||
|
||||
"lng_passcode_remove_button" = "Remover";
|
||||
|
||||
@@ -348,8 +388,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_passcode_autolock" = "Autobloquear";
|
||||
"lng_passcode_autolock_away" = "Autobloquear se ausente por:";
|
||||
"lng_passcode_autolock_inactive" = "Autobloquear se inativo por:";
|
||||
"lng_passcode_autolock_minutes" = "{count:_not_used_|# minuto|# minutos}";
|
||||
"lng_passcode_autolock_hours" = "{count:_not_used_|# hora|# horas}";
|
||||
"lng_passcode_autolock_minutes#one" = "{count} minuto";
|
||||
"lng_passcode_autolock_minutes#other" = "{count} minutos";
|
||||
"lng_passcode_autolock_hours#one" = "{count} hora";
|
||||
"lng_passcode_autolock_hours#other" = "{count} horas";
|
||||
"lng_passcode_enter_old" = "Insira sua senha atual";
|
||||
"lng_passcode_enter_first" = "Insira uma senha";
|
||||
"lng_passcode_enter_new" = "Insira sua nova senha";
|
||||
@@ -455,32 +497,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_privacy_lastseen_title" = "Visto por último";
|
||||
"lng_edit_privacy_lastseen_description" = "Você pode escolher quem vê o seu \"visto por último\":";
|
||||
"lng_edit_privacy_lastseen_warning" = "Importante: você não poderá ver o horário de Visto por Último de pessoas com as quais você não compartilha o seu. Você verá um valor aproximado (recentemente, na última semana, no último mês).";
|
||||
"lng_edit_privacy_lastseen_always" = "Sempre compartilhar com{count:| # usuário| # usuários}";
|
||||
"lng_edit_privacy_lastseen_never" = "Nunca compartilhar com{count:| # usuário| # usuários}";
|
||||
"lng_edit_privacy_lastseen_always_empty" = "Sempre compartilhar com";
|
||||
"lng_edit_privacy_lastseen_always#one" = "Sempre compartilhar com {count} usuário";
|
||||
"lng_edit_privacy_lastseen_always#other" = "Sempre compartilhar com {count} usuários";
|
||||
"lng_edit_privacy_lastseen_never_empty" = "Nunca compartilhar com";
|
||||
"lng_edit_privacy_lastseen_never#one" = "Nunca compartilhar com {count} usuário";
|
||||
"lng_edit_privacy_lastseen_never#other" = "Nunca compartilhar com {count} usuários";
|
||||
"lng_edit_privacy_lastseen_exceptions" = "Essas configurações irão sobrescrever os valores anteriores.";
|
||||
"lng_edit_privacy_lastseen_always_title" = "Sempre compartilhar com";
|
||||
"lng_edit_privacy_lastseen_never_title" = "Nunca compartilhar com";
|
||||
|
||||
"lng_edit_privacy_groups_title" = "Configurações de convite à grupos";
|
||||
"lng_edit_privacy_groups_description" = "Você pode escolher quem pode te adicionar em grupos e canais com precisão:";
|
||||
"lng_edit_privacy_groups_always" = "Sempre permitir{count:| # usuário| # usuários}";
|
||||
"lng_edit_privacy_groups_never" = "Nunca permitir{count:| # usuário| # usuários}";
|
||||
"lng_edit_privacy_groups_always_empty" = "Sempre permitir";
|
||||
"lng_edit_privacy_groups_always#one" = "Sempre permitir {count} usuário";
|
||||
"lng_edit_privacy_groups_always#other" = "Sempre permitir {count} usuários";
|
||||
"lng_edit_privacy_groups_never_empty" = "Nunca permitir";
|
||||
"lng_edit_privacy_groups_never#one" = "Nunca permitir {count} usuário";
|
||||
"lng_edit_privacy_groups_never#other" = "Nunca permitir {count} usuários";
|
||||
"lng_edit_privacy_groups_exceptions" = "Esses usuários poderão ou não te adicionar em grupos e canais dependendo de suas configurações.";
|
||||
"lng_edit_privacy_groups_always_title" = "Sempre permitir";
|
||||
"lng_edit_privacy_groups_never_title" = "Nunca permitir";
|
||||
|
||||
"lng_edit_privacy_calls_title" = "Chamadas";
|
||||
"lng_edit_privacy_calls_description" = "Você pode restringir quem te ligou:";
|
||||
"lng_edit_privacy_calls_always" = "Sempre permitir{count:| # usuário| # usuários}";
|
||||
"lng_edit_privacy_calls_never" = "Nunca permitir{count:| # usuário| # usuários}";
|
||||
"lng_edit_privacy_calls_always_empty" = "Sempre permitir";
|
||||
"lng_edit_privacy_calls_always#one" = "Sempre permitir {count} usuário";
|
||||
"lng_edit_privacy_calls_always#other" = "Sempre permitir {count} usuários";
|
||||
"lng_edit_privacy_calls_never_empty" = "Nunca permitir";
|
||||
"lng_edit_privacy_calls_never#one" = "Nunca permitir {count} usuário";
|
||||
"lng_edit_privacy_calls_never#other" = "Nunca permitir {count} usuários";
|
||||
"lng_edit_privacy_calls_exceptions" = "Esses usuários poderão ou não te ligar dependendo de suas configurações.";
|
||||
"lng_edit_privacy_calls_always_title" = "Sempre permitir";
|
||||
"lng_edit_privacy_calls_never_title" = "Nunca permitir";
|
||||
|
||||
"lng_self_destruct_title" = "Auto-destruição da conta";
|
||||
"lng_self_destruct_description" = "Se você não ficar online ao menos uma vez nesse período, sua conta será apagada junto com seus grupos, mensagens e contatos.";
|
||||
"lng_self_destruct_months" = "{count:_not_used_|# mês|# meses}";
|
||||
"lng_self_destruct_years" = "{count:_not_used_|# ano|# anos}";
|
||||
"lng_self_destruct_months#one" = "{count} mês";
|
||||
"lng_self_destruct_months#other" = "{count} meses";
|
||||
"lng_self_destruct_years#one" = "{count} ano";
|
||||
"lng_self_destruct_years#other" = "{count} anos";
|
||||
|
||||
"lng_change_phone_title" = "Alterar número de telefone";
|
||||
"lng_change_phone_description" = "Você pode alterar seu número do Telegram aqui.\nSua conta e todos os seus dados — mensagens,\nmídia, contatos, etc. serão movidos para\no novo número.\n\n[b]Importante[/b]: todos os contatos do Telegram terão\nseu [b]novo número[/b] adicionado às suas lista de contatos,\ndesde que eles tenham seu número antigo e você não\nos tenha bloqueado no Telegram.";
|
||||
@@ -506,15 +562,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_invite_link_section" = "Link de convite";
|
||||
"lng_profile_create_public_link" = "Criar link público";
|
||||
"lng_profile_edit_public_link" = "Editar link público";
|
||||
"lng_profile_search_members" = "Buscar membros";
|
||||
"lng_profile_manage_admins" = "Gerenciar administradores";
|
||||
"lng_profile_manage_blocklist" = "Gerenciar usuários bloqueados";
|
||||
"lng_profile_common_groups" = "{count:_not_used_|# grupo|# grupos} em comum";
|
||||
"lng_profile_manage_blocklist" = "Gerenciar usuários banidos";
|
||||
"lng_profile_manage_restrictedlist" = "Gerenciar usuários restritos";
|
||||
"lng_profile_recent_actions" = "Ações recentes";
|
||||
"lng_profile_common_groups#one" = "{count} grupo em comum";
|
||||
"lng_profile_common_groups#other" = "{count} grupos em comum";
|
||||
"lng_profile_common_groups_section" = "Grupos em comum";
|
||||
"lng_profile_participants_section" = "Membros";
|
||||
"lng_profile_info_section" = "Info";
|
||||
"lng_profile_mobile_number" = "Celular:";
|
||||
"lng_profile_username" = "Nome de usuário:";
|
||||
"lng_profile_link" = "Link:";
|
||||
"lng_profile_bio" = "Bio:";
|
||||
"lng_profile_add_contact" = "Adicionar Contato";
|
||||
"lng_profile_edit_contact" = "Editar";
|
||||
"lng_profile_enable_notifications" = "Notificações";
|
||||
@@ -542,23 +603,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_delete_and_exit" = "Sair";
|
||||
"lng_profile_kick" = "Remover";
|
||||
"lng_profile_admin" = "administrador";
|
||||
"lng_profile_edit_permissions" = "Editar";
|
||||
"lng_profile_sure_kick" = "Remover {user} do grupo?";
|
||||
"lng_profile_sure_kick_channel" = "Remover {user} do canal?";
|
||||
"lng_profile_sure_kick_admin" = "Remover {user} dos administradores?";
|
||||
"lng_profile_loading" = "Carregando...";
|
||||
"lng_profile_shared_media" = "Mídia compartilhada";
|
||||
"lng_profile_no_media" = "Nenhuma mídia nessa conversa.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# foto|# fotos}";
|
||||
"lng_profile_photos#one" = "{count} foto";
|
||||
"lng_profile_photos#other" = "{count} fotos";
|
||||
"lng_profile_photos_header" = "Fotos";
|
||||
"lng_profile_videos" = "{count:_not_used_|# vídeo|# vídeos}";
|
||||
"lng_profile_videos#one" = "{count} vídeo";
|
||||
"lng_profile_videos#other" = "{count} vídeos";
|
||||
"lng_profile_videos_header" = "Vídeos";
|
||||
"lng_profile_songs" = "{count:_not_used_|# áudio|# áudios}";
|
||||
"lng_profile_songs#one" = "{count} áudio";
|
||||
"lng_profile_songs#other" = "{count} áudios";
|
||||
"lng_profile_songs_header" = "Áudios";
|
||||
"lng_profile_files" = "{count:_not_used_|# arquivo|# arquivos}";
|
||||
"lng_profile_files#one" = "{count} arquivo";
|
||||
"lng_profile_files#other" = "{count} arquivos";
|
||||
"lng_profile_files_header" = "Arquivos";
|
||||
"lng_profile_audios" = "{count:_not_used_|# mensagem de voz|# mensagens de voz}";
|
||||
"lng_profile_audios#one" = "{count} mensagem de voz";
|
||||
"lng_profile_audios#other" = "{count} mensagens de voz";
|
||||
"lng_profile_audios_header" = "Mensagens de voz";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# link compartilhado|# links compartilhados}";
|
||||
"lng_profile_shared_links#one" = "{count} link compartilhado";
|
||||
"lng_profile_shared_links#other" = "{count} links compartilhados";
|
||||
"lng_profile_shared_links_header" = "Links compartilhados";
|
||||
"lng_profile_copy_phone" = "Copiar Número de Telefone";
|
||||
"lng_profile_copy_fullname" = "Copiar Nome";
|
||||
@@ -578,16 +646,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_report_button" = "Reportar";
|
||||
"lng_report_thanks" = "Obrigado! O relatório será revisado pela nossa equipe em breve.";
|
||||
|
||||
"lng_channel_add_admins" = "Novo administrador";
|
||||
"lng_channel_add_members" = "Adicionar membros";
|
||||
"lng_channel_add_banned" = "Banir usuário";
|
||||
"lng_channel_add_restricted" = "Restringir usuário";
|
||||
"lng_channel_members" = "Membros";
|
||||
"lng_channel_only_last_shown" = "Somente os últimos {count:_not_used_|# membro é|# membros são} exibidos";
|
||||
"lng_channel_only_last_shown#one" = "Somente o último {count} membro é exibido aqui";
|
||||
"lng_channel_only_last_shown#other" = "Somente os últimos {count} membros são exibidos aqui";
|
||||
"lng_channel_admins" = "Administradores";
|
||||
"lng_channel_add_admin" = "Adicionar Administrador";
|
||||
"lng_channel_admin_sure" = "Adicionar {user} aos administradores?";
|
||||
"lng_channel_admins_too_much" = "Você atingiu o limite de administradores. Remova um dos administradores primeiro.";
|
||||
"lng_channel_admin_status_creator" = "Criador";
|
||||
"lng_channel_admin_status_promoted_by" = "Promovido por {user}";
|
||||
"lng_channel_admin_status_not_admin" = "Não é administrador";
|
||||
|
||||
"lng_group_blocked_list_about" = "Usuários bloqueados são removidos do grupo e só podem voltar se convidados por um admin.\nLinks de convite não funcionam para eles.";
|
||||
"lng_group_blocked_list_about" = "Usuários banidos são removidos do grupo e só podem voltar se convidados por um admin.\nLinks de convite não funcionam para eles.";
|
||||
|
||||
"lng_chat_all_members_admins" = "Todos São Admins";
|
||||
"lng_chat_about_all_admins" = "Todos podem adicionar novos membros, editar nome e foto do grupo.";
|
||||
@@ -595,7 +667,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_participant_filter" = "Buscar";
|
||||
"lng_participant_invite" = "Convidar";
|
||||
"lng_participant_invite_sorry" = "Desculpe, você só pode adicionar os primeiros {count:_not_used|# membro|# membros} ao canal.\n\nDe agora em diante, precisarão do link de convite para entrar.";
|
||||
"lng_participant_invite_sorry#one" = "Desculpe, você só pode adicionar\no primeiro {count} membro ao canal.\n\nDe agora em diante, precisarão\ndo link de convite para entrar.";
|
||||
"lng_participant_invite_sorry#other" = "Desculpe, você só pode adicionar\nos primeiros {count} membros ao canal.\n\nDe agora em diante, precisarão\ndo link de convite para entrar.";
|
||||
"lng_create_group_back" = "Voltar";
|
||||
"lng_create_group_next" = "Próximo";
|
||||
"lng_create_group_create" = "Criar";
|
||||
@@ -637,8 +710,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_message_empty" = "Mensagem Vazia";
|
||||
"lng_message_unsupported" = "Essa mensagem não é suportada em sua versão do Telegram Desktop. Atualize para a última versão nas Configurações ou instale por aqui {link}";
|
||||
|
||||
"lng_duration_seconds" = "{count:_not_used_|# segundo|# segundos}";
|
||||
"lng_duration_minutes_seconds" = "{count_minutes:# min|# min|# min} {count_seconds:# seg|# seg|# seg}";
|
||||
"lng_duration_seconds#one" = "{count} segundo";
|
||||
"lng_duration_seconds#other" = "{count} segundos";
|
||||
"lng_duration_minsec_minutes#one" = "{count} min";
|
||||
"lng_duration_minsec_minutes#other" = "{count} min";
|
||||
"lng_duration_minsec_seconds#one" = "{count} seg";
|
||||
"lng_duration_minsec_seconds#other" = "{count} seg";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_add_user" = "{from} adicionou {user}";
|
||||
"lng_action_add_users_many" = "{from} adicionou {users}";
|
||||
@@ -676,18 +754,33 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_action_pinned_media_sticker" = "um sticker";
|
||||
"lng_action_pinned_media_emoji_sticker" = "um {emoji} sticker";
|
||||
"lng_action_pinned_media_game" = "o jogo «{game}»";
|
||||
"lng_action_game_score" = "{from} marcou {count:# pontos|# ponto|# pontos} em {game}";
|
||||
"lng_action_game_you_scored" = "Você marcou {count:# pontos|# ponto|# pontos} em {game}";
|
||||
"lng_action_game_score_no_game" = "{from} marcou {count:# pontos|# ponto|# pontos}";
|
||||
"lng_action_game_you_scored_no_game" = "Você marcou {count:# pontos|# ponto|# pontos}";
|
||||
"lng_action_game_score#one" = "{from} marcou {count} ponto em {game}";
|
||||
"lng_action_game_score#other" = "{count} marcou {count} pontos em {game}";
|
||||
"lng_action_game_you_scored#one" = "Você marcou {count} ponto em {game}";
|
||||
"lng_action_game_you_scored#other" = "Você marcou {count} pontos em {game}";
|
||||
"lng_action_game_score_no_game#one" = "{from} marcou {count} ponto";
|
||||
"lng_action_game_score_no_game#other" = "{from} marcou {count} pontos";
|
||||
"lng_action_game_you_scored_no_game#one" = "Você marcou {count} ponto";
|
||||
"lng_action_game_you_scored_no_game#other" = "Você marcou {count} pontos";
|
||||
"lng_action_payment_done" = "Você transferiu com sucesso {amount} para {user}";
|
||||
"lng_action_payment_done_for" = "Você transferiu com sucesso {amount} para {user} por {invoice}";
|
||||
"lng_action_took_screenshot" = "{from} realizou uma captura de tela!";
|
||||
"lng_action_you_took_screenshot" = "Você realizou uma captura de tela!";
|
||||
|
||||
"lng_profile_migrate_reached" = "{count:_not_used_|# membro|# membros} limite alcançado";
|
||||
"lng_ttl_photo_received" = "{from} te enviou uma foto auto-destrutiva. Por favor, veja em seu celular.";
|
||||
"lng_ttl_photo_sent" = "Você enviou uma foto auto-destrutiva.";
|
||||
"lng_ttl_photo_expired" = "A foto expirou";
|
||||
"lng_ttl_video_received" = "{from} te enviou um vídeo auto-destrutivo. Por favor, veja em seu celular.";
|
||||
"lng_ttl_video_sent" = "Você enviou um vídeo auto-destrutivo.";
|
||||
"lng_ttl_video_expired" = "O vídeo expirou";
|
||||
|
||||
"lng_profile_migrate_reached#one" = "{count} limite de membro alcançado";
|
||||
"lng_profile_migrate_reached#other" = "{count} limite de membros alcançado";
|
||||
"lng_profile_migrate_body" = "Para ir além desse limite, você pode converter seu grupo em um supergrupo.";
|
||||
"lng_profile_migrate_learn_more" = "Leia mais »";
|
||||
"lng_profile_migrate_about" = "Se você deseja ir além do limite, pode converter seu grupo em um supergrupo. Nos supergrupos:";
|
||||
"lng_profile_migrate_feature1" = "— O limite de membros são {count:_not_used_|# usuário|# usuários}";
|
||||
"lng_profile_migrate_feature1#one" = "— O limite de membros é de {count} usuário";
|
||||
"lng_profile_migrate_feature1#other" = "— O limite de membros é de {count} usuários";
|
||||
"lng_profile_migrate_feature2" = "— Novos membros podem ver todo o histórico";
|
||||
"lng_profile_migrate_feature3" = "— Administradores podem apagar mensagens para todos";
|
||||
"lng_profile_migrate_feature4" = "— Notificações silenciadas por padrão";
|
||||
@@ -698,11 +791,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_convert_about" = "Em supergrupos:";
|
||||
"lng_profile_convert_feature1" = "— Novos membros podem ver todo o histórico";
|
||||
"lng_profile_convert_feature2" = "— Mensagens apagadas desaparecerão para todos";
|
||||
"lng_profile_convert_feature3" = "— Admins podem ficar mensagens importantes";
|
||||
"lng_profile_convert_feature3" = "— Admins podem fixar mensagens importantes";
|
||||
"lng_profile_convert_feature4" = "— Criador pode definir um link público para o grupo";
|
||||
"lng_profile_convert_warning" = "{bold_start}Nota:{bold_end} Essa ação não pode ser desfeita";
|
||||
"lng_profile_convert_confirm" = "Converter";
|
||||
"lng_profile_add_more_after_upgrade" = "Você pode adicionar até {count:_not_used_|# membro|# membros} depois de converter seu grupo a um supergrupo.";
|
||||
"lng_profile_add_more_after_upgrade#one" = "Você pode adicionar até {count} membro depois de converter seu grupo a um supergrupo.";
|
||||
"lng_profile_add_more_after_upgrade#other" = "Você pode adicionar até {count} membros depois de converter seu grupo a um supergrupo.";
|
||||
|
||||
"lng_channel_not_accessible" = "Desculpe, esse canal não está acessível.";
|
||||
"lng_group_not_accessible" = "Desculpe, esse grupo não está acessível.";
|
||||
@@ -717,7 +811,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_group_invite_want_join_channel" = "Você deseja entrar no canal «{title}»?";
|
||||
"lng_group_invite_join" = "Entrar";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# membro|# membros}, entre eles:";
|
||||
"lng_group_invite_members#one" = "{count} membro, entre eles:";
|
||||
"lng_group_invite_members#other" = "{count} membros, entre eles:";
|
||||
|
||||
"lng_group_invite_link" = "Link de convite:";
|
||||
"lng_group_invite_create" = "Criar um link de convite";
|
||||
@@ -730,6 +825,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_channel_public_link_copied" = "Link copiado para área de transferência.";
|
||||
|
||||
"lng_forwarded" = "Encaminhado de {user}";
|
||||
"lng_forwarded_date" = "Original: {date}";
|
||||
"lng_forwarded_channel" = "Encaminhado de {channel}";
|
||||
"lng_forwarded_via" = "Encaminhado de {user} via {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Encaminhado de {channel} via {inline_bot}";
|
||||
@@ -809,7 +905,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_stickers_you_have" = "Gerenciar e reordenar os pacotes de sticker";
|
||||
"lng_stickers_featured" = "Stickers Populares";
|
||||
"lng_stickers_return" = "Desfazer";
|
||||
"lng_stickers_count" = "{count:Carregando...|# sticker|# stickers}";
|
||||
"lng_stickers_count#one" = "{count} sticker";
|
||||
"lng_stickers_count#other" = "{count} stickers";
|
||||
"lng_stickers_masks_pack" = "Esse é um pacote de máscaras. Você pode usá-las no editor de fotos em nossos aplicativos para celular.";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
@@ -839,6 +936,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_cant_invite_banned" = "Apenas um administrador pode adicionar esse usuário.";
|
||||
"lng_cant_invite_privacy" = "Você não pode adicionar esse usuário em grupos devido as configurações de privacidade.";
|
||||
"lng_cant_invite_privacy_channel" = "Você não pode adicionar esse usuário em canais devido as configurações de privacidade.";
|
||||
"lng_cant_delete_group#one" = "Desculpe, atualmente não é possível apagar comunidades que tenham mais de {count} membro. Por favor, contate o suporte do Telegram se você precisa apagar esse grupo.";
|
||||
"lng_cant_delete_group#other" = "Desculpe, atualmente não é possível apagar comunidades que tenham mais de {count} membros. Por favor, contate o suporte do Telegram se você precisa apagar esse grupo.";
|
||||
"lng_cant_delete_channel#one" = "Desculpe, atualmente não é possível apagar comunidades que tenham mais de {count} membro. Por favor, contate o suporte do Telegram se você precisa apagar esse canal.";
|
||||
"lng_cant_delete_channel#other" = "Desculpe, atualmente não é possível apagar comunidades que tenham mais de {count} membros. Por favor, contate o suporte do Telegram se você precisa apagar esse canal.";
|
||||
"lng_cant_do_this" = "Essa ação não está disponível.";
|
||||
|
||||
"lng_send_button" = "Enviar";
|
||||
@@ -884,11 +985,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_typing" = "escrevendo";
|
||||
"lng_user_typing" = "{user} está escrevendo";
|
||||
"lng_users_typing" = "{user} e {second_user} estão escrevendo";
|
||||
"lng_many_typing" = "{count:_not_used_|# está|# estão} escrevendo";
|
||||
"lng_many_typing#one" = "{count} está escrevendo";
|
||||
"lng_many_typing#other" = "{count} estão escrevendo";
|
||||
"lng_playing_game" = "jogando";
|
||||
"lng_user_playing_game" = "{user} está jogando";
|
||||
"lng_users_playing_game" = "{user} e {second_user} estão jogando";
|
||||
"lng_many_playing_game" = "{count:_not_used_|# está|# estão} jogando";
|
||||
"lng_many_playing_game#one" = "{count} está jogando";
|
||||
"lng_many_playing_game#other" = "{count} estão jogando";
|
||||
"lng_send_action_record_video" = "gravando um vídeo";
|
||||
"lng_user_action_record_video" = "{user} está gravando um vídeo";
|
||||
"lng_send_action_upload_video" = "enviando um vídeo";
|
||||
@@ -909,7 +1012,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_user_action_geo_location" = "{user} está escolhendo uma localização";
|
||||
"lng_send_action_choose_contact" = "escolhendo um contato";
|
||||
"lng_user_action_choose_contact" = "{user} está escolhendo um contato";
|
||||
"lng_unread_bar" = "{count:_not_used_|# mensagem não lida|# mensagens não lidas}";
|
||||
"lng_unread_bar#one" = "{count} mensagem não lida";
|
||||
"lng_unread_bar#other" = "{count} mensagens não lidas";
|
||||
|
||||
"lng_maps_point" = "Localização";
|
||||
"lng_save_photo" = "Salvar imagem";
|
||||
@@ -932,7 +1036,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_from_top" = "Desafixar do topo";
|
||||
|
||||
"lng_context_promote_admin" = "Promover a administrador";
|
||||
"lng_context_remove_admin" = "Remover dos administradores";
|
||||
"lng_context_edit_permissions" = "Editar permissões";
|
||||
"lng_context_restrict_user" = "Restringir usuário";
|
||||
"lng_context_remove_from_group" = "Remover do grupo";
|
||||
|
||||
"lng_context_copy_link" = "Copiar Link";
|
||||
@@ -970,31 +1075,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_context_unpin_msg" = "Desafixar Mensagem";
|
||||
"lng_context_cancel_upload" = "Cancelar Envio";
|
||||
"lng_context_copy_selected" = "Copiar Texto Selecionado";
|
||||
"lng_context_copy_selected_items" = "Copiar Seleção como Texto";
|
||||
"lng_context_forward_selected" = "Encaminhar Selecionado";
|
||||
"lng_context_delete_selected" = "Apagar Selecionado";
|
||||
"lng_context_clear_selection" = "Limpar Seleção";
|
||||
"lng_really_send_image" = "Você deseja enviar essa imagem?";
|
||||
"lng_really_send_file" = "Você deseja enviar esse arquivo?";
|
||||
"lng_really_share_contact" = "Você deseja compartilhar esse contato?";
|
||||
"lng_send_images_compress" = "Comprimir {count:_not_used_|imagem|imagens}";
|
||||
"lng_send_images_compress#one" = "Comprimir imagem";
|
||||
"lng_send_images_compress#other" = "Comprimir imagens";
|
||||
"lng_send_image_non_local" = "Não foi possível enviar um arquivo não local: {name}";
|
||||
"lng_send_image_empty" = "Não foi possível enviar um arquivo vazio: {name}";
|
||||
"lng_send_image_too_large" = "Não foi possível enviar um arquivo, por ser maior que 1500 MB: {name}";
|
||||
"lng_send_folder" = "Não pude enviar «{name}» porque é um diretório :(";
|
||||
"lng_send_images_selected" = "{count:_not_used_|# imagem selecionada|# imagens selecionadas}";
|
||||
"lng_send_photos" = "Enviar {count:_not_used_|# foto|# fotos}";
|
||||
"lng_send_files_selected" = "{count:_not_used_|# arquivo selecionado|# arquivos selecionados}";
|
||||
"lng_send_files" = "Enviar {count:_not_used_|# arquivo|# arquivos}";
|
||||
"lng_send_images_selected#one" = "{count} imagem selecionada";
|
||||
"lng_send_images_selected#other" = "{count} imagens selecionadas";
|
||||
"lng_send_photos#one" = "Enviar {count} foto";
|
||||
"lng_send_photos#other" = "Enviar {count} fotos";
|
||||
"lng_send_files_selected#one" = "{count} arquivo selecionado";
|
||||
"lng_send_files_selected#other" = "{count} arquivos selecionados";
|
||||
"lng_send_files#one" = "Enviar {count} arquivo";
|
||||
"lng_send_files#other" = "Enviar {count} arquivos";
|
||||
|
||||
"lng_forward_choose" = "Escolher recipiente...";
|
||||
"lng_forward_cant" = "Desculpe, não há como encaminhar aqui :(";
|
||||
"lng_forward_confirm" = "Encaminhar para {recipient}?";
|
||||
"lng_forward_share_contact" = "Compartilhar contato com {recipient}?";
|
||||
"lng_forward_share_cant" = "Não há como compartilhar um contato aqui :(";
|
||||
"lng_forward_send_file_confirm" = "Enviar «{name}» para {recipient}";
|
||||
"lng_forward_send_files_confirm" = "Enviar arquivos selecionados para {recipient}?";
|
||||
"lng_forward_send_files_cant" = "Não há como compartilhar um mídias aqui :(";
|
||||
"lng_forward_send" = "Enviar";
|
||||
"lng_forward_messages" = "{count:_not_used_|Mensagem encaminhada|# mensagens encaminhadas}";
|
||||
"lng_forwarding_from" = "{user} e {count:_not_used_|# outro|# outros}";
|
||||
"lng_forward_messages#one" = "{count} mensagem encaminhada";
|
||||
"lng_forward_messages#other" = "{count} mensagens encaminhadas";
|
||||
"lng_forwarding_from#one" = "{user} e {count} outro";
|
||||
"lng_forwarding_from#other" = "{user} e {count} outros";
|
||||
"lng_forwarding_from_two" = "{user} e {second_user}";
|
||||
"lng_inline_switch_choose" = "Escolher conversa...";
|
||||
"lng_inline_switch_cant" = "Desculpe, não há como escrever aqui :(";
|
||||
@@ -1016,6 +1131,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_edit_contact_title" = "Editar nome de contato";
|
||||
"lng_edit_channel_title" = "Editar Canal";
|
||||
"lng_edit_sign_messages" = "Assinar mensagens";
|
||||
"lng_edit_group_who_invites" = "Quem pode adicionar membros";
|
||||
"lng_edit_group_invites_everybody" = "Todos os membros";
|
||||
"lng_edit_group_invites_only_admins" = "Somente administradores";
|
||||
"lng_edit_group" = "Editar grupo";
|
||||
"lng_edit_self_title" = "Editar seu nome";
|
||||
"lng_confirm_contact_data" = "Novo Contato";
|
||||
@@ -1040,15 +1158,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_selected_clear" = "Cancelar";
|
||||
"lng_selected_delete" = "Apagar";
|
||||
"lng_selected_forward" = "Encaminhar";
|
||||
"lng_selected_count" = "{count:_not_used_|# mensagem|# mensagens}";
|
||||
"lng_selected_count#one" = "{count} mensagem";
|
||||
"lng_selected_count#other" = "{count} mensagens";
|
||||
"lng_selected_cancel_sure_this" = "Cancelar envio?";
|
||||
"lng_selected_upload_stop" = "Parar";
|
||||
"lng_selected_delete_sure_this" = "Você deseja apagar essa mensagem?";
|
||||
"lng_selected_delete_sure" = "Você deseja apagar {count:_not_used_|# mensagem|# mensagens}?";
|
||||
"lng_selected_delete_sure#one" = "Você deseja apagar {count} mensagem?";
|
||||
"lng_selected_delete_sure#other" = "Você deseja apagar {count} mensagens?";
|
||||
"lng_delete_photo_sure" = "Você deseja apagar essa foto?";
|
||||
"lng_delete_for_everyone_hint" = "Isso irá apagar {count:_not_used_|a mensagem|as mensagens} para todos nessa conversa.";
|
||||
"lng_delete_for_me_chat_hint" = "Isso irá apagar {count:_not_used_|a mensagem|as mensagens} somente para você, não para os outros participantes da conversa.";
|
||||
"lng_delete_for_me_hint" = "Isso irá apagar {count:_not_used_|a mensagem|as mensagens} apenas para você.";
|
||||
"lng_delete_for_everyone_hint#one" = "Isso irá apagar para todos nessa conversa.";
|
||||
"lng_delete_for_everyone_hint#other" = "Isso irá apagar para todos nessa conversa.";
|
||||
"lng_delete_for_me_chat_hint#one" = "Isso apagará somente para você, não para os outros participantes da conversa.";
|
||||
"lng_delete_for_me_chat_hint#other" = "Isso irá apagar somente para você, não para os outros participantes da conversa.";
|
||||
"lng_delete_for_me_hint#one" = "Isso irá apagar somente para você.";
|
||||
"lng_delete_for_me_hint#other" = "Isso irá apagar somente para você.";
|
||||
"lng_delete_for_everyone_check" = "Apagar para todos";
|
||||
"lng_delete_for_other_check" = "Apagar para {user}";
|
||||
"lng_box_delete" = "Apagar";
|
||||
@@ -1060,7 +1183,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_about_text_3" = "Visite as {faq_open}Perguntas Frequentes{faq_close} para mais informações.";
|
||||
"lng_about_done" = "Concluído";
|
||||
|
||||
"lng_search_found_results" = "{count:Nenhuma mensagem encontrada|Encontrada # mensagem|Encontradas # mensagens}";
|
||||
"lng_search_no_results" = "Nenhuma mensagem encontrada";
|
||||
"lng_search_found_results#one" = "Encontrada {count} mensagem";
|
||||
"lng_search_found_results#other" = "Encontradas {count} mensagens";
|
||||
"lng_search_global_results" = "Resultados da busca global";
|
||||
|
||||
"lng_media_save_progress" = "{ready} de {total} {mb}";
|
||||
@@ -1169,11 +1294,133 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_player_message_yesterday" = "Ontem às {time}";
|
||||
"lng_player_message_date" = "{date} às {time}";
|
||||
|
||||
"lng_rights_edit_admin" = "Editar administrador";
|
||||
"lng_rights_edit_admin_header" = "O que esse administrador pode fazer?";
|
||||
"lng_rights_about_add_admins_yes" = "Esse admin poderá adicionar novos admins com as mesmas (ou mais limitadas) permissões.";
|
||||
"lng_rights_about_add_admins_no" = "Esse admin não poderá adicionar novos admins.";
|
||||
"lng_rights_about_admin_cant_edit" = "Você não pode editar as permissões desse admin.";
|
||||
"lng_rights_user_restrictions" = "Restrições do usuário";
|
||||
"lng_rights_user_restrictions_header" = "O que esse usuário pode fazer?";
|
||||
|
||||
"lng_rights_channel_info" = "Alterar info do canal";
|
||||
"lng_rights_channel_post" = "Postar mensagens";
|
||||
"lng_rights_channel_edit" = "Editar mensagens de outros";
|
||||
"lng_rights_channel_delete" = "Apagar mensagens de outros";
|
||||
"lng_rights_group_info" = "Alterar info do grupo";
|
||||
"lng_rights_group_ban" = "Banir usuários";
|
||||
"lng_rights_group_invite_link" = "Convidar usuários via link";
|
||||
"lng_rights_group_invite" = "Adicionar usuários";
|
||||
"lng_rights_group_pin" = "Fixar mensagens";
|
||||
"lng_rights_group_delete" = "Apagar mensagens";
|
||||
"lng_rights_add_admins" = "Adicionar novos admins";
|
||||
"lng_rights_chat_read" = "Ler mensagens";
|
||||
"lng_rights_chat_send_text" = "Enviar mensagens";
|
||||
"lng_rights_chat_send_media" = "Enviar mídias";
|
||||
"lng_rights_chat_send_stickers" = "Enviar stickers e GIFs";
|
||||
"lng_rights_chat_send_links" = "Preview de links";
|
||||
"lng_rights_chat_banned_until_header" = "Restringir até";
|
||||
"lng_rights_chat_banned_forever" = "Sempre";
|
||||
"lng_rights_chat_banned_day#one" = "Por {count} dia";
|
||||
"lng_rights_chat_banned_day#other" = "Por {count} dias";
|
||||
"lng_rights_chat_banned_week#one" = "Por {count} semana";
|
||||
"lng_rights_chat_banned_week#other" = "Por {count} semanas";
|
||||
"lng_rights_chat_banned_custom" = "Personalizado";
|
||||
"lng_rights_chat_banned_custom_date" = "Até {date}";
|
||||
"lng_rights_chat_banned_block" = "Banir e remover do grupo";
|
||||
|
||||
"lng_restricted_send_message" = "Os administradores do grupo restringiram você de escrever aqui.";
|
||||
"lng_restricted_send_media" = "Os administradores do grupo restringiram você de enviar mídias aqui.";
|
||||
"lng_restricted_send_stickers" = "Desculpe, os administradores do grupo te restringiram do envio de stickers.";
|
||||
"lng_restricted_send_gifs" = "Desculpe, os administradores do grupo te restringiram do envio de GIFs.";
|
||||
"lng_restricted_send_inline" = "Os administradores do grupo restringiram você de usar bots integrados aqui.";
|
||||
|
||||
"lng_restricted_list_title" = "Usuários restritos";
|
||||
"lng_banned_list_title" = "Usuários banidos";
|
||||
|
||||
"lng_admin_log_title_all" = "Todas as ações";
|
||||
"lng_admin_log_title_selected" = "Ações selecionadas";
|
||||
"lng_admin_log_filter" = "Filtro";
|
||||
"lng_admin_log_filter_title" = "Filtro";
|
||||
"lng_admin_log_filter_all_actions" = "Todas as ações";
|
||||
"lng_admin_log_filter_restrictions" = "Novas restrições";
|
||||
"lng_admin_log_filter_admins_new" = "Novos admins";
|
||||
"lng_admin_log_filter_members_new" = "Novos membros";
|
||||
"lng_admin_log_filter_info_group" = "Info do grupo";
|
||||
"lng_admin_log_filter_info_channel" = "Info do canal";
|
||||
"lng_admin_log_filter_messages_deleted" = "Mensagens apagadas";
|
||||
"lng_admin_log_filter_messages_edited" = "Mensagens editadas";
|
||||
"lng_admin_log_filter_messages_pinned" = "Mensagens fixadas";
|
||||
"lng_admin_log_filter_members_removed" = "Membros saindo";
|
||||
"lng_admin_log_filter_all_admins" = "Todos usuários e admins";
|
||||
"lng_admin_log_about" = "O que é isso?";
|
||||
"lng_admin_log_about_text" = "Essa é uma lista de todas as ações tomadas pelos membros e admins do grupo nas últimas 48 horas.";
|
||||
"lng_admin_log_no_results_title" = "Nenhuma ação encontrada";
|
||||
"lng_admin_log_no_results_text" = "Nenhuma ação correspondente foi encontrado.";
|
||||
"lng_admin_log_no_results_search_text" = "Nenhuma ação que contenha \"{query}\" foi encontrada.";
|
||||
"lng_admin_log_no_events_title" = "Ainda não há ações aqui.";
|
||||
"lng_admin_log_no_events_text" = "Nenhuma ação foi tomada pelos\nmembros e admins do grupo\nnas últimas 48 horas.";
|
||||
|
||||
"lng_admin_log_empty_text" = "Vazio";
|
||||
"lng_admin_log_changed_title_group" = "{from} alterou o título do grupo para «{title}»";
|
||||
"lng_admin_log_changed_title_channel" = "{from} alterou o título do canal para «{title}»";
|
||||
"lng_admin_log_changed_description_group" = "{from} editou a descrição do grupo:";
|
||||
"lng_admin_log_removed_description_group" = "{from} removeu a descrição do grupo";
|
||||
"lng_admin_log_changed_description_channel" = "{from} editou a descrição do canal:";
|
||||
"lng_admin_log_removed_description_channel" = "{from} removeu a descrição do canal";
|
||||
"lng_admin_log_previous_description" = "Descrição prévia";
|
||||
"lng_admin_log_changed_link_group" = "{from} alterou o link do grupo";
|
||||
"lng_admin_log_removed_link_group" = "{from} removeu o link do grupo";
|
||||
"lng_admin_log_changed_link_channel" = "{from} alterou o link do canal:";
|
||||
"lng_admin_log_removed_link_channel" = "{from} removeu o link do canal";
|
||||
"lng_admin_log_previous_link" = "Link prévio";
|
||||
"lng_admin_log_changed_photo_group" = "{from} alterou a foto do grupo";
|
||||
"lng_admin_log_changed_photo_channel" = "{from} alterou a foto do canal";
|
||||
"lng_admin_log_removed_photo_group" = "{from} removeu a foto do grupo";
|
||||
"lng_admin_log_removed_photo_channel" = "{from} removeu a foto do canal";
|
||||
"lng_admin_log_invites_enabled" = "{from} habilitou convites ao grupo";
|
||||
"lng_admin_log_invites_disabled" = "{from} desabilitou convites ao grupo";
|
||||
"lng_admin_log_signatures_enabled" = "{from} assinaturas habilitadas";
|
||||
"lng_admin_log_signatures_disabled" = "{from} assinaturas desabilitadas";
|
||||
"lng_admin_log_pinned_message" = "{from} fixou a mensagem:";
|
||||
"lng_admin_log_unpinned_message" = "{from} desafixou a mensagem";
|
||||
"lng_admin_log_edited_caption" = "{from} editou a legenda:";
|
||||
"lng_admin_log_removed_caption" = "{from} removeu a legenda";
|
||||
"lng_admin_log_previous_caption" = "Legenda original";
|
||||
"lng_admin_log_edited_message" = "{from} editou a mensagem:";
|
||||
"lng_admin_log_previous_message" = "Mensagem original";
|
||||
"lng_admin_log_deleted_message" = "{from} apagou a mensagem:";
|
||||
"lng_admin_log_participant_joined" = "{from} entrou no grupo";
|
||||
"lng_admin_log_participant_joined_channel" = "{from} entrou no canal";
|
||||
"lng_admin_log_participant_left" = "{from} deixou o grupo";
|
||||
"lng_admin_log_participant_left_channel" = "{from} saiu do canal";
|
||||
"lng_admin_log_invited" = "convidou {user}";
|
||||
"lng_admin_log_banned" = "baniu {user}";
|
||||
"lng_admin_log_restricted" = "alterou as restrições de {user} {until}";
|
||||
"lng_admin_log_promoted" = "alterou os privilégios de {user}";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_restricted_forever" = "indefinidamente";
|
||||
"lng_admin_log_restricted_until" = "até {data}";
|
||||
"lng_admin_log_banned_view_messages" = "Ler mensagens";
|
||||
"lng_admin_log_banned_send_messages" = "Enviar mensagens";
|
||||
"lng_admin_log_banned_send_media" = "Enviar mídias";
|
||||
"lng_admin_log_banned_send_stickers" = "Enviar stickers e GIFs";
|
||||
"lng_admin_log_banned_embed_links" = "Preview de links";
|
||||
"lng_admin_log_admin_change_info" = "Alterar info";
|
||||
"lng_admin_log_admin_post_messages" = "Postar mensagens";
|
||||
"lng_admin_log_admin_edit_messages" = "Editar mensagens";
|
||||
"lng_admin_log_admin_delete_messages" = "Apagar mensagens";
|
||||
"lng_admin_log_admin_ban_users" = "Banir usuários";
|
||||
"lng_admin_log_admin_invite_users" = "Adicionar usuários";
|
||||
"lng_admin_log_admin_invite_link" = "Convidar usuários via link";
|
||||
"lng_admin_log_admin_pin_messages" = "Fixar mensagens";
|
||||
"lng_admin_log_admin_add_admins" = "Adicionar novos admins";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "Info";
|
||||
"lng_profile_group_info" = "Informação do grupo";
|
||||
"lng_profile_channel_info" = "Info do Canal";
|
||||
"lng_channel_add_admins" = "Novo administrador";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
||||
BIN
Telegram/Resources/night.tdesktop-theme
Normal file
@@ -8,6 +8,7 @@
|
||||
<file alias="art/logo_256.png">../art/logo_256.png</file>
|
||||
<file alias="art/logo_256_no_margin.png">../art/logo_256_no_margin.png</file>
|
||||
<file alias="art/sunrise.jpg">../art/sunrise.jpg</file>
|
||||
<file alias="night.tdesktop-theme">../night.tdesktop-theme</file>
|
||||
</qresource>
|
||||
<qresource prefix="/sounds">
|
||||
<file alias="msg_incoming.mp3">../sounds/msg_incoming.mp3</file>
|
||||
|
||||
@@ -106,6 +106,9 @@ new_session_created#9ec20908 first_msg_id:long unique_id:long server_salt:long =
|
||||
|
||||
http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;
|
||||
|
||||
ipPort ipv4:int port:int = IpPort;
|
||||
help.configSimple#d997c3c5 date:int expires:int dc_id:int ip_port_list:Vector<ipPort> = help.ConfigSimple;
|
||||
|
||||
---functions---
|
||||
|
||||
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
|
||||
@@ -152,17 +155,16 @@ inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile
|
||||
inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile;
|
||||
|
||||
inputMediaEmpty#9664f57f = InputMedia;
|
||||
inputMediaUploadedPhoto#630c9af1 flags:# file:InputFile caption:string stickers:flags.0?Vector<InputDocument> = InputMedia;
|
||||
inputMediaPhoto#e9bfb4f3 id:InputPhoto caption:string = InputMedia;
|
||||
inputMediaUploadedPhoto#2f37e231 flags:# file:InputFile caption:string stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
|
||||
inputMediaPhoto#81fa373a flags:# id:InputPhoto caption:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
|
||||
inputMediaContact#a6e45987 phone_number:string first_name:string last_name:string = InputMedia;
|
||||
inputMediaUploadedDocument#d070f1e9 flags:# file:InputFile mime_type:string attributes:Vector<DocumentAttribute> caption:string stickers:flags.0?Vector<InputDocument> = InputMedia;
|
||||
inputMediaUploadedThumbDocument#50d88cae flags:# file:InputFile thumb:InputFile mime_type:string attributes:Vector<DocumentAttribute> caption:string stickers:flags.0?Vector<InputDocument> = InputMedia;
|
||||
inputMediaDocument#1a77f29c id:InputDocument caption:string = InputMedia;
|
||||
inputMediaUploadedDocument#e39621fd flags:# file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> caption:string stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
|
||||
inputMediaDocument#5acb668e flags:# id:InputDocument caption:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaVenue#2827a81a geo_point:InputGeoPoint title:string address:string provider:string venue_id:string = InputMedia;
|
||||
inputMediaGifExternal#4843b0fd url:string q:string = InputMedia;
|
||||
inputMediaPhotoExternal#b55f4f18 url:string caption:string = InputMedia;
|
||||
inputMediaDocumentExternal#e5e9607c url:string caption:string = InputMedia;
|
||||
inputMediaPhotoExternal#922aec1 flags:# url:string caption:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaDocumentExternal#b6f74335 flags:# url:string caption:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
|
||||
inputMediaInvoice#92153685 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string start_param:string = InputMedia;
|
||||
|
||||
@@ -216,11 +218,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
||||
chatEmpty#9ba2d800 id:int = Chat;
|
||||
chat#d91cdd54 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true admins_enabled:flags.3?true admin:flags.4?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel = Chat;
|
||||
chatForbidden#7328bdb id:int title:string = Chat;
|
||||
channel#a14dca52 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true editor:flags.3?true moderator:flags.4?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true democracy:flags.10?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string = Chat;
|
||||
channelForbidden#8537784f flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string = Chat;
|
||||
channel#cb44b1c flags:# creator:flags.0?true left:flags.2?true editor:flags.3?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true democracy:flags.10?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChannelAdminRights banned_rights:flags.15?ChannelBannedRights = Chat;
|
||||
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
|
||||
chatFull#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> = ChatFull;
|
||||
channelFull#c3d5512f flags:# can_view_participants:flags.3?true can_set_username:flags.6?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int = ChatFull;
|
||||
channelFull#95cb5f57 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int = ChatFull;
|
||||
|
||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
||||
@@ -233,15 +235,15 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
|
||||
|
||||
messageEmpty#83e5de54 id:int = Message;
|
||||
message#c09be45f flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int = Message;
|
||||
message#90dddc11 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string = Message;
|
||||
messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;
|
||||
|
||||
messageMediaEmpty#3ded6320 = MessageMedia;
|
||||
messageMediaPhoto#3d8ce53d photo:Photo caption:string = MessageMedia;
|
||||
messageMediaPhoto#b5223b0f flags:# photo:flags.0?Photo caption:flags.1?string ttl_seconds:flags.2?int = MessageMedia;
|
||||
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
|
||||
messageMediaContact#5e7d2f39 phone_number:string first_name:string last_name:string user_id:int = MessageMedia;
|
||||
messageMediaUnsupported#9f84f49e = MessageMedia;
|
||||
messageMediaDocument#f3e02ea8 document:Document caption:string = MessageMedia;
|
||||
messageMediaDocument#7c4414d3 flags:# document:flags.0?Document caption:flags.1?string ttl_seconds:flags.2?int = MessageMedia;
|
||||
messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia;
|
||||
messageMediaVenue#7912b71f geo:GeoPoint title:string address:string provider:string venue_id:string = MessageMedia;
|
||||
messageMediaGame#fdb19008 game:Game = MessageMedia;
|
||||
@@ -264,6 +266,7 @@ messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
|
||||
messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
|
||||
messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction;
|
||||
messageActionPhoneCall#80e11a7f flags:# call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
|
||||
messageActionScreenshotTaken#4792929b = MessageAction;
|
||||
|
||||
dialog#66ffba14 flags:# pinned:flags.2?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog;
|
||||
|
||||
@@ -326,7 +329,7 @@ contacts.link#3ace484c my_link:ContactLink foreign_link:ContactLink user:User =
|
||||
contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
|
||||
contacts.contacts#6f8b8cb2 contacts:Vector<Contact> users:Vector<User> = contacts.Contacts;
|
||||
|
||||
contacts.importedContacts#ad524315 imported:Vector<ImportedContact> retry_contacts:Vector<long> users:Vector<User> = contacts.ImportedContacts;
|
||||
contacts.importedContacts#77d01c3b imported:Vector<ImportedContact> popular_invites:Vector<PopularContact> retry_contacts:Vector<long> users:Vector<User> = contacts.ImportedContacts;
|
||||
|
||||
contacts.blocked#1c138d15 blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
|
||||
contacts.blockedSlice#900802a1 count:int blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
|
||||
@@ -420,6 +423,8 @@ updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Upd
|
||||
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
|
||||
updateBotPrecheckoutQuery#5d2f3aa9 flags:# query_id:long user_id:int payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string currency:string total_amount:long = Update;
|
||||
updatePhoneCall#ab0f6b1e phone_call:PhoneCall = Update;
|
||||
updateLangPackTooLong#10c2404b = Update;
|
||||
updateLangPack#56022f4d difference:LangPackDifference = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@@ -442,11 +447,11 @@ photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> =
|
||||
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
|
||||
|
||||
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
|
||||
upload.fileCdnRedirect#1508485a dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes = upload.File;
|
||||
upload.fileCdnRedirect#ea52fe5a dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes cdn_file_hashes:Vector<CdnFileHash> = upload.File;
|
||||
|
||||
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true id:int ip_address:string port:int = DcOption;
|
||||
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int = DcOption;
|
||||
|
||||
config#cb601684 flags:# phonecalls_enabled:flags.1?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string disabled_features:Vector<DisabledFeature> = Config;
|
||||
config#7feec888 flags:# phonecalls_enabled:flags.1?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int disabled_features:Vector<DisabledFeature> = Config;
|
||||
|
||||
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
|
||||
|
||||
@@ -644,19 +649,16 @@ channelMessagesFilter#cd77d957 flags:# exclude_new_messages:flags.1?true ranges:
|
||||
|
||||
channelParticipant#15ebac1d user_id:int date:int = ChannelParticipant;
|
||||
channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelParticipant;
|
||||
channelParticipantModerator#91057fef user_id:int inviter_id:int date:int = ChannelParticipant;
|
||||
channelParticipantEditor#98192d61 user_id:int inviter_id:int date:int = ChannelParticipant;
|
||||
channelParticipantKicked#8cc5e69a user_id:int kicked_by:int date:int = ChannelParticipant;
|
||||
channelParticipantCreator#e3e2e1f9 user_id:int = ChannelParticipant;
|
||||
channelParticipantAdmin#a82fa898 flags:# can_edit:flags.0?true user_id:int inviter_id:int promoted_by:int date:int admin_rights:ChannelAdminRights = ChannelParticipant;
|
||||
channelParticipantBanned#222c1886 flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChannelBannedRights = ChannelParticipant;
|
||||
|
||||
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
|
||||
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
|
||||
channelParticipantsKicked#3c37bb7a = ChannelParticipantsFilter;
|
||||
channelParticipantsKicked#a3b54985 q:string = ChannelParticipantsFilter;
|
||||
channelParticipantsBots#b0d1865b = ChannelParticipantsFilter;
|
||||
|
||||
channelRoleEmpty#b285a0c6 = ChannelParticipantRole;
|
||||
channelRoleModerator#9618d975 = ChannelParticipantRole;
|
||||
channelRoleEditor#820bfe8c = ChannelParticipantRole;
|
||||
channelParticipantsBanned#1427a5e1 q:string = ChannelParticipantsFilter;
|
||||
channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter;
|
||||
|
||||
channels.channelParticipants#f56ee2a8 count:int participants:Vector<ChannelParticipant> users:Vector<User> = channels.ChannelParticipants;
|
||||
|
||||
@@ -697,7 +699,7 @@ messages.botResults#ccd3563d flags:# gallery:flags.0?true query_id:long next_off
|
||||
|
||||
exportedMessageLink#1f486803 link:string = ExportedMessageLink;
|
||||
|
||||
messageFwdHeader#c786ddcb flags:# from_id:flags.0?int date:int channel_id:flags.1?int channel_post:flags.2?int = MessageFwdHeader;
|
||||
messageFwdHeader#fadff4ac flags:# from_id:flags.0?int date:int channel_id:flags.1?int channel_post:flags.2?int post_author:flags.3?string = MessageFwdHeader;
|
||||
|
||||
auth.codeTypeSms#72a3158c = auth.CodeType;
|
||||
auth.codeTypeCall#741cd3e3 = auth.CodeType;
|
||||
@@ -725,6 +727,7 @@ topPeerCategoryBotsInline#148677e2 = TopPeerCategory;
|
||||
topPeerCategoryCorrespondents#637b7ed = TopPeerCategory;
|
||||
topPeerCategoryGroups#bd17a14a = TopPeerCategory;
|
||||
topPeerCategoryChannels#161d9628 = TopPeerCategory;
|
||||
topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
|
||||
|
||||
topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;
|
||||
|
||||
@@ -795,9 +798,10 @@ pageBlockEmbedPost#292c7be9 url:string webpage_id:long author_photo_id:long auth
|
||||
pageBlockCollage#8b31c4f items:Vector<PageBlock> caption:RichText = PageBlock;
|
||||
pageBlockSlideshow#130c8963 items:Vector<PageBlock> caption:RichText = PageBlock;
|
||||
pageBlockChannel#ef1751b5 channel:Chat = PageBlock;
|
||||
pageBlockAudio#31b81a7f audio_id:long caption:RichText = PageBlock;
|
||||
|
||||
pagePart#8dee6c44 blocks:Vector<PageBlock> photos:Vector<Photo> videos:Vector<Document> = Page;
|
||||
pageFull#d7a19d69 blocks:Vector<PageBlock> photos:Vector<Photo> videos:Vector<Document> = Page;
|
||||
pagePart#8e3f9ebe blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
|
||||
pageFull#556ec7aa blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
|
||||
|
||||
phoneCallDiscardReasonMissed#85e42301 = PhoneCallDiscardReason;
|
||||
phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason;
|
||||
@@ -844,6 +848,8 @@ account.tmpPassword#db64fd34 tmp_password:bytes valid_until:int = account.TmpPas
|
||||
|
||||
shippingOption#b6213cdf id:string title:string prices:Vector<LabeledPrice> = ShippingOption;
|
||||
|
||||
inputStickerSetItem#ffa0a496 flags:# document:InputDocument emoji:string mask_coords:flags.0?MaskCoords = InputStickerSetItem;
|
||||
|
||||
inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall;
|
||||
|
||||
phoneCallEmpty#5366c915 id:long = PhoneCall;
|
||||
@@ -866,11 +872,48 @@ cdnPublicKey#c982eaba dc_id:int public_key:string = CdnPublicKey;
|
||||
|
||||
cdnConfig#5725e40a public_keys:Vector<CdnPublicKey> = CdnConfig;
|
||||
|
||||
langPackString#cad181f6 key:string value:string = LangPackString;
|
||||
langPackStringPluralized#6c47ac9f flags:# key:string zero_value:flags.0?string one_value:flags.1?string two_value:flags.2?string few_value:flags.3?string many_value:flags.4?string other_value:string = LangPackString;
|
||||
langPackStringDeleted#2979eeb2 key:string = LangPackString;
|
||||
|
||||
langPackDifference#f385c1f6 lang_code:string from_version:int version:int strings:Vector<LangPackString> = LangPackDifference;
|
||||
|
||||
langPackLanguage#117698f1 name:string native_name:string lang_code:string = LangPackLanguage;
|
||||
|
||||
channelAdminRights#5d7ceba5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true invite_link:flags.6?true pin_messages:flags.7?true add_admins:flags.9?true = ChannelAdminRights;
|
||||
|
||||
channelBannedRights#58cf4249 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true until_date:int = ChannelBannedRights;
|
||||
|
||||
channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionChangePhoto#b82f55c3 prev_photo:ChatPhoto new_photo:ChatPhoto = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionToggleInvites#1b7907ae new_value:Bool = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionToggleSignatures#26ae0971 new_value:Bool = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionUpdatePinned#e9e82c18 message:Message = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionEditMessage#709b2405 prev_message:Message new_message:Message = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionDeleteMessage#42e047bb message:Message = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionParticipantJoin#183040d3 = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionParticipantLeave#f89777f2 = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionParticipantInvite#e31c34d8 participant:ChannelParticipant = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionParticipantToggleBan#e6d83d7e prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionParticipantToggleAdmin#d5676710 prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction;
|
||||
|
||||
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
||||
|
||||
channels.adminLogResults#ed8af74d events:Vector<ChannelAdminLogEvent> chats:Vector<Chat> users:Vector<User> = channels.AdminLogResults;
|
||||
|
||||
channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?true invite:flags.2?true ban:flags.3?true unban:flags.4?true kick:flags.5?true unkick:flags.6?true promote:flags.7?true demote:flags.8?true info:flags.9?true settings:flags.10?true pinned:flags.11?true edit:flags.12?true delete:flags.13?true = ChannelAdminLogEventsFilter;
|
||||
|
||||
popularContact#5ce14175 client_id:long importers:int = PopularContact;
|
||||
|
||||
cdnFileHash#77eec38f offset:int limit:int hash:bytes = CdnFileHash;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
|
||||
initConnection#69796de9 {X:Type} api_id:int device_model:string system_version:string app_version:string lang_code:string query:!X = X;
|
||||
initConnection#c7481da6 {X:Type} api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string query:!X = X;
|
||||
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
|
||||
invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
|
||||
|
||||
@@ -935,13 +978,13 @@ contacts.exportCard#84e53737 = Vector<int>;
|
||||
contacts.importCard#4fe196fe export_card:Vector<int> = User;
|
||||
contacts.search#11f812d8 q:string limit:int = contacts.Found;
|
||||
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
|
||||
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
|
||||
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
|
||||
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
|
||||
|
||||
messages.getMessages#4222fa74 id:Vector<int> = messages.Messages;
|
||||
messages.getDialogs#191ba9c5 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs;
|
||||
messages.getHistory#afa92846 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.search#d4569248 flags:# peer:InputPeer q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages;
|
||||
messages.search#f288a275 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages;
|
||||
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
||||
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true peer:InputPeer max_id:int = messages.AffectedHistory;
|
||||
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
|
||||
@@ -1023,6 +1066,8 @@ messages.reorderPinnedDialogs#959ff644 flags:# force:flags.0?true order:Vector<I
|
||||
messages.getPinnedDialogs#e254d64e = messages.PeerDialogs;
|
||||
messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
|
||||
messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
|
||||
messages.uploadMedia#519bc2b1 peer:InputPeer media:InputMedia = MessageMedia;
|
||||
messages.sendScreenshotNotification#c97df020 peer:InputPeer reply_to_msg_id:int random_id:long = Updates;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||
@@ -1038,7 +1083,8 @@ upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload
|
||||
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
|
||||
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
|
||||
upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile;
|
||||
upload.reuploadCdnFile#2e7a2020 file_token:bytes request_token:bytes = Bool;
|
||||
upload.reuploadCdnFile#1af91c09 file_token:bytes request_token:bytes = Vector<CdnFileHash>;
|
||||
upload.getCdnFileHashes#f715c87b file_token:bytes offset:int = Vector<CdnFileHash>;
|
||||
|
||||
help.getConfig#c4f9186b = Config;
|
||||
help.getNearestDc#1fb33026 = NearestDc;
|
||||
@@ -1062,7 +1108,7 @@ channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
|
||||
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
|
||||
channels.createChannel#f4893d7f flags:# broadcast:flags.0?true megagroup:flags.1?true title:string about:string = Updates;
|
||||
channels.editAbout#13e27f1e channel:InputChannel about:string = Bool;
|
||||
channels.editAdmin#eb7611d0 channel:InputChannel user_id:InputUser role:ChannelParticipantRole = Updates;
|
||||
channels.editAdmin#20b88214 channel:InputChannel user_id:InputUser admin_rights:ChannelAdminRights = Updates;
|
||||
channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
|
||||
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
|
||||
channels.checkUsername#10e6bd2c channel:InputChannel username:string = Bool;
|
||||
@@ -1070,7 +1116,6 @@ channels.updateUsername#3514b3de channel:InputChannel username:string = Bool;
|
||||
channels.joinChannel#24b524c5 channel:InputChannel = Updates;
|
||||
channels.leaveChannel#f836aa95 channel:InputChannel = Updates;
|
||||
channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector<InputUser> = Updates;
|
||||
channels.kickFromChannel#a672de14 channel:InputChannel user_id:InputUser kicked:Bool = Updates;
|
||||
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
|
||||
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
||||
channels.toggleInvites#49609307 channel:InputChannel enabled:Bool = Updates;
|
||||
@@ -1078,6 +1123,8 @@ channels.exportMessageLink#c846d22d channel:InputChannel id:int = ExportedMessag
|
||||
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates;
|
||||
channels.getAdminedPublicChannels#8d8d82d7 = messages.Chats;
|
||||
channels.editBanned#bfd915cd channel:InputChannel user_id:InputUser banned_rights:ChannelBannedRights = Updates;
|
||||
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
||||
|
||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||
@@ -1089,6 +1136,11 @@ payments.sendPaymentForm#2b8879b3 flags:# msg_id:int requested_info_id:flags.0?s
|
||||
payments.getSavedInfo#227d824b = payments.SavedInfo;
|
||||
payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
|
||||
|
||||
stickers.createStickerSet#9bd86e6a flags:# masks:flags.0?true user_id:InputUser title:string short_name:string stickers:Vector<InputStickerSetItem> = messages.StickerSet;
|
||||
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
|
||||
stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = messages.StickerSet;
|
||||
stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
|
||||
|
||||
phone.getCallConfig#55451fa9 = DataJSON;
|
||||
phone.requestCall#5b95b3d4 user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||
phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||
@@ -1098,4 +1150,9 @@ phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDisc
|
||||
phone.setCallRating#1c536a34 peer:InputPhoneCall rating:int comment:string = Updates;
|
||||
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
||||
|
||||
// LAYER 66
|
||||
langpack.getLangPack#9ab5c58e lang_code:string = LangPackDifference;
|
||||
langpack.getStrings#2e1ee318 lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
||||
langpack.getDifference#b2e4d7d from_version:int = LangPackDifference;
|
||||
langpack.getLanguages#800fd57d = Vector<LangPackLanguage>;
|
||||
|
||||
// LAYER 70
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="1.1.7.0" />
|
||||
Version="1.1.17.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
||||
@@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,7,0
|
||||
PRODUCTVERSION 1,1,7,0
|
||||
FILEVERSION 1,1,17,0
|
||||
PRODUCTVERSION 1,1,17,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -52,10 +52,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "1.1.7.0"
|
||||
VALUE "FileVersion", "1.1.17.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "1.1.7.0"
|
||||
VALUE "ProductVersion", "1.1.17.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,7,0
|
||||
PRODUCTVERSION 1,1,7,0
|
||||
FILEVERSION 1,1,17,0
|
||||
PRODUCTVERSION 1,1,17,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -43,10 +43,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "1.1.7.0"
|
||||
VALUE "FileVersion", "1.1.17.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "1.1.7.0"
|
||||
VALUE "ProductVersion", "1.1.17.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -22,12 +22,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "data/data_drafts.h"
|
||||
#include "observer_peer.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "application.h"
|
||||
#include "mainwindow.h"
|
||||
#include "messenger.h"
|
||||
#include "mainwidget.h"
|
||||
#include "historywidget.h"
|
||||
#include "history/history_widget.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "auth_session.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
@@ -44,11 +44,75 @@ constexpr auto kSmallDelayMs = 5;
|
||||
|
||||
} // namespace
|
||||
|
||||
ApiWrap::ApiWrap()
|
||||
: _messageDataResolveDelayed([this] { resolveMessageDatas(); })
|
||||
ApiWrap::ApiWrap(gsl::not_null<AuthSession*> session)
|
||||
: _session(session)
|
||||
, _messageDataResolveDelayed([this] { resolveMessageDatas(); })
|
||||
, _webPagesTimer([this] { resolveWebPages(); })
|
||||
, _draftsSaveTimer([this] { saveDraftsToCloud(); }) {
|
||||
}
|
||||
|
||||
void ApiWrap::start() {
|
||||
Window::Theme::Background()->start();
|
||||
requestAppChangelogs();
|
||||
}
|
||||
|
||||
void ApiWrap::requestAppChangelogs() {
|
||||
auto oldAppVersion = Local::oldMapVersion();
|
||||
if (oldAppVersion > 0 && oldAppVersion < AppVersion) {
|
||||
_changelogSubscription = subscribe(_session->data().moreChatsLoaded(), [this, oldAppVersion] {
|
||||
auto oldVersionString = qsl("%1.%2.%3").arg(oldAppVersion / 1000000).arg((oldAppVersion % 1000000) / 1000).arg(oldAppVersion % 1000);
|
||||
request(MTPhelp_GetAppChangelog(MTP_string(oldVersionString))).done([this, oldAppVersion](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
|
||||
auto resultEmpty = true;
|
||||
switch (result.type()) {
|
||||
case mtpc_updateShortMessage:
|
||||
case mtpc_updateShortChatMessage:
|
||||
case mtpc_updateShort: resultEmpty = false; break;
|
||||
case mtpc_updatesCombined: resultEmpty = result.c_updatesCombined().vupdates.v.isEmpty(); break;
|
||||
case mtpc_updates: resultEmpty = result.c_updates().vupdates.v.isEmpty(); break;
|
||||
case mtpc_updatesTooLong:
|
||||
case mtpc_updateShortSentMessage: LOG(("API Error: Bad updates type in app changelog.")); break;
|
||||
}
|
||||
if (resultEmpty) {
|
||||
addLocalChangelogs(oldAppVersion);
|
||||
}
|
||||
}).send();
|
||||
unsubscribe(base::take(_changelogSubscription));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::addLocalChangelogs(int oldAppVersion) {
|
||||
auto addedSome = false;
|
||||
auto addLocalChangelog = [this, &addedSome](const QString &text) {
|
||||
auto textWithEntities = TextWithEntities { text };
|
||||
TextUtilities::ParseEntities(textWithEntities, TextParseLinks);
|
||||
App::wnd()->serviceNotification(textWithEntities, MTP_messageMediaEmpty(), unixtime());
|
||||
addedSome = true;
|
||||
};
|
||||
if (cAlphaVersion() || cBetaVersion()) {
|
||||
auto addLocalAlphaChangelog = [this, oldAppVersion, addLocalChangelog](int changeVersion, const char *changes) {
|
||||
if (oldAppVersion < changeVersion) {
|
||||
auto changeVersionString = QString::number(changeVersion / 1000000) + '.' + QString::number((changeVersion % 1000000) / 1000) + ((changeVersion % 1000) ? ('.' + QString::number(changeVersion % 1000)) : QString());
|
||||
auto text = qsl("New in version %1:\n\n").arg(changeVersionString) + QString::fromUtf8(changes).trimmed();
|
||||
addLocalChangelog(text);
|
||||
}
|
||||
};
|
||||
addLocalAlphaChangelog(1001008, "\xE2\x80\x94 Toggle night mode in the main menu.\n");
|
||||
addLocalAlphaChangelog(1001010, "\xE2\x80\x94 Filter added to channel and supergroup event log.\n\xE2\x80\x94 Search by username in privacy exceptions editor fixed.\n\xE2\x80\x94 Adding admins in channels fixed.");
|
||||
addLocalAlphaChangelog(1001011, "\xE2\x80\x94 Send **bold** and __italic__ text in your messages (in addition to already supported `monospace` and ```multiline monospace```).\n\xE2\x80\x94 Search in channel and supergroup admin event log.\n\xE2\x80\x94 Ban members from right click menu in supergroup admin event log.");
|
||||
addLocalAlphaChangelog(1001012, "\xE2\x80\x94 Click on forwarded messages bar to change the recipient chat in case you chose a wrong one first.\n\xE2\x80\x94 Quickly share posts from channels and media messages from bots.\n\xE2\x80\x94 Search in large supergroup members by name.\n\xE2\x80\x94 Search in channel members by name if you're a channel admin.\n\xE2\x80\x94 Copy links to messages in public supergroups.");
|
||||
addLocalAlphaChangelog(1001014, "\xE2\x80\x94 Bug fixes and other minor improvements.");
|
||||
}
|
||||
if (!addedSome) {
|
||||
auto text = lng_new_version_wrap(lt_version, str_const_toString(AppVersionStr), lt_changes, lang(lng_new_version_minor), lt_link, qsl("https://desktop.telegram.org/changelog")).trimmed();
|
||||
addLocalChangelog(text);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId) {
|
||||
App::main()->feedUpdates(updates, sentMessageRandomId);
|
||||
}
|
||||
|
||||
void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback) {
|
||||
@@ -114,10 +178,6 @@ void ApiWrap::resolveMessageDatas() {
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::updatesReceived(const MTPUpdates &updates) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
|
||||
void ApiWrap::gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &msgs, mtpRequestId requestId) {
|
||||
switch (msgs.type()) {
|
||||
case mtpc_messages_messages: {
|
||||
@@ -204,9 +264,9 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
||||
auto &vc = d.vchats.v;
|
||||
auto badVersion = false;
|
||||
if (peer->isChat()) {
|
||||
badVersion = (!vc.isEmpty() && vc.at(0).type() == mtpc_chat && vc.at(0).c_chat().vversion.v < peer->asChat()->version);
|
||||
badVersion = (!vc.isEmpty() && vc[0].type() == mtpc_chat && vc[0].c_chat().vversion.v < peer->asChat()->version);
|
||||
} else if (peer->isChannel()) {
|
||||
badVersion = (!vc.isEmpty() && vc.at(0).type() == mtpc_channel && vc.at(0).c_channel().vversion.v < peer->asChannel()->version);
|
||||
badVersion = (!vc.isEmpty() && vc[0].type() == mtpc_channel && vc[0].c_channel().vversion.v < peer->asChannel()->version);
|
||||
}
|
||||
|
||||
App::feedUsers(d.vusers);
|
||||
@@ -239,6 +299,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
||||
chat->photoId = 0;
|
||||
}
|
||||
chat->setInviteLink((f.vexported_invite.type() == mtpc_chatInviteExported) ? qs(f.vexported_invite.c_chatInviteExported().vlink) : QString());
|
||||
chat->fullUpdated();
|
||||
|
||||
notifySettingReceived(MTP_inputNotifyPeer(peer->input), f.vnotify_settings);
|
||||
} else if (auto channel = peer->asChannel()) {
|
||||
@@ -303,6 +364,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
||||
channel->setAbout(qs(f.vabout));
|
||||
channel->setMembersCount(f.has_participants_count() ? f.vparticipants_count.v : 0);
|
||||
channel->setAdminsCount(f.has_admins_count() ? f.vadmins_count.v : 0);
|
||||
channel->setRestrictedCount(f.has_banned_count() ? f.vbanned_count.v : 0);
|
||||
channel->setKickedCount(f.has_kicked_count() ? f.vkicked_count.v : 0);
|
||||
channel->setInviteLink((f.vexported_invite.type() == mtpc_chatInviteExported) ? qs(f.vexported_invite.c_chatInviteExported().vlink) : QString());
|
||||
if (auto h = App::historyLoaded(channel->id)) {
|
||||
@@ -321,23 +383,23 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
||||
}
|
||||
channel->fullUpdated();
|
||||
|
||||
if (canViewAdmins != channel->canViewAdmins()) Notify::peerUpdatedDelayed(channel, Notify::PeerUpdate::Flag::ChannelCanViewAdmins);
|
||||
if (canViewMembers != channel->canViewMembers()) Notify::peerUpdatedDelayed(channel, Notify::PeerUpdate::Flag::ChannelCanViewMembers);
|
||||
if (canViewAdmins != channel->canViewAdmins()
|
||||
|| canViewMembers != channel->canViewMembers()) Notify::peerUpdatedDelayed(channel, Notify::PeerUpdate::Flag::ChannelRightsChanged);
|
||||
|
||||
notifySettingReceived(MTP_inputNotifyPeer(peer->input), f.vnotify_settings);
|
||||
}
|
||||
|
||||
if (req) {
|
||||
QMap<PeerData*, mtpRequestId>::iterator i = _fullPeerRequests.find(peer);
|
||||
auto i = _fullPeerRequests.find(peer);
|
||||
if (i != _fullPeerRequests.cend() && i.value() == req) {
|
||||
_fullPeerRequests.erase(i);
|
||||
}
|
||||
}
|
||||
if (badVersion) {
|
||||
if (peer->isChat()) {
|
||||
peer->asChat()->version = vc.at(0).c_chat().vversion.v;
|
||||
} else if (peer->isChannel()) {
|
||||
peer->asChannel()->version = vc.at(0).c_channel().vversion.v;
|
||||
if (auto chat = peer->asChat()) {
|
||||
chat->version = vc[0].c_chat().vversion.v;
|
||||
} else if (auto channel = peer->asChannel()) {
|
||||
channel->version = vc[0].c_channel().vversion.v;
|
||||
}
|
||||
requestPeer(peer);
|
||||
}
|
||||
@@ -365,6 +427,7 @@ void ApiWrap::gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestI
|
||||
user->setCallsStatus(d.is_phone_calls_private() ? UserData::CallsStatus::Private : d.is_phone_calls_available() ? UserData::CallsStatus::Enabled : UserData::CallsStatus::Disabled);
|
||||
user->setAbout(d.has_about() ? qs(d.vabout) : QString());
|
||||
user->setCommonChatsCount(d.vcommon_chats_count.v);
|
||||
user->fullUpdated();
|
||||
|
||||
if (req) {
|
||||
auto i = _fullPeerRequests.find(user);
|
||||
@@ -389,18 +452,18 @@ void ApiWrap::requestPeer(PeerData *peer) {
|
||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
||||
auto &v = chats->v;
|
||||
bool badVersion = false;
|
||||
if (peer->isChat()) {
|
||||
badVersion = (!v.isEmpty() && v.at(0).type() == mtpc_chat && v.at(0).c_chat().vversion.v < peer->asChat()->version);
|
||||
} else if (peer->isChannel()) {
|
||||
badVersion = (!v.isEmpty() && v.at(0).type() == mtpc_channel && v.at(0).c_chat().vversion.v < peer->asChannel()->version);
|
||||
if (auto chat = peer->asChat()) {
|
||||
badVersion = (!v.isEmpty() && v[0].type() == mtpc_chat && v[0].c_chat().vversion.v < chat->version);
|
||||
} else if (auto channel = peer->asChannel()) {
|
||||
badVersion = (!v.isEmpty() && v[0].type() == mtpc_channel && v[0].c_channel().vversion.v < channel->version);
|
||||
}
|
||||
auto chat = App::feedChats(*chats);
|
||||
if (chat == peer) {
|
||||
if (badVersion) {
|
||||
if (peer->isChat()) {
|
||||
peer->asChat()->version = v.at(0).c_chat().vversion.v;
|
||||
} else if (peer->isChannel()) {
|
||||
peer->asChannel()->version = v.at(0).c_channel().vversion.v;
|
||||
if (auto chat = peer->asChat()) {
|
||||
chat->version = v[0].c_chat().vversion.v;
|
||||
} else if (auto channel = peer->asChannel()) {
|
||||
channel->version = v[0].c_channel().vversion.v;
|
||||
}
|
||||
requestPeer(peer);
|
||||
}
|
||||
@@ -464,7 +527,7 @@ void ApiWrap::requestLastParticipants(ChannelData *channel, bool fromStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto needAdmins = channel->amEditor();
|
||||
auto needAdmins = channel->canViewAdmins();
|
||||
auto adminsOutdated = (channel->mgInfo->lastParticipantsStatus & MegagroupInfo::LastParticipantsAdminsOutdated) != 0;
|
||||
if ((needAdmins && adminsOutdated) || channel->lastParticipantsCountOutdated()) {
|
||||
fromStart = true;
|
||||
@@ -539,19 +602,36 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
|
||||
auto needBotsInfos = false;
|
||||
auto botStatus = peer->mgInfo->botStatus;
|
||||
auto keyboardBotFound = !h || !h->lastKeyboardFrom;
|
||||
auto emptyAdminRights = MTP_channelAdminRights(MTP_flags(0));
|
||||
auto emptyRestrictedRights = MTP_channelBannedRights(MTP_flags(0), MTP_int(0));
|
||||
for_const (auto &participant, v) {
|
||||
auto userId = UserId(0);
|
||||
bool admin = false;
|
||||
auto adminCanEdit = false;
|
||||
auto adminRights = emptyAdminRights;
|
||||
auto restrictedRights = emptyRestrictedRights;
|
||||
|
||||
switch (participant.type()) {
|
||||
case mtpc_channelParticipant: userId = participant.c_channelParticipant().vuser_id.v; break;
|
||||
case mtpc_channelParticipantSelf: userId = participant.c_channelParticipantSelf().vuser_id.v; break;
|
||||
case mtpc_channelParticipantModerator: userId = participant.c_channelParticipantModerator().vuser_id.v; break;
|
||||
case mtpc_channelParticipantEditor: userId = participant.c_channelParticipantEditor().vuser_id.v; admin = true; break;
|
||||
case mtpc_channelParticipantKicked: userId = participant.c_channelParticipantKicked().vuser_id.v; break;
|
||||
case mtpc_channelParticipantCreator: userId = participant.c_channelParticipantCreator().vuser_id.v; admin = true; break;
|
||||
case mtpc_channelParticipantAdmin:
|
||||
userId = participant.c_channelParticipantAdmin().vuser_id.v;
|
||||
adminCanEdit = participant.c_channelParticipantAdmin().is_can_edit();
|
||||
adminRights = participant.c_channelParticipantAdmin().vadmin_rights;
|
||||
break;
|
||||
case mtpc_channelParticipantBanned:
|
||||
userId = participant.c_channelParticipantBanned().vuser_id.v;
|
||||
restrictedRights = participant.c_channelParticipantBanned().vbanned_rights;
|
||||
break;
|
||||
case mtpc_channelParticipantCreator: userId = participant.c_channelParticipantCreator().vuser_id.v; break;
|
||||
}
|
||||
if (!userId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto u = App::user(userId);
|
||||
if (participant.type() == mtpc_channelParticipantCreator) {
|
||||
peer->mgInfo->creator = u;
|
||||
}
|
||||
if (bots) {
|
||||
if (u->botInfo) {
|
||||
peer->mgInfo->bots.insert(u);
|
||||
@@ -566,7 +646,11 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
|
||||
} else {
|
||||
if (peer->mgInfo->lastParticipants.indexOf(u) < 0) {
|
||||
peer->mgInfo->lastParticipants.push_back(u);
|
||||
if (admin) peer->mgInfo->lastAdmins.insert(u);
|
||||
if (adminRights.c_channelAdminRights().vflags.v) {
|
||||
peer->mgInfo->lastAdmins.insert(u, MegagroupInfo::Admin { adminRights, adminCanEdit });
|
||||
} else if (restrictedRights.c_channelBannedRights().vflags.v != 0) {
|
||||
peer->mgInfo->lastRestricted.insert(u, MegagroupInfo::Restricted { restrictedRights });
|
||||
}
|
||||
if (u->botInfo) {
|
||||
peer->mgInfo->bots.insert(u);
|
||||
if (peer->mgInfo->botStatus != 0 && peer->mgInfo->botStatus < 2) {
|
||||
@@ -625,20 +709,17 @@ void ApiWrap::requestSelfParticipant(ChannelData *channel) {
|
||||
} break;
|
||||
case mtpc_channelParticipantCreator: {
|
||||
auto &d = p.vparticipant.c_channelParticipantCreator();
|
||||
channel->inviter = AuthSession::CurrentUserId();
|
||||
channel->inviter = _session->userId();
|
||||
channel->inviteDate = date(MTP_int(channel->date));
|
||||
if (channel->mgInfo) {
|
||||
channel->mgInfo->creator = App::self();
|
||||
}
|
||||
} break;
|
||||
case mtpc_channelParticipantModerator: {
|
||||
auto &d = p.vparticipant.c_channelParticipantModerator();
|
||||
case mtpc_channelParticipantAdmin: {
|
||||
auto &d = p.vparticipant.c_channelParticipantAdmin();
|
||||
channel->inviter = d.vinviter_id.v;
|
||||
channel->inviteDate = date(d.vdate);
|
||||
} break;
|
||||
case mtpc_channelParticipantEditor: {
|
||||
auto &d = p.vparticipant.c_channelParticipantEditor();
|
||||
channel->inviter = d.vinviter_id.v;
|
||||
channel->inviteDate = date(d.vdate);
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
if (App::main()) App::main()->onSelfParticipantUpdated(channel);
|
||||
@@ -652,44 +733,17 @@ void ApiWrap::requestSelfParticipant(ChannelData *channel) {
|
||||
_selfParticipantRequests.insert(channel, requestId);
|
||||
}
|
||||
|
||||
void ApiWrap::kickParticipant(PeerData *peer, UserData *user) {
|
||||
void ApiWrap::kickParticipant(PeerData *peer, UserData *user, const MTPChannelBannedRights ¤tRights) {
|
||||
auto kick = KickRequest(peer, user);
|
||||
if (_kickRequests.contains(kick)) return;
|
||||
|
||||
if (auto channel = peer->asChannel()) {
|
||||
auto requestId = request(MTPchannels_KickFromChannel(channel->inputChannel, user->inputUser, MTP_bool(true))).done([this, peer, user](const MTPUpdates &result) {
|
||||
App::main()->sentUpdatesReceived(result);
|
||||
auto rights = ChannelData::KickedRestrictedRights();
|
||||
auto requestId = request(MTPchannels_EditBanned(channel->inputChannel, user->inputUser, rights)).done([this, channel, user, currentRights, rights](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
|
||||
_kickRequests.remove(KickRequest(peer, user));
|
||||
if (auto channel = peer->asMegagroup()) {
|
||||
auto megagroupInfo = channel->mgInfo;
|
||||
|
||||
auto i = megagroupInfo->lastParticipants.indexOf(user);
|
||||
if (i >= 0) {
|
||||
megagroupInfo->lastParticipants.removeAt(i);
|
||||
}
|
||||
|
||||
if (channel->membersCount() > 1) {
|
||||
channel->setMembersCount(channel->membersCount() - 1);
|
||||
} else {
|
||||
megagroupInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated;
|
||||
megagroupInfo->lastParticipantsCount = 0;
|
||||
}
|
||||
channel->setKickedCount(channel->kickedCount() + 1);
|
||||
if (megagroupInfo->lastAdmins.contains(user)) {
|
||||
megagroupInfo->lastAdmins.remove(user);
|
||||
if (channel->adminsCount() > 1) {
|
||||
channel->setAdminsCount(channel->adminsCount() - 1);
|
||||
}
|
||||
Notify::peerUpdatedDelayed(channel, Notify::PeerUpdate::Flag::AdminsChanged);
|
||||
}
|
||||
megagroupInfo->bots.remove(user);
|
||||
if (megagroupInfo->bots.isEmpty() && megagroupInfo->botStatus > 0) {
|
||||
megagroupInfo->botStatus = -1;
|
||||
}
|
||||
}
|
||||
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
||||
fullPeerUpdated().notify(peer);
|
||||
_kickRequests.remove(KickRequest(channel, user));
|
||||
channel->applyEditBanned(user, currentRights, rights);
|
||||
}).fail([this, kick](const RPCError &error) {
|
||||
_kickRequests.remove(kick);
|
||||
}).send();
|
||||
@@ -703,15 +757,15 @@ void ApiWrap::unblockParticipant(PeerData *peer, UserData *user) {
|
||||
if (_kickRequests.contains(kick)) return;
|
||||
|
||||
if (auto channel = peer->asChannel()) {
|
||||
auto requestId = request(MTPchannels_KickFromChannel(channel->inputChannel, user->inputUser, MTP_bool(false))).done([this, peer, user](const MTPUpdates &result) {
|
||||
App::main()->sentUpdatesReceived(result);
|
||||
auto requestId = request(MTPchannels_EditBanned(channel->inputChannel, user->inputUser, MTP_channelBannedRights(MTP_flags(0), MTP_int(0)))).done([this, peer, user](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
|
||||
_kickRequests.remove(KickRequest(peer, user));
|
||||
if (auto channel = peer->asMegagroup()) {
|
||||
if (channel->kickedCount() > 0) {
|
||||
channel->setKickedCount(channel->kickedCount() - 1);
|
||||
} else {
|
||||
channel->updateFull(true);
|
||||
channel->updateFullForced();
|
||||
}
|
||||
}
|
||||
}).fail([this, kick](const RPCError &error) {
|
||||
@@ -877,7 +931,7 @@ void ApiWrap::joinChannel(ChannelData *channel) {
|
||||
} else if (!_channelAmInRequests.contains(channel)) {
|
||||
auto requestId = request(MTPchannels_JoinChannel(channel->inputChannel)).done([this, channel](const MTPUpdates &result) {
|
||||
_channelAmInRequests.remove(channel);
|
||||
updatesReceived(result);
|
||||
applyUpdates(result);
|
||||
}).fail([this, channel](const RPCError &error) {
|
||||
if (error.type() == qstr("CHANNELS_TOO_MUCH")) {
|
||||
Ui::show(Box<InformBox>(lang(lng_join_channel_error)));
|
||||
@@ -895,7 +949,7 @@ void ApiWrap::leaveChannel(ChannelData *channel) {
|
||||
} else if (!_channelAmInRequests.contains(channel)) {
|
||||
auto requestId = request(MTPchannels_LeaveChannel(channel->inputChannel)).done([this, channel](const MTPUpdates &result) {
|
||||
_channelAmInRequests.remove(channel);
|
||||
updatesReceived(result);
|
||||
applyUpdates(result);
|
||||
}).fail([this, channel](const RPCError &error) {
|
||||
_channelAmInRequests.remove(channel);
|
||||
}).send();
|
||||
@@ -1128,7 +1182,7 @@ void ApiWrap::saveDraftsToCloud() {
|
||||
if (!textWithTags.tags.isEmpty()) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_entities;
|
||||
}
|
||||
auto entities = linksToMTP(ConvertTextTagsToEntities(textWithTags.tags), true);
|
||||
auto entities = TextUtilities::EntitiesToMTP(ConvertTextTagsToEntities(textWithTags.tags), TextUtilities::ConvertOption::SkipLocal);
|
||||
|
||||
cloudDraft->saveRequestId = request(MTPmessages_SaveDraft(MTP_flags(flags), MTP_int(cloudDraft->msgId), history->peer->input, MTP_string(textWithTags.text), entities)).done([this, history](const MTPBool &result, mtpRequestId requestId) {
|
||||
if (auto cloudDraft = history->cloudDraft()) {
|
||||
@@ -1197,7 +1251,7 @@ PeerData *ApiWrap::notifySettingReceived(MTPInputNotifyPeer notifyPeer, const MT
|
||||
}
|
||||
} break;
|
||||
}
|
||||
AuthSession::Current().notifications().checkDelayed();
|
||||
_session->notifications().checkDelayed();
|
||||
return requestedPeer;
|
||||
}
|
||||
|
||||
@@ -1391,7 +1445,7 @@ void ApiWrap::resolveWebPages() {
|
||||
|
||||
void ApiWrap::requestParticipantsCountDelayed(ChannelData *channel) {
|
||||
_participantsCountRequestTimer.call(kReloadChannelMembersTimeout, [this, channel] {
|
||||
channel->updateFull(true);
|
||||
channel->updateFullForced();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1479,4 +1533,121 @@ void ApiWrap::stickersSaveOrder() {
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
|
||||
switch (updates.type()) {
|
||||
case mtpc_updateShortMessage: {
|
||||
auto &d = updates.c_updateShortMessage();
|
||||
auto flags = mtpCastFlags(d.vflags.v) | MTPDmessage::Flag::f_from_id;
|
||||
App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.is_out() ? MTP_int(AuthSession::CurrentUserId()) : d.vuser_id, MTP_peerUser(d.is_out() ? d.vuser_id : MTP_int(AuthSession::CurrentUserId())), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint(), MTPstring()), NewMessageUnread);
|
||||
} break;
|
||||
|
||||
case mtpc_updateShortChatMessage: {
|
||||
auto &d = updates.c_updateShortChatMessage();
|
||||
auto flags = mtpCastFlags(d.vflags.v) | MTPDmessage::Flag::f_from_id;
|
||||
App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint(), MTPstring()), NewMessageUnread);
|
||||
} break;
|
||||
|
||||
case mtpc_updateShortSentMessage: {
|
||||
auto &d = updates.c_updateShortSentMessage();
|
||||
Q_UNUSED(d); // Sent message data was applied anyway.
|
||||
} break;
|
||||
|
||||
default: Unexpected("Type in applyUpdatesNoPtsCheck()");
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
||||
switch (update.type()) {
|
||||
case mtpc_updateNewMessage: {
|
||||
auto &d = update.c_updateNewMessage();
|
||||
auto needToAdd = true;
|
||||
if (d.vmessage.type() == mtpc_message) { // index forwarded messages to links _overview
|
||||
if (App::checkEntitiesAndViewsUpdate(d.vmessage.c_message())) { // already in blocks
|
||||
LOG(("Skipping message, because it is already in blocks!"));
|
||||
needToAdd = false;
|
||||
}
|
||||
}
|
||||
if (needToAdd) {
|
||||
App::histories().addNewMessage(d.vmessage, NewMessageUnread);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateReadMessagesContents: {
|
||||
auto &d = update.c_updateReadMessagesContents();
|
||||
auto &v = d.vmessages.v;
|
||||
for (auto i = 0, l = v.size(); i < l; ++i) {
|
||||
if (auto item = App::histItemById(NoChannel, v.at(i).v)) {
|
||||
if (item->isMediaUnread()) {
|
||||
item->markMediaRead();
|
||||
Ui::repaintHistoryItem(item);
|
||||
|
||||
if (item->out() && item->history()->peer->isUser()) {
|
||||
auto when = App::main()->requestingDifference() ? 0 : unixtime();
|
||||
item->history()->peer->asUser()->madeAction(when);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateReadHistoryInbox: {
|
||||
auto &d = update.c_updateReadHistoryInbox();
|
||||
App::feedInboxRead(peerFromMTP(d.vpeer), d.vmax_id.v);
|
||||
} break;
|
||||
|
||||
case mtpc_updateReadHistoryOutbox: {
|
||||
auto &d = update.c_updateReadHistoryOutbox();
|
||||
auto peerId = peerFromMTP(d.vpeer);
|
||||
auto when = App::main()->requestingDifference() ? 0 : unixtime();
|
||||
App::feedOutboxRead(peerId, d.vmax_id.v, when);
|
||||
} break;
|
||||
|
||||
case mtpc_updateWebPage: {
|
||||
auto &d = update.c_updateWebPage();
|
||||
Q_UNUSED(d); // Web page was updated anyway.
|
||||
} break;
|
||||
|
||||
case mtpc_updateDeleteMessages: {
|
||||
auto &d = update.c_updateDeleteMessages();
|
||||
App::feedWereDeleted(NoChannel, d.vmessages.v);
|
||||
} break;
|
||||
|
||||
case mtpc_updateNewChannelMessage: {
|
||||
auto &d = update.c_updateNewChannelMessage();
|
||||
auto needToAdd = true;
|
||||
if (d.vmessage.type() == mtpc_message) { // index forwarded messages to links _overview
|
||||
if (App::checkEntitiesAndViewsUpdate(d.vmessage.c_message())) { // already in blocks
|
||||
LOG(("Skipping message, because it is already in blocks!"));
|
||||
needToAdd = false;
|
||||
}
|
||||
}
|
||||
if (needToAdd) {
|
||||
App::histories().addNewMessage(d.vmessage, NewMessageUnread);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateEditChannelMessage: {
|
||||
auto &d = update.c_updateEditChannelMessage();
|
||||
App::updateEditedMessage(d.vmessage);
|
||||
} break;
|
||||
|
||||
case mtpc_updateEditMessage: {
|
||||
auto &d = update.c_updateEditMessage();
|
||||
App::updateEditedMessage(d.vmessage);
|
||||
} break;
|
||||
|
||||
case mtpc_updateChannelWebPage: {
|
||||
auto &d = update.c_updateChannelWebPage();
|
||||
Q_UNUSED(d); // Web page was updated anyway.
|
||||
} break;
|
||||
|
||||
case mtpc_updateDeleteChannelMessages: {
|
||||
auto &d = update.c_updateDeleteChannelMessages();
|
||||
App::feedWereDeleted(d.vchannel_id.v, d.vmessages.v);
|
||||
} break;
|
||||
|
||||
default: Unexpected("Type in applyUpdateNoPtsCheck()");
|
||||
}
|
||||
}
|
||||
|
||||
ApiWrap::~ApiWrap() = default;
|
||||
|
||||
@@ -24,6 +24,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "core/single_timer.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class AuthSession;
|
||||
|
||||
namespace Api {
|
||||
|
||||
inline const MTPVector<MTPChat> *getChatsFromMessagesChats(const MTPmessages_Chats &chats) {
|
||||
@@ -36,9 +38,12 @@ inline const MTPVector<MTPChat> *getChatsFromMessagesChats(const MTPmessages_Cha
|
||||
|
||||
} // namespace Api
|
||||
|
||||
class ApiWrap : private MTP::Sender {
|
||||
class ApiWrap : private MTP::Sender, private base::Subscriber {
|
||||
public:
|
||||
ApiWrap();
|
||||
ApiWrap(gsl::not_null<AuthSession*> session);
|
||||
|
||||
void start();
|
||||
void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0);
|
||||
|
||||
using RequestMessageDataCallback = base::lambda<void(ChannelData*, MsgId)>;
|
||||
void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback);
|
||||
@@ -54,7 +59,7 @@ public:
|
||||
void processFullPeer(UserData *user, const MTPUserFull &result);
|
||||
|
||||
void requestSelfParticipant(ChannelData *channel);
|
||||
void kickParticipant(PeerData *peer, UserData *user);
|
||||
void kickParticipant(PeerData *peer, UserData *user, const MTPChannelBannedRights ¤tRights);
|
||||
void unblockParticipant(PeerData *peer, UserData *user);
|
||||
|
||||
void requestWebPageDelayed(WebPageData *page);
|
||||
@@ -86,6 +91,9 @@ public:
|
||||
|
||||
bool isQuitPrevent();
|
||||
|
||||
void applyUpdatesNoPtsCheck(const MTPUpdates &updates);
|
||||
void applyUpdateNoPtsCheck(const MTPUpdate &update);
|
||||
|
||||
~ApiWrap();
|
||||
|
||||
private:
|
||||
@@ -96,6 +104,8 @@ private:
|
||||
};
|
||||
using MessageDataRequests = QMap<MsgId, MessageDataRequest>;
|
||||
|
||||
void requestAppChangelogs();
|
||||
void addLocalChangelogs(int oldAppVersion);
|
||||
void updatesReceived(const MTPUpdates &updates);
|
||||
void checkQuitPreventFinished();
|
||||
|
||||
@@ -119,6 +129,9 @@ private:
|
||||
void stickerSetDisenabled(mtpRequestId requestId);
|
||||
void stickersSaveOrder();
|
||||
|
||||
gsl::not_null<AuthSession*> _session;
|
||||
mtpRequestId _changelogSubscription = 0;
|
||||
|
||||
MessageDataRequests _messageDataRequests;
|
||||
QMap<ChannelData*, MessageDataRequests> _channelMessageDataRequests;
|
||||
SingleQueuedInvokation _messageDataResolveDelayed;
|
||||
|
||||
@@ -29,7 +29,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "data/data_abstract_structure.h"
|
||||
#include "history/history_service_layout.h"
|
||||
#include "history/history_location_manager.h"
|
||||
@@ -111,15 +111,12 @@ namespace {
|
||||
style::font monofont;
|
||||
|
||||
struct CornersPixmaps {
|
||||
CornersPixmaps() {
|
||||
memset(p, 0, sizeof(p));
|
||||
}
|
||||
QPixmap *p[4];
|
||||
QPixmap p[4];
|
||||
};
|
||||
CornersPixmaps corners[RoundCornersCount];
|
||||
QVector<CornersPixmaps> corners;
|
||||
using CornersMap = QMap<uint32, CornersPixmaps>;
|
||||
CornersMap cornersMap;
|
||||
QImage *cornersMaskLarge[4] = { nullptr }, *cornersMaskSmall[4] = { nullptr };
|
||||
QImage cornersMaskLarge[4], cornersMaskSmall[4];
|
||||
|
||||
using EmojiImagesMap = QMap<int, QPixmap>;
|
||||
EmojiImagesMap MainEmojiMap;
|
||||
@@ -459,11 +456,11 @@ namespace {
|
||||
// apply first_name and last_name from minimal user only if we don't have
|
||||
// local values for first name and last name already, otherwise skip
|
||||
bool noLocalName = data->firstName.isEmpty() && data->lastName.isEmpty();
|
||||
QString fname = (!minimal || noLocalName) ? (d.has_first_name() ? textOneLine(qs(d.vfirst_name)) : QString()) : data->firstName;
|
||||
QString lname = (!minimal || noLocalName) ? (d.has_last_name() ? textOneLine(qs(d.vlast_name)) : QString()) : data->lastName;
|
||||
QString fname = (!minimal || noLocalName) ? (d.has_first_name() ? TextUtilities::SingleLine(qs(d.vfirst_name)) : QString()) : data->firstName;
|
||||
QString lname = (!minimal || noLocalName) ? (d.has_last_name() ? TextUtilities::SingleLine(qs(d.vlast_name)) : QString()) : data->lastName;
|
||||
|
||||
QString phone = minimal ? data->phone() : (d.has_phone() ? qs(d.vphone) : QString());
|
||||
QString uname = minimal ? data->username : (d.has_username() ? textOneLine(qs(d.vusername)) : QString());
|
||||
QString uname = minimal ? data->username : (d.has_username() ? TextUtilities::SingleLine(qs(d.vusername)) : QString());
|
||||
|
||||
bool phoneChanged = (data->phone() != phone);
|
||||
if (phoneChanged) {
|
||||
@@ -640,7 +637,7 @@ namespace {
|
||||
cdata->flags = d.vflags.v;
|
||||
|
||||
cdata->count = d.vparticipants_count.v;
|
||||
cdata->isForbidden = false;
|
||||
cdata->setIsForbidden(false);
|
||||
if (canEdit != cdata->canEdit()) {
|
||||
update.flags |= UpdateFlag::ChatCanEdit;
|
||||
}
|
||||
@@ -659,13 +656,13 @@ namespace {
|
||||
cdata->count = -1;
|
||||
cdata->invalidateParticipants();
|
||||
cdata->flags = 0;
|
||||
cdata->isForbidden = true;
|
||||
cdata->setIsForbidden(true);
|
||||
if (canEdit != cdata->canEdit()) {
|
||||
update.flags |= UpdateFlag::ChatCanEdit;
|
||||
}
|
||||
} break;
|
||||
case mtpc_channel: {
|
||||
auto &d(chat.c_channel());
|
||||
auto &d = chat.c_channel();
|
||||
|
||||
auto peerId = peerFromChannel(d.vid.v);
|
||||
minimal = d.is_min();
|
||||
@@ -681,16 +678,24 @@ namespace {
|
||||
|
||||
auto cdata = data->asChannel();
|
||||
auto wasInChannel = cdata->amIn();
|
||||
auto canEditPhoto = cdata->canEditPhoto();
|
||||
auto canViewAdmins = cdata->canViewAdmins();
|
||||
auto canViewMembers = cdata->canViewMembers();
|
||||
auto canAddMembers = cdata->canAddMembers();
|
||||
auto wasEditor = cdata->amEditor();
|
||||
|
||||
if (minimal) {
|
||||
auto mask = MTPDchannel::Flag::f_broadcast | MTPDchannel::Flag::f_verified | MTPDchannel::Flag::f_megagroup | MTPDchannel::Flag::f_democracy;
|
||||
cdata->flags = (cdata->flags & ~mask) | (d.vflags.v & mask);
|
||||
} else {
|
||||
if (d.has_admin_rights()) {
|
||||
cdata->setAdminRights(d.vadmin_rights);
|
||||
} else if (cdata->hasAdminRights()) {
|
||||
cdata->setAdminRights(MTP_channelAdminRights(MTP_flags(0)));
|
||||
}
|
||||
if (d.has_banned_rights()) {
|
||||
cdata->setRestrictedRights(d.vbanned_rights);
|
||||
} else if (cdata->hasRestrictedRights()) {
|
||||
cdata->setRestrictedRights(MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
|
||||
}
|
||||
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
|
||||
cdata->access = d.vaccess_hash.v;
|
||||
cdata->date = d.vdate.v;
|
||||
@@ -706,21 +711,16 @@ namespace {
|
||||
}
|
||||
cdata->flagsUpdated();
|
||||
|
||||
QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString();
|
||||
QString uname = d.has_username() ? TextUtilities::SingleLine(qs(d.vusername)) : QString();
|
||||
cdata->setName(qs(d.vtitle), uname);
|
||||
|
||||
cdata->isForbidden = false;
|
||||
cdata->setIsForbidden(false);
|
||||
cdata->setPhoto(d.vphoto);
|
||||
|
||||
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
|
||||
if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto;
|
||||
if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins;
|
||||
if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers;
|
||||
if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers;
|
||||
if (wasEditor != cdata->amEditor()) {
|
||||
cdata->selfAdminUpdated();
|
||||
update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged);
|
||||
}
|
||||
if (canViewAdmins != cdata->canViewAdmins()
|
||||
|| canViewMembers != cdata->canViewMembers()
|
||||
|| canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelRightsChanged;
|
||||
} break;
|
||||
case mtpc_channelForbidden: {
|
||||
auto &d(chat.c_channelForbidden());
|
||||
@@ -731,11 +731,9 @@ namespace {
|
||||
|
||||
auto cdata = data->asChannel();
|
||||
auto wasInChannel = cdata->amIn();
|
||||
auto canEditPhoto = cdata->canEditPhoto();
|
||||
auto canViewAdmins = cdata->canViewAdmins();
|
||||
auto canViewMembers = cdata->canViewMembers();
|
||||
auto canAddMembers = cdata->canAddMembers();
|
||||
auto wasEditor = cdata->amEditor();
|
||||
|
||||
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
|
||||
|
||||
@@ -743,23 +741,25 @@ namespace {
|
||||
cdata->flags = (cdata->flags & ~mask) | (mtpCastFlags(d.vflags) & mask);
|
||||
cdata->flagsUpdated();
|
||||
|
||||
if (cdata->hasAdminRights()) {
|
||||
cdata->setAdminRights(MTP_channelAdminRights(MTP_flags(0)));
|
||||
}
|
||||
if (cdata->hasRestrictedRights()) {
|
||||
cdata->setRestrictedRights(MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
|
||||
}
|
||||
|
||||
cdata->setName(qs(d.vtitle), QString());
|
||||
|
||||
cdata->access = d.vaccess_hash.v;
|
||||
cdata->setPhoto(MTP_chatPhotoEmpty());
|
||||
cdata->date = 0;
|
||||
cdata->setMembersCount(0);
|
||||
cdata->isForbidden = true;
|
||||
cdata->setIsForbidden(true);
|
||||
|
||||
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
|
||||
if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto;
|
||||
if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins;
|
||||
if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers;
|
||||
if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers;
|
||||
if (wasEditor != cdata->amEditor()) {
|
||||
cdata->selfAdminUpdated();
|
||||
update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged);
|
||||
}
|
||||
if (canViewAdmins != cdata->canViewAdmins()
|
||||
|| canViewMembers != cdata->canViewMembers()
|
||||
|| canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelRightsChanged;
|
||||
} break;
|
||||
}
|
||||
if (!data) {
|
||||
@@ -812,10 +812,10 @@ namespace {
|
||||
auto &v = d.vparticipants.v;
|
||||
chat->count = v.size();
|
||||
int32 pversion = chat->participants.isEmpty() ? 1 : (chat->participants.begin().value() + 1);
|
||||
chat->invitedByMe = ChatData::InvitedByMe();
|
||||
chat->admins = ChatData::Admins();
|
||||
chat->invitedByMe.clear();
|
||||
chat->admins.clear();
|
||||
chat->flags &= ~MTPDchat::Flag::f_admin;
|
||||
for (QVector<MTPChatParticipant>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
|
||||
for (auto i = v.cbegin(), e = v.cend(); i != e; ++i) {
|
||||
int32 uid = 0, inviter = 0;
|
||||
switch (i->type()) {
|
||||
case mtpc_chatParticipantCreator: {
|
||||
@@ -857,7 +857,7 @@ namespace {
|
||||
History *h = App::historyLoaded(chat->id);
|
||||
bool found = !h || !h->lastKeyboardFrom;
|
||||
int32 botStatus = -1;
|
||||
for (ChatData::Participants::iterator i = chat->participants.begin(), e = chat->participants.end(); i != e;) {
|
||||
for (auto i = chat->participants.begin(), e = chat->participants.end(); i != e;) {
|
||||
if (i.value() < pversion) {
|
||||
i = chat->participants.erase(i);
|
||||
} else {
|
||||
@@ -963,7 +963,7 @@ namespace {
|
||||
chat->count--;
|
||||
}
|
||||
} else {
|
||||
ChatData::Participants::iterator i = chat->participants.find(user);
|
||||
auto i = chat->participants.find(user);
|
||||
if (i != chat->participants.end()) {
|
||||
chat->participants.erase(i);
|
||||
chat->count--;
|
||||
@@ -980,7 +980,7 @@ namespace {
|
||||
}
|
||||
if (chat->botStatus > 0 && user->botInfo) {
|
||||
int32 botStatus = -1;
|
||||
for (ChatData::Participants::const_iterator j = chat->participants.cbegin(), e = chat->participants.cend(); j != e; ++j) {
|
||||
for (auto j = chat->participants.cbegin(), e = chat->participants.cend(); j != e; ++j) {
|
||||
if (j.key()->botInfo) {
|
||||
if (true || botStatus > 0/* || !j.key()->botInfo->readsAllHistory*/) {
|
||||
botStatus = 2;
|
||||
@@ -1093,7 +1093,7 @@ namespace {
|
||||
}
|
||||
if (auto existing = App::histItemById(peerToChannel(peerId), m.vid.v)) {
|
||||
auto text = qs(m.vmessage);
|
||||
auto entities = m.has_entities() ? entitiesFromMTP(m.ventities.v) : EntitiesInText();
|
||||
auto entities = m.has_entities() ? TextUtilities::EntitiesFromMTP(m.ventities.v) : EntitiesInText();
|
||||
existing->setText({ text, entities });
|
||||
existing->updateMedia(m.has_media() ? (&m.vmedia) : nullptr);
|
||||
existing->updateReplyMarkup(m.has_reply_markup() ? (&m.vreply_markup) : nullptr);
|
||||
@@ -1331,7 +1331,7 @@ namespace {
|
||||
bool showPhone = !isServiceUser(user->id) && !user->isSelf() && !user->contact;
|
||||
bool showPhoneChanged = !isServiceUser(user->id) && !user->isSelf() && ((showPhone && !wasShowPhone) || (!showPhone && wasShowPhone));
|
||||
if (showPhoneChanged) {
|
||||
user->setName(textOneLine(user->firstName), textOneLine(user->lastName), showPhone ? App::formatPhone(user->phone()) : QString(), textOneLine(user->username));
|
||||
user->setName(TextUtilities::SingleLine(user->firstName), TextUtilities::SingleLine(user->lastName), showPhone ? App::formatPhone(user->phone()) : QString(), TextUtilities::SingleLine(user->username));
|
||||
}
|
||||
markPeerUpdated(user);
|
||||
}
|
||||
@@ -1494,11 +1494,18 @@ namespace {
|
||||
}
|
||||
|
||||
WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) {
|
||||
return App::webPageSet(webpage.vid.v, convert, webpage.has_type() ? qs(webpage.vtype) : qsl("article"), qs(webpage.vurl), qs(webpage.vdisplay_url), webpage.has_site_name() ? qs(webpage.vsite_name) : QString(), webpage.has_title() ? qs(webpage.vtitle) : QString(), webpage.has_description() ? qs(webpage.vdescription) : QString(), webpage.has_photo() ? App::feedPhoto(webpage.vphoto) : 0, webpage.has_document() ? App::feedDocument(webpage.vdocument) : 0, webpage.has_duration() ? webpage.vduration.v : 0, webpage.has_author() ? qs(webpage.vauthor) : QString(), 0);
|
||||
auto description = TextWithEntities { webpage.has_description() ? TextUtilities::Clean(qs(webpage.vdescription)) : QString() };
|
||||
auto siteName = webpage.has_site_name() ? qs(webpage.vsite_name) : QString();
|
||||
auto parseFlags = TextParseLinks | TextParseMultiline | TextParseRichText;
|
||||
if (siteName == qstr("Twitter") || siteName == qstr("Instagram")) {
|
||||
parseFlags |= TextParseHashtags | TextParseMentions;
|
||||
}
|
||||
TextUtilities::ParseEntities(description, parseFlags);
|
||||
return App::webPageSet(webpage.vid.v, convert, webpage.has_type() ? qs(webpage.vtype) : qsl("article"), qs(webpage.vurl), qs(webpage.vdisplay_url), siteName, webpage.has_title() ? qs(webpage.vtitle) : QString(), description, webpage.has_photo() ? App::feedPhoto(webpage.vphoto) : nullptr, webpage.has_document() ? App::feedDocument(webpage.vdocument) : nullptr, webpage.has_duration() ? webpage.vduration.v : 0, webpage.has_author() ? qs(webpage.vauthor) : QString(), 0);
|
||||
}
|
||||
|
||||
WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert) {
|
||||
return App::webPageSet(webpage.vid.v, convert, QString(), QString(), QString(), QString(), QString(), QString(), 0, 0, 0, QString(), webpage.vdate.v);
|
||||
return App::webPageSet(webpage.vid.v, convert, QString(), QString(), QString(), QString(), QString(), TextWithEntities(), nullptr, nullptr, 0, QString(), webpage.vdate.v);
|
||||
}
|
||||
|
||||
WebPageData *feedWebPage(const MTPWebPage &webpage) {
|
||||
@@ -1515,6 +1522,10 @@ namespace {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WebPageData *feedWebPage(WebPageId webPageId, const QString &siteName, const TextWithEntities &content) {
|
||||
return App::webPageSet(webPageId, nullptr, qsl("article"), QString(), QString(), siteName, QString(), content, nullptr, nullptr, 0, QString(), 0);
|
||||
}
|
||||
|
||||
GameData *feedGame(const MTPDgame &game, GameData *convert) {
|
||||
return App::gameSet(game.vid.v, convert, game.vaccess_hash.v, qs(game.vshort_name), qs(game.vtitle), qs(game.vdescription), App::feedPhoto(game.vphoto), game.has_document() ? App::feedDocument(game.vdocument) : nullptr);
|
||||
}
|
||||
@@ -1775,7 +1786,7 @@ namespace {
|
||||
return i.value();
|
||||
}
|
||||
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *document, int32 duration, const QString &author, int32 pendingTill) {
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *document, int32 duration, const QString &author, int32 pendingTill) {
|
||||
if (convert) {
|
||||
if (convert->id != webPage) {
|
||||
auto i = webPagesData.find(convert->id);
|
||||
@@ -1786,15 +1797,15 @@ namespace {
|
||||
}
|
||||
if ((convert->url.isEmpty() && !url.isEmpty()) || (convert->pendingTill && convert->pendingTill != pendingTill && pendingTill >= -1)) {
|
||||
convert->type = toWebPageType(type);
|
||||
convert->url = textClean(url);
|
||||
convert->displayUrl = textClean(displayUrl);
|
||||
convert->siteName = textClean(siteName);
|
||||
convert->title = textOneLine(textClean(title));
|
||||
convert->description = textClean(description);
|
||||
convert->url = TextUtilities::Clean(url);
|
||||
convert->displayUrl = TextUtilities::Clean(displayUrl);
|
||||
convert->siteName = TextUtilities::Clean(siteName);
|
||||
convert->title = TextUtilities::SingleLine(title);
|
||||
convert->description = description;
|
||||
convert->photo = photo;
|
||||
convert->document = document;
|
||||
convert->duration = duration;
|
||||
convert->author = textClean(author);
|
||||
convert->author = TextUtilities::Clean(author);
|
||||
if (convert->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(convert);
|
||||
convert->pendingTill = pendingTill;
|
||||
if (App::main()) App::main()->webPageUpdated(convert);
|
||||
@@ -1817,15 +1828,15 @@ namespace {
|
||||
if (result != convert) {
|
||||
if ((result->url.isEmpty() && !url.isEmpty()) || (result->pendingTill && result->pendingTill != pendingTill && pendingTill >= -1)) {
|
||||
result->type = toWebPageType(type);
|
||||
result->url = textClean(url);
|
||||
result->displayUrl = textClean(displayUrl);
|
||||
result->siteName = textClean(siteName);
|
||||
result->title = textOneLine(textClean(title));
|
||||
result->description = textClean(description);
|
||||
result->url = TextUtilities::Clean(url);
|
||||
result->displayUrl = TextUtilities::Clean(displayUrl);
|
||||
result->siteName = TextUtilities::Clean(siteName);
|
||||
result->title = TextUtilities::SingleLine(title);
|
||||
result->description = description;
|
||||
result->photo = photo;
|
||||
result->document = document;
|
||||
result->duration = duration;
|
||||
result->author = textClean(author);
|
||||
result->author = TextUtilities::Clean(author);
|
||||
if (result->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(result);
|
||||
result->pendingTill = pendingTill;
|
||||
if (App::main()) App::main()->webPageUpdated(result);
|
||||
@@ -1855,9 +1866,9 @@ namespace {
|
||||
}
|
||||
if (!convert->accessHash && accessHash) {
|
||||
convert->accessHash = accessHash;
|
||||
convert->shortName = textClean(shortName);
|
||||
convert->title = textOneLine(textClean(title));
|
||||
convert->description = textClean(description);
|
||||
convert->shortName = TextUtilities::Clean(shortName);
|
||||
convert->title = TextUtilities::SingleLine(title);
|
||||
convert->description = TextUtilities::Clean(description);
|
||||
convert->photo = photo;
|
||||
convert->document = document;
|
||||
if (App::main()) App::main()->gameUpdated(convert);
|
||||
@@ -1877,9 +1888,9 @@ namespace {
|
||||
if (result != convert) {
|
||||
if (!result->accessHash && accessHash) {
|
||||
result->accessHash = accessHash;
|
||||
result->shortName = textClean(shortName);
|
||||
result->title = textOneLine(textClean(title));
|
||||
result->description = textClean(description);
|
||||
result->shortName = TextUtilities::Clean(shortName);
|
||||
result->title = TextUtilities::SingleLine(title);
|
||||
result->description = TextUtilities::Clean(description);
|
||||
result->photo = photo;
|
||||
result->document = document;
|
||||
if (App::main()) App::main()->gameUpdated(result);
|
||||
@@ -2160,6 +2171,7 @@ namespace {
|
||||
}
|
||||
|
||||
void prepareCorners(RoundCorners index, int32 radius, const QBrush &brush, const style::color *shadow = nullptr, QImage *cors = nullptr) {
|
||||
Expects(::corners.size() > index);
|
||||
int32 r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor();
|
||||
QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4];
|
||||
{
|
||||
@@ -2184,8 +2196,8 @@ namespace {
|
||||
cors[3] = rect.copy(r * 2, r * 2, r, r + (shadow ? s : 0));
|
||||
if (index != SmallMaskCorners && index != LargeMaskCorners) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
::corners[index].p[i] = new QPixmap(pixmapFromImageInPlace(std::move(cors[i])));
|
||||
::corners[index].p[i]->setDevicePixelRatio(cRetinaFactor());
|
||||
::corners[index].p[i] = pixmapFromImageInPlace(std::move(cors[i]));
|
||||
::corners[index].p[i].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2207,18 +2219,21 @@ namespace {
|
||||
return MsgRadius;
|
||||
}
|
||||
|
||||
void createCorners() {
|
||||
void createMaskCorners() {
|
||||
QImage mask[4];
|
||||
prepareCorners(LargeMaskCorners, msgRadius(), QColor(255, 255, 255), nullptr, mask);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
::cornersMaskLarge[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
|
||||
::cornersMaskLarge[i]->setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
prepareCorners(SmallMaskCorners, st::buttonRadius, QColor(255, 255, 255), nullptr, mask);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
::cornersMaskSmall[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
|
||||
::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor());
|
||||
::cornersMaskSmall[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
::cornersMaskSmall[i].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
prepareCorners(LargeMaskCorners, msgRadius(), QColor(255, 255, 255), nullptr, mask);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
::cornersMaskLarge[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
::cornersMaskLarge[i].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
}
|
||||
|
||||
void createPaletteCorners() {
|
||||
prepareCorners(MenuCorners, st::buttonRadius, st::menuBg);
|
||||
prepareCorners(BoxCorners, st::boxRadius, st::boxBg);
|
||||
prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBgAdd);
|
||||
@@ -2235,8 +2250,6 @@ namespace {
|
||||
prepareCorners(EmojiHoverCorners, st::buttonRadius, st::emojiPanHover);
|
||||
prepareCorners(StickerHoverCorners, st::buttonRadius, st::emojiPanHover);
|
||||
prepareCorners(BotKeyboardCorners, st::buttonRadius, st::botKbBg);
|
||||
prepareCorners(BotKeyboardOverCorners, st::buttonRadius, st::botKbOverBg);
|
||||
prepareCorners(BotKeyboardDownCorners, st::buttonRadius, st::botKbDownBg);
|
||||
prepareCorners(PhotoSelectOverlayCorners, st::buttonRadius, st::overviewPhotoSelectOverlay);
|
||||
|
||||
prepareCorners(Doc1Corners, st::buttonRadius, st::msgFile1Bg);
|
||||
@@ -2250,19 +2263,14 @@ namespace {
|
||||
prepareCorners(MessageOutSelectedCorners, msgRadius(), st::msgOutBgSelected, &st::msgOutShadowSelected);
|
||||
}
|
||||
|
||||
void createCorners() {
|
||||
::corners.resize(RoundCornersCount);
|
||||
createMaskCorners();
|
||||
createPaletteCorners();
|
||||
}
|
||||
|
||||
void clearCorners() {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
for (int i = 0; i < RoundCornersCount; ++i) {
|
||||
delete ::corners[i].p[j]; ::corners[i].p[j] = nullptr;
|
||||
}
|
||||
delete ::cornersMaskSmall[j]; ::cornersMaskSmall[j] = nullptr;
|
||||
delete ::cornersMaskLarge[j]; ::cornersMaskLarge[j] = nullptr;
|
||||
}
|
||||
for (auto i = ::cornersMap.cbegin(), e = ::cornersMap.cend(); i != e; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
delete i->p[j];
|
||||
}
|
||||
}
|
||||
::corners.clear();
|
||||
::cornersMap.clear();
|
||||
}
|
||||
|
||||
@@ -2291,18 +2299,13 @@ namespace {
|
||||
using Update = Window::Theme::BackgroundUpdate;
|
||||
static auto subscription = Window::Theme::Background()->add_subscription([](const Update &update) {
|
||||
if (update.paletteChanged()) {
|
||||
clearCorners();
|
||||
createCorners();
|
||||
createPaletteCorners();
|
||||
|
||||
if (App::main()) {
|
||||
App::main()->updateScrollColors();
|
||||
}
|
||||
HistoryLayout::serviceColorsUpdated();
|
||||
} else if (update.type == Update::Type::New) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
delete ::corners[StickerCorners].p[i]; ::corners[StickerCorners].p[i] = nullptr;
|
||||
delete ::corners[StickerSelectedCorners].p[i]; ::corners[StickerSelectedCorners].p[i] = nullptr;
|
||||
}
|
||||
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
|
||||
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
|
||||
|
||||
@@ -2766,7 +2769,7 @@ namespace {
|
||||
roundRect(p, rect, st::msgInBg, MessageInCorners, nullptr, parts);
|
||||
}
|
||||
|
||||
QImage **cornersMask(ImageRoundRadius radius) {
|
||||
QImage *cornersMask(ImageRoundRadius radius) {
|
||||
switch (radius) {
|
||||
case ImageRoundRadius::Large: return ::cornersMaskLarge;
|
||||
case ImageRoundRadius::Small:
|
||||
@@ -2776,8 +2779,8 @@ namespace {
|
||||
}
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) {
|
||||
auto cornerWidth = corner.p[0]->width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0]->height() / cIntRetinaFactor();
|
||||
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
|
||||
if (w < 2 * cornerWidth || h < 2 * cornerHeight) return;
|
||||
if (w > 2 * cornerWidth) {
|
||||
if (parts & RectPart::Top) {
|
||||
@@ -2806,16 +2809,16 @@ namespace {
|
||||
}
|
||||
}
|
||||
if (parts & RectPart::TopLeft) {
|
||||
p.drawPixmap(x, y, *corner.p[0]);
|
||||
p.drawPixmap(x, y, corner.p[0]);
|
||||
}
|
||||
if (parts & RectPart::TopRight) {
|
||||
p.drawPixmap(x + w - cornerWidth, y, *corner.p[1]);
|
||||
p.drawPixmap(x + w - cornerWidth, y, corner.p[1]);
|
||||
}
|
||||
if (parts & RectPart::BottomLeft) {
|
||||
p.drawPixmap(x, y + h - cornerHeight, *corner.p[2]);
|
||||
p.drawPixmap(x, y + h - cornerHeight, corner.p[2]);
|
||||
}
|
||||
if (parts & RectPart::BottomRight) {
|
||||
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, *corner.p[3]);
|
||||
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, corner.p[3]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2825,18 +2828,18 @@ namespace {
|
||||
|
||||
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts) {
|
||||
auto &corner = ::corners[index];
|
||||
auto cornerWidth = corner.p[0]->width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0]->height() / cIntRetinaFactor();
|
||||
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
|
||||
if (parts & RectPart::Bottom) {
|
||||
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, shadow);
|
||||
}
|
||||
if (parts & RectPart::BottomLeft) {
|
||||
p.fillRect(x, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
|
||||
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, *corner.p[2]);
|
||||
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, corner.p[2]);
|
||||
}
|
||||
if (parts & RectPart::BottomRight) {
|
||||
p.fillRect(x + w - cornerWidth, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
|
||||
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, *corner.p[3]);
|
||||
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, corner.p[3]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2853,8 +2856,8 @@ namespace {
|
||||
|
||||
CornersPixmaps pixmaps;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
pixmaps.p[j] = new QPixmap(pixmapFromImageInPlace(std::move(images[j])));
|
||||
pixmaps.p[j]->setDevicePixelRatio(cRetinaFactor());
|
||||
pixmaps.p[j] = pixmapFromImageInPlace(std::move(images[j]));
|
||||
pixmaps.p[j].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
i = cornersMap.insert(colorKey, pixmaps);
|
||||
}
|
||||
|
||||
@@ -21,10 +21,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "core/basic_types.h"
|
||||
#include "history.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_media.h"
|
||||
#include "history/history_message.h"
|
||||
#include "layout.h"
|
||||
|
||||
class Messenger;
|
||||
@@ -104,6 +102,7 @@ namespace App {
|
||||
WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPWebPage &webpage);
|
||||
WebPageData *feedWebPage(WebPageId webPageId, const QString &siteName, const TextWithEntities &content);
|
||||
GameData *feedGame(const MTPDgame &game, GameData *convert = nullptr);
|
||||
|
||||
PeerData *peer(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded);
|
||||
@@ -156,7 +155,7 @@ namespace App {
|
||||
DocumentData *document(const DocumentId &document);
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
|
||||
WebPageData *webPage(const WebPageId &webPage);
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill);
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill);
|
||||
GameData *game(const GameId &game);
|
||||
GameData *gameSet(const GameId &game, GameData *convert, const uint64 &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc);
|
||||
LocationData *location(const LocationCoords &coords);
|
||||
@@ -284,7 +283,7 @@ namespace App {
|
||||
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners);
|
||||
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners);
|
||||
|
||||
QImage **cornersMask(ImageRoundRadius radius);
|
||||
QImage *cornersMask(ImageRoundRadius radius);
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
|
||||
|
||||
@@ -242,6 +242,7 @@ void Application::newInstanceConnected() {
|
||||
}
|
||||
|
||||
void Application::readClients() {
|
||||
// This method can be called before Messenger is constructed.
|
||||
QString startUrl;
|
||||
QStringList toSend;
|
||||
for (LocalClients::iterator i = _localClients.begin(), e = _localClients.end(); i != e; ++i) {
|
||||
@@ -286,8 +287,8 @@ void Application::readClients() {
|
||||
if (!startUrl.isEmpty()) {
|
||||
cSetStartUrl(startUrl);
|
||||
}
|
||||
if (auto main = App::main()) {
|
||||
main->checkStartUrl();
|
||||
if (auto messenger = Messenger::InstancePointer()) {
|
||||
messenger->checkStartUrl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ QString AuthSessionData::getSoundPath(const QString &key) const {
|
||||
AuthSession::AuthSession(UserId userId)
|
||||
: _userId(userId)
|
||||
, _autoLockTimer([this] { checkAutoLock(); })
|
||||
, _api(std::make_unique<ApiWrap>())
|
||||
, _api(std::make_unique<ApiWrap>(this))
|
||||
, _calls(std::make_unique<Calls::Instance>())
|
||||
, _downloader(std::make_unique<Storage::Downloader>())
|
||||
, _notifications(std::make_unique<Window::Notifications::System>(this)) {
|
||||
@@ -167,6 +167,7 @@ AuthSession::AuthSession(UserId userId)
|
||||
_shouldLockAt = 0;
|
||||
notifications().updateAll();
|
||||
});
|
||||
_api->start();
|
||||
}
|
||||
|
||||
bool AuthSession::Exists() {
|
||||
|
||||
@@ -57,6 +57,22 @@ public:
|
||||
base::Observable<void> &savedGifsUpdated() {
|
||||
return _savedGifsUpdated;
|
||||
}
|
||||
base::Observable<gsl::not_null<History*>> &historyCleared() {
|
||||
return _historyCleared;
|
||||
}
|
||||
base::Observable<gsl::not_null<const HistoryItem*>> &repaintLogEntry() {
|
||||
return _repaintLogEntry;
|
||||
}
|
||||
base::Observable<void> &pendingHistoryResize() {
|
||||
return _pendingHistoryResize;
|
||||
}
|
||||
struct ItemVisibilityQuery {
|
||||
gsl::not_null<HistoryItem*> item;
|
||||
gsl::not_null<bool*> isVisible;
|
||||
};
|
||||
base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
|
||||
return _queryItemVisibility;
|
||||
}
|
||||
|
||||
void copyFrom(const AuthSessionData &other) {
|
||||
_variables = other._variables;
|
||||
@@ -131,6 +147,10 @@ private:
|
||||
base::Variable<bool> _allChatsLoaded = { false };
|
||||
base::Observable<void> _moreChatsLoaded;
|
||||
base::Observable<void> _savedGifsUpdated;
|
||||
base::Observable<gsl::not_null<History*>> _historyCleared;
|
||||
base::Observable<gsl::not_null<const HistoryItem*>> _repaintLogEntry;
|
||||
base::Observable<void> _pendingHistoryResize;
|
||||
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
|
||||
Variables _variables;
|
||||
TimeMs _lastTimeVideoPlayedAt = 0;
|
||||
|
||||
|
||||
@@ -427,9 +427,10 @@ void UpdateChecker::unpackUpdate() {
|
||||
LOG(("Update Error: cant open file '%1' for writing").arg(tempDirPath + '/' + relativeName));
|
||||
return fatalFail();
|
||||
}
|
||||
if (f.write(fileInnerData) != fileSize) {
|
||||
auto writtenBytes = f.write(fileInnerData);
|
||||
if (writtenBytes != fileSize) {
|
||||
f.close();
|
||||
LOG(("Update Error: cant write file '%1'").arg(tempDirPath + '/' + relativeName));
|
||||
LOG(("Update Error: cant write file '%1', desiredSize: %2, write result: %3").arg(tempDirPath + '/' + relativeName).arg(fileSize).arg(writtenBytes));
|
||||
return fatalFail();
|
||||
}
|
||||
f.close();
|
||||
|
||||
@@ -335,12 +335,12 @@ public:
|
||||
}
|
||||
|
||||
// Copy / move construct / assign from an arbitrary type.
|
||||
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
lambda_once(Lambda other) {
|
||||
data_.vtable = &lambda_internal::vtable_once<Lambda, Return, Args...>::instance;
|
||||
lambda_internal::vtable_once<Lambda, Return, Args...>::construct_move_lambda_method(data_.storage, &other);
|
||||
}
|
||||
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
lambda_once &operator=(Lambda other) {
|
||||
if (data_.vtable) {
|
||||
data_.vtable->destruct(data_.storage);
|
||||
@@ -414,11 +414,11 @@ public:
|
||||
}
|
||||
|
||||
// Copy / move construct / assign from an arbitrary type.
|
||||
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
lambda(Lambda other) : Parent(&lambda_internal::vtable<Lambda, Return, Args...>::instance, typename Parent::Private()) {
|
||||
lambda_internal::vtable<Lambda, Return, Args...>::construct_move_lambda_method(this->data_.storage, &other);
|
||||
}
|
||||
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
lambda &operator=(Lambda other) {
|
||||
if (this->data_.vtable) {
|
||||
this->data_.vtable->destruct(this->data_.storage);
|
||||
|
||||
@@ -229,10 +229,14 @@ private:
|
||||
break;
|
||||
}
|
||||
} while (_current);
|
||||
}
|
||||
|
||||
bool destroyMeIfEmpty() const {
|
||||
if (empty()) {
|
||||
_observable->_data.reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CommonObservable<EventType, Handler> *_observable = nullptr;
|
||||
@@ -282,6 +286,9 @@ private:
|
||||
this->notifyEnumerate([this, &event]() {
|
||||
this->_current->handler(event);
|
||||
});
|
||||
if (this->destroyMeIfEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_handling = false;
|
||||
UnregisterActiveObservable(&this->_callHandlers);
|
||||
@@ -329,6 +336,9 @@ private:
|
||||
this->notifyEnumerate([this]() {
|
||||
this->_current->handler();
|
||||
});
|
||||
if (this->destroyMeIfEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_handling = false;
|
||||
UnregisterActiveObservable(&this->_callHandlers);
|
||||
@@ -357,9 +367,9 @@ class Observable : public internal::BaseObservable<EventType, Handler, base::typ
|
||||
public:
|
||||
Observable() = default;
|
||||
Observable(const Observable &other) = delete;
|
||||
Observable(Observable &&other) = default;
|
||||
Observable(Observable &&other) = delete;
|
||||
Observable &operator=(const Observable &other) = delete;
|
||||
Observable &operator=(Observable &&other) = default;
|
||||
Observable &operator=(Observable &&other) = delete;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ typedef void(*RuntimeComponentDestruct)(void *location);
|
||||
typedef void(*RuntimeComponentMove)(void *location, void *waslocation);
|
||||
|
||||
struct RuntimeComponentWrapStruct {
|
||||
// don't init any fields, because it is only created in
|
||||
// global scope, so it will be filled by zeros from the start
|
||||
// Don't init any fields, because it is only created in
|
||||
// global scope, so it will be filled by zeros from the start.
|
||||
RuntimeComponentWrapStruct() = default;
|
||||
RuntimeComponentWrapStruct(std::size_t size, std::size_t align, RuntimeComponentConstruct construct, RuntimeComponentDestruct destruct, RuntimeComponentMove move)
|
||||
: Size(size)
|
||||
@@ -54,7 +54,8 @@ extern QAtomicInt RuntimeComponentIndexLast;
|
||||
template <typename Type>
|
||||
struct RuntimeComponent {
|
||||
RuntimeComponent() {
|
||||
static_assert(alignof(Type) <= alignof(SmallestSizeType), "Components should align to a pointer!");
|
||||
// While there is no std::aligned_alloc().
|
||||
static_assert(alignof(Type) <= alignof(std::max_align_t), "Components should align to std::max_align_t!");
|
||||
}
|
||||
RuntimeComponent(const RuntimeComponent &other) = delete;
|
||||
RuntimeComponent &operator=(const RuntimeComponent &other) = delete;
|
||||
@@ -62,17 +63,17 @@ struct RuntimeComponent {
|
||||
RuntimeComponent &operator=(RuntimeComponent &&other) = default;
|
||||
|
||||
static int Index() {
|
||||
static QAtomicInt _index(0);
|
||||
if (int index = _index.loadAcquire()) {
|
||||
static QAtomicInt MyIndex(0);
|
||||
if (auto index = MyIndex.loadAcquire()) {
|
||||
return index - 1;
|
||||
}
|
||||
while (true) {
|
||||
int last = RuntimeComponentIndexLast.loadAcquire();
|
||||
auto last = RuntimeComponentIndexLast.loadAcquire();
|
||||
if (RuntimeComponentIndexLast.testAndSetOrdered(last, last + 1)) {
|
||||
t_assert(last < 64);
|
||||
if (_index.testAndSetOrdered(0, last + 1)) {
|
||||
if (MyIndex.testAndSetOrdered(0, last + 1)) {
|
||||
RuntimeComponentWraps[last] = RuntimeComponentWrapStruct(
|
||||
CeilDivideMinimumOne<sizeof(Type), sizeof(SmallestSizeType)>::Result * sizeof(SmallestSizeType),
|
||||
sizeof(Type),
|
||||
alignof(Type),
|
||||
Type::RuntimeComponentConstruct,
|
||||
Type::RuntimeComponentDestruct,
|
||||
@@ -81,15 +82,13 @@ struct RuntimeComponent {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return _index.loadAcquire() - 1;
|
||||
return MyIndex.loadAcquire() - 1;
|
||||
}
|
||||
static uint64 Bit() {
|
||||
return (1ULL << Index());
|
||||
}
|
||||
|
||||
protected:
|
||||
using SmallestSizeType = void*;
|
||||
|
||||
static void RuntimeComponentConstruct(void *location, RuntimeComposer *composer) {
|
||||
new (location) Type();
|
||||
}
|
||||
@@ -104,30 +103,32 @@ protected:
|
||||
|
||||
class RuntimeComposerMetadata {
|
||||
public:
|
||||
RuntimeComposerMetadata(uint64 mask) : size(0), last(64), _mask(mask) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
uint64 m = (1ULL << i);
|
||||
if (_mask & m) {
|
||||
int s = RuntimeComponentWraps[i].Size;
|
||||
if (s) {
|
||||
RuntimeComposerMetadata(uint64 mask) : _mask(mask) {
|
||||
for (int i = 0; i != 64; ++i) {
|
||||
auto componentBit = (1ULL << i);
|
||||
if (_mask & componentBit) {
|
||||
auto componentSize = RuntimeComponentWraps[i].Size;
|
||||
if (componentSize) {
|
||||
auto componentAlign = RuntimeComponentWraps[i].Align;
|
||||
if (auto badAlign = (size % componentAlign)) {
|
||||
size += (componentAlign - badAlign);
|
||||
}
|
||||
offsets[i] = size;
|
||||
size += s;
|
||||
} else {
|
||||
offsets[i] = -1;
|
||||
size += componentSize;
|
||||
accumulate_max(align, componentAlign);
|
||||
}
|
||||
} else if (_mask < m) {
|
||||
} else if (_mask < componentBit) {
|
||||
last = i;
|
||||
for (; i < 64; ++i) {
|
||||
offsets[i] = -1;
|
||||
}
|
||||
} else {
|
||||
offsets[i] = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size, last;
|
||||
int offsets[64];
|
||||
// Meta pointer in the start.
|
||||
std::size_t size = sizeof(const RuntimeComposerMetadata*);
|
||||
std::size_t align = alignof(const RuntimeComposerMetadata*);
|
||||
std::size_t offsets[64] = { 0 };
|
||||
int last = 64;
|
||||
|
||||
bool equals(uint64 mask) const {
|
||||
return _mask == mask;
|
||||
@@ -150,28 +151,28 @@ class RuntimeComposer {
|
||||
public:
|
||||
RuntimeComposer(uint64 mask = 0) : _data(zerodata()) {
|
||||
if (mask) {
|
||||
const RuntimeComposerMetadata *meta = GetRuntimeComposerMetadata(mask);
|
||||
int size = sizeof(meta) + meta->size;
|
||||
auto meta = GetRuntimeComposerMetadata(mask);
|
||||
|
||||
auto data = operator new(size);
|
||||
auto data = operator new(meta->size);
|
||||
t_assert(data != nullptr);
|
||||
|
||||
_data = data;
|
||||
_meta() = meta;
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
auto offset = meta->offsets[i];
|
||||
if (offset >= sizeof(_meta())) {
|
||||
try {
|
||||
auto constructAt = _dataptrunsafe(offset);
|
||||
auto space = RuntimeComponentWraps[i].Size;
|
||||
auto alignedAt = std::align(RuntimeComponentWraps[i].Align, space, constructAt, space);
|
||||
auto alignedAt = constructAt;
|
||||
std::align(RuntimeComponentWraps[i].Align, space, alignedAt, space);
|
||||
t_assert(alignedAt == constructAt);
|
||||
RuntimeComponentWraps[i].Construct(constructAt, this);
|
||||
} catch (...) {
|
||||
while (i > 0) {
|
||||
--i;
|
||||
offset = meta->offsets[--i];
|
||||
if (offset >= 0) {
|
||||
if (offset >= sizeof(_meta())) {
|
||||
RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset));
|
||||
}
|
||||
}
|
||||
@@ -187,8 +188,8 @@ public:
|
||||
if (_data != zerodata()) {
|
||||
auto meta = _meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
auto offset = meta->offsets[i];
|
||||
if (offset >= sizeof(_meta())) {
|
||||
RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset));
|
||||
}
|
||||
}
|
||||
@@ -198,7 +199,7 @@ public:
|
||||
|
||||
template <typename Type>
|
||||
bool Has() const {
|
||||
return (_meta()->offsets[Type::Index()] >= 0);
|
||||
return (_meta()->offsets[Type::Index()] >= sizeof(_meta()));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
@@ -218,8 +219,9 @@ protected:
|
||||
if (_data != zerodata() && tmp._data != zerodata()) {
|
||||
auto meta = _meta(), wasmeta = tmp._meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i];
|
||||
if (offset >= 0 && wasoffset >= 0) {
|
||||
auto offset = meta->offsets[i];
|
||||
auto wasoffset = wasmeta->offsets[i];
|
||||
if (offset >= sizeof(_meta()) && wasoffset >= sizeof(_meta())) {
|
||||
RuntimeComponentWraps[i].Move(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset));
|
||||
}
|
||||
}
|
||||
@@ -240,15 +242,15 @@ private:
|
||||
}
|
||||
|
||||
void *_dataptrunsafe(int skip) const {
|
||||
return (char*)_data + sizeof(_meta()) + skip;
|
||||
return (char*)_data + skip;
|
||||
}
|
||||
void *_dataptr(int skip) const {
|
||||
return (skip >= 0) ? _dataptrunsafe(skip) : 0;
|
||||
return (skip >= sizeof(_meta())) ? _dataptrunsafe(skip) : nullptr;
|
||||
}
|
||||
const RuntimeComposerMetadata *&_meta() const {
|
||||
return *static_cast<const RuntimeComposerMetadata**>(_data);
|
||||
}
|
||||
void *_data;
|
||||
void *_data = nullptr;
|
||||
|
||||
void swap(RuntimeComposer &other) {
|
||||
std::swap(_data, other._data);
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/about_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "autoupdater.h"
|
||||
@@ -39,9 +39,10 @@ AboutBox::AboutBox(QWidget *parent)
|
||||
}
|
||||
|
||||
void AboutBox::prepare() {
|
||||
setTitle(qsl("Telegram Desktop"));
|
||||
constexpr auto test = std::is_convertible<const char*, QString>::value;
|
||||
setTitle([] { return qsl("Telegram Desktop"); });
|
||||
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
||||
_text3->setRichText(lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]")));
|
||||
|
||||
@@ -88,13 +89,11 @@ void AboutBox::keyPressEvent(QKeyEvent *e) {
|
||||
}
|
||||
|
||||
QString telegramFaqLink() {
|
||||
QString result = qsl("https://telegram.org/faq");
|
||||
if (cLang() > languageDefault && cLang() < languageCount) {
|
||||
const char *code = LanguageCodes[cLang()].c_str();
|
||||
if (qstr("de") == code || qstr("es") == code || qstr("it") == code || qstr("ko") == code) {
|
||||
result += qsl("/") + code;
|
||||
} else if (qstr("pt_BR") == code) {
|
||||
result += qsl("/br");
|
||||
auto result = qsl("https://telegram.org/faq");
|
||||
auto language = Lang::Current().id();
|
||||
for (auto faqLanguage : { "de", "es", "it", "ko", "br" }) {
|
||||
if (language.startsWith(QLatin1String(faqLanguage))) {
|
||||
result.append('/').append(faqLanguage);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/widget_fade_wrap.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
@@ -33,12 +33,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) {
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> BoxContent::addButton(const QString &text, base::lambda<void()> clickCallback) {
|
||||
return addButton(text, std::move(clickCallback), st::defaultBoxButton);
|
||||
QPointer<Ui::RoundButton> BoxContent::addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback) {
|
||||
return addButton(std::move(textFactory), std::move(clickCallback), st::defaultBoxButton);
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> BoxContent::addLeftButton(const QString &text, base::lambda<void()> clickCallback) {
|
||||
return getDelegate()->addLeftButton(text, std::move(clickCallback), st::defaultBoxButton);
|
||||
QPointer<Ui::RoundButton> BoxContent::addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback) {
|
||||
return getDelegate()->addLeftButton(std::move(textFactory), std::move(clickCallback), st::defaultBoxButton);
|
||||
}
|
||||
|
||||
void BoxContent::setInner(object_ptr<TWidget> inner) {
|
||||
@@ -58,9 +58,10 @@ void BoxContent::setInner(object_ptr<TWidget> inner, const style::ScrollArea &st
|
||||
_topShadow.create(this, object_ptr<BoxLayerTitleShadow>(this));
|
||||
_bottomShadow.create(this, object_ptr<BoxLayerTitleShadow>(this));
|
||||
}
|
||||
updateScrollAreaGeometry();
|
||||
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
connect(_scroll, SIGNAL(innerResized()), this, SLOT(onInnerResize()));
|
||||
if (!_preparing) {
|
||||
// We didn't set dimensions yet, this will be called from finishPrepare();
|
||||
finishScrollCreate();
|
||||
}
|
||||
} else {
|
||||
getDelegate()->setLayerType(false);
|
||||
_scroll.destroyDelayed();
|
||||
@@ -69,6 +70,21 @@ void BoxContent::setInner(object_ptr<TWidget> inner, const style::ScrollArea &st
|
||||
}
|
||||
}
|
||||
|
||||
void BoxContent::finishPrepare() {
|
||||
_preparing = false;
|
||||
if (_scroll) {
|
||||
finishScrollCreate();
|
||||
}
|
||||
setInnerFocus();
|
||||
}
|
||||
|
||||
void BoxContent::finishScrollCreate() {
|
||||
Expects(_scroll != nullptr);
|
||||
updateScrollAreaGeometry();
|
||||
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
connect(_scroll, SIGNAL(innerResized()), this, SLOT(onInnerResize()));
|
||||
}
|
||||
|
||||
void BoxContent::onScrollToY(int top, int bottom) {
|
||||
if (_scroll) {
|
||||
_scroll->scrollToY(top, bottom);
|
||||
@@ -198,6 +214,7 @@ void BoxContent::paintEvent(QPaintEvent *e) {
|
||||
AbstractBox::AbstractBox(QWidget *parent, Window::Controller *controller, object_ptr<BoxContent> content) : LayerWidget(parent)
|
||||
, _controller(controller)
|
||||
, _content(std::move(content)) {
|
||||
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
|
||||
_content->setParent(this);
|
||||
_content->setDelegate(this);
|
||||
}
|
||||
@@ -256,17 +273,18 @@ void AbstractBox::parentResized() {
|
||||
update();
|
||||
}
|
||||
|
||||
void AbstractBox::setTitle(const QString &title) {
|
||||
setTitle({ title, EntitiesInText() });
|
||||
void AbstractBox::setTitle(base::lambda<TextWithEntities()> titleFactory) {
|
||||
_titleFactory = std::move(titleFactory);
|
||||
refreshTitle();
|
||||
}
|
||||
|
||||
void AbstractBox::setTitle(const TextWithEntities &title) {
|
||||
void AbstractBox::refreshTitle() {
|
||||
auto wasTitle = hasTitle();
|
||||
if (!title.text.isEmpty()) {
|
||||
if (_titleFactory) {
|
||||
if (!_title) {
|
||||
_title.create(this, st::boxTitle);
|
||||
}
|
||||
_title->setMarkedText(title);
|
||||
_title->setMarkedText(_titleFactory());
|
||||
updateTitlePosition();
|
||||
} else {
|
||||
_title.destroy();
|
||||
@@ -276,11 +294,22 @@ void AbstractBox::setTitle(const TextWithEntities &title) {
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractBox::setAdditionalTitle(const QString &additional) {
|
||||
_additionalTitle = additional;
|
||||
void AbstractBox::setAdditionalTitle(base::lambda<QString()> additionalFactory) {
|
||||
_additionalTitleFactory = std::move(additionalFactory);
|
||||
refreshAdditionalTitle();
|
||||
}
|
||||
|
||||
void AbstractBox::refreshAdditionalTitle() {
|
||||
_additionalTitle = _additionalTitleFactory ? _additionalTitleFactory() : QString();
|
||||
update();
|
||||
}
|
||||
|
||||
void AbstractBox::refreshLang() {
|
||||
refreshTitle();
|
||||
refreshAdditionalTitle();
|
||||
InvokeQueued(this, [this] { updateButtonsPositions(); });
|
||||
}
|
||||
|
||||
bool AbstractBox::hasTitle() const {
|
||||
return (_title != nullptr) || !_additionalTitle.isEmpty();
|
||||
}
|
||||
@@ -320,8 +349,8 @@ void AbstractBox::clearButtons() {
|
||||
_leftButton.destroy();
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> AbstractBox::addButton(const QString &text, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
_buttons.push_back(object_ptr<Ui::RoundButton>(this, text, st));
|
||||
QPointer<Ui::RoundButton> AbstractBox::addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
_buttons.push_back(object_ptr<Ui::RoundButton>(this, std::move(textFactory), st));
|
||||
auto result = QPointer<Ui::RoundButton>(_buttons.back());
|
||||
result->setClickedCallback(std::move(clickCallback));
|
||||
result->show();
|
||||
@@ -329,8 +358,8 @@ QPointer<Ui::RoundButton> AbstractBox::addButton(const QString &text, base::lamb
|
||||
return result;
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> AbstractBox::addLeftButton(const QString &text, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
_leftButton = object_ptr<Ui::RoundButton>(this, text, st);
|
||||
QPointer<Ui::RoundButton> AbstractBox::addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
_leftButton = object_ptr<Ui::RoundButton>(this, std::move(textFactory), st);
|
||||
auto result = QPointer<Ui::RoundButton>(_leftButton);
|
||||
result->setClickedCallback(std::move(clickCallback));
|
||||
result->show();
|
||||
|
||||
@@ -47,13 +47,12 @@ public:
|
||||
virtual Window::Controller *controller() const = 0;
|
||||
|
||||
virtual void setLayerType(bool layerType) = 0;
|
||||
virtual void setTitle(const QString &title) = 0;
|
||||
virtual void setTitle(const TextWithEntities &title) = 0;
|
||||
virtual void setAdditionalTitle(const QString &additional) = 0;
|
||||
virtual void setTitle(base::lambda<TextWithEntities()> titleFactory) = 0;
|
||||
virtual void setAdditionalTitle(base::lambda<QString()> additionalFactory) = 0;
|
||||
|
||||
virtual void clearButtons() = 0;
|
||||
virtual QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> clickCallback, const style::RoundButton &st) = 0;
|
||||
virtual QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> clickCallback, const style::RoundButton &st) = 0;
|
||||
virtual QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) = 0;
|
||||
virtual QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) = 0;
|
||||
virtual void updateButtonsPositions() = 0;
|
||||
|
||||
virtual void setDimensions(int newWidth, int maxHeight) = 0;
|
||||
@@ -78,23 +77,27 @@ public:
|
||||
getDelegate()->closeBox();
|
||||
}
|
||||
|
||||
void setTitle(const QString &title) {
|
||||
getDelegate()->setTitle(title);
|
||||
void setTitle(base::lambda<QString()> titleFactory) {
|
||||
if (titleFactory) {
|
||||
getDelegate()->setTitle([titleFactory] { return TextWithEntities { titleFactory(), EntitiesInText() }; });
|
||||
} else {
|
||||
getDelegate()->setTitle(base::lambda<TextWithEntities()>());
|
||||
}
|
||||
}
|
||||
void setTitle(const TextWithEntities &title) {
|
||||
getDelegate()->setTitle(title);
|
||||
void setTitle(base::lambda<TextWithEntities()> titleFactory) {
|
||||
getDelegate()->setTitle(std::move(titleFactory));
|
||||
}
|
||||
void setAdditionalTitle(const QString &additional) {
|
||||
getDelegate()->setAdditionalTitle(additional);
|
||||
void setAdditionalTitle(base::lambda<QString()> additional) {
|
||||
getDelegate()->setAdditionalTitle(std::move(additional));
|
||||
}
|
||||
|
||||
void clearButtons() {
|
||||
getDelegate()->clearButtons();
|
||||
}
|
||||
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> clickCallback);
|
||||
QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> clickCallback);
|
||||
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
return getDelegate()->addButton(text, std::move(clickCallback), st);
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback);
|
||||
QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback);
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
return getDelegate()->addButton(std::move(textFactory), std::move(clickCallback), st);
|
||||
}
|
||||
void updateButtonsGeometry() {
|
||||
getDelegate()->updateButtonsPositions();
|
||||
@@ -108,8 +111,9 @@ public:
|
||||
|
||||
void setDelegate(BoxContentDelegate *newDelegate) {
|
||||
_delegate = newDelegate;
|
||||
_preparing = true;
|
||||
prepare();
|
||||
setInnerFocus();
|
||||
finishPrepare();
|
||||
}
|
||||
|
||||
public slots:
|
||||
@@ -174,6 +178,8 @@ private slots:
|
||||
void onDraggingScrollTimer();
|
||||
|
||||
private:
|
||||
void finishPrepare();
|
||||
void finishScrollCreate();
|
||||
void setInner(object_ptr<TWidget> inner);
|
||||
void setInner(object_ptr<TWidget> inner, const style::ScrollArea &st);
|
||||
void updateScrollAreaGeometry();
|
||||
@@ -187,6 +193,7 @@ private:
|
||||
}
|
||||
BoxContentDelegate *_delegate = nullptr;
|
||||
|
||||
bool _preparing = false;
|
||||
bool _noContentMargin = false;
|
||||
int _innerTopSkip = 0;
|
||||
object_ptr<Ui::ScrollArea> _scroll = { nullptr };
|
||||
@@ -208,13 +215,12 @@ public:
|
||||
void parentResized() override;
|
||||
|
||||
void setLayerType(bool layerType) override;
|
||||
void setTitle(const QString &title) override;
|
||||
void setTitle(const TextWithEntities &title) override;
|
||||
void setAdditionalTitle(const QString &additional) override;
|
||||
void setTitle(base::lambda<TextWithEntities()> titleFactory) override;
|
||||
void setAdditionalTitle(base::lambda<QString()> additionalFactory) override;
|
||||
|
||||
void clearButtons() override;
|
||||
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> clickCallback, const style::RoundButton &st) override;
|
||||
QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> clickCallback, const style::RoundButton &st) override;
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) override;
|
||||
QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) override;
|
||||
void updateButtonsPositions() override;
|
||||
|
||||
void setDimensions(int newWidth, int maxHeight) override;
|
||||
@@ -248,6 +254,9 @@ protected:
|
||||
private:
|
||||
void paintAdditionalTitle(Painter &p);
|
||||
void updateTitlePosition();
|
||||
void refreshTitle();
|
||||
void refreshAdditionalTitle();
|
||||
void refreshLang();
|
||||
|
||||
bool hasTitle() const;
|
||||
int titleHeight() const;
|
||||
@@ -266,7 +275,9 @@ private:
|
||||
object_ptr<BoxContent> _content;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _title = { nullptr };
|
||||
base::lambda<TextWithEntities()> _titleFactory;
|
||||
QString _additionalTitle;
|
||||
base::lambda<QString()> _additionalTitleFactory;
|
||||
int _titleLeft = 0;
|
||||
int _titleTop = 0;
|
||||
bool _layerType = false;
|
||||
|
||||
@@ -22,8 +22,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "messenger.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "boxes/contacts_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/photo_crop_box.h"
|
||||
@@ -40,10 +41,60 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "observer_peer.h"
|
||||
#include "auth_session.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kMaxGroupChannelTitle = 255;
|
||||
constexpr auto kMaxChannelDescription = 255;
|
||||
constexpr auto kMaxBioLength = 70;
|
||||
|
||||
style::InputField CreateBioFieldStyle() {
|
||||
auto result = st::newGroupDescription;
|
||||
result.textMargins.setRight(st::boxTextFont->spacew + st::boxTextFont->width(QString::number(kMaxBioLength)));
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class RevokePublicLinkBox::Inner : public TWidget, private MTP::Sender {
|
||||
public:
|
||||
Inner(QWidget *parent, base::lambda<void()> revokeCallback);
|
||||
|
||||
protected:
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
struct ChatRow {
|
||||
ChatRow(gsl::not_null<PeerData*> peer) : peer(peer) {
|
||||
}
|
||||
|
||||
gsl::not_null<PeerData*> peer;
|
||||
Text name, status;
|
||||
};
|
||||
void paintChat(Painter &p, const ChatRow &row, bool selected) const;
|
||||
void updateSelected();
|
||||
|
||||
PeerData *_selected = nullptr;
|
||||
PeerData *_pressed = nullptr;
|
||||
|
||||
std::vector<ChatRow> _rows;
|
||||
|
||||
int _rowsTop = 0;
|
||||
int _rowHeight = 0;
|
||||
int _revokeWidth = 0;
|
||||
|
||||
base::lambda<void()> _revokeCallback;
|
||||
mtpRequestId _revokeRequestId = 0;
|
||||
QPointer<ConfirmBox> _weakRevokeConfirmBox;
|
||||
|
||||
};
|
||||
|
||||
AddContactBox::AddContactBox(QWidget*, QString fname, QString lname, QString phone)
|
||||
: _first(this, st::defaultInputField, lang(lng_signup_firstname), fname)
|
||||
, _last(this, st::defaultInputField, lang(lng_signup_lastname), lname)
|
||||
, _phone(this, st::defaultInputField, lang(lng_contact_phone), phone)
|
||||
: _first(this, st::defaultInputField, langFactory(lng_signup_firstname), fname)
|
||||
, _last(this, st::defaultInputField, langFactory(lng_signup_lastname), lname)
|
||||
, _phone(this, st::defaultInputField, langFactory(lng_contact_phone), phone)
|
||||
, _invertOrder(langFirstNameGoesSecond()) {
|
||||
if (!phone.isEmpty()) {
|
||||
_phone->setDisabled(true);
|
||||
@@ -52,9 +103,9 @@ AddContactBox::AddContactBox(QWidget*, QString fname, QString lname, QString pho
|
||||
|
||||
AddContactBox::AddContactBox(QWidget*, UserData *user)
|
||||
: _user(user)
|
||||
, _first(this, st::defaultInputField, lang(lng_signup_firstname), user->firstName)
|
||||
, _last(this, st::defaultInputField, lang(lng_signup_lastname), user->lastName)
|
||||
, _phone(this, st::defaultInputField, lang(lng_contact_phone), user->phone())
|
||||
, _first(this, st::defaultInputField, langFactory(lng_signup_firstname), user->firstName)
|
||||
, _last(this, st::defaultInputField, langFactory(lng_signup_lastname), user->lastName)
|
||||
, _phone(this, st::defaultInputField, langFactory(lng_contact_phone), user->phone())
|
||||
, _invertOrder(langFirstNameGoesSecond()) {
|
||||
_phone->setDisabled(true);
|
||||
}
|
||||
@@ -64,10 +115,10 @@ void AddContactBox::prepare() {
|
||||
setTabOrder(_last, _first);
|
||||
}
|
||||
if (_user) {
|
||||
setTitle(lang(lng_edit_contact_title));
|
||||
setTitle(langFactory(lng_edit_contact_title));
|
||||
} else {
|
||||
bool readyToAdd = !_phone->getLastText().isEmpty() && (!_first->getLastText().isEmpty() || !_last->getLastText().isEmpty());
|
||||
setTitle(lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data));
|
||||
auto readyToAdd = !_phone->getLastText().isEmpty() && (!_first->getLastText().isEmpty() || !_last->getLastText().isEmpty());
|
||||
setTitle(langFactory(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data));
|
||||
}
|
||||
updateButtons();
|
||||
|
||||
@@ -136,9 +187,9 @@ void AddContactBox::onSubmit() {
|
||||
void AddContactBox::onSave() {
|
||||
if (_addRequest) return;
|
||||
|
||||
QString firstName = prepareText(_first->getLastText());
|
||||
QString lastName = prepareText(_last->getLastText());
|
||||
QString phone = _phone->getLastText().trimmed();
|
||||
auto firstName = TextUtilities::PrepareForSending(_first->getLastText());
|
||||
auto lastName = TextUtilities::PrepareForSending(_last->getLastText());
|
||||
auto phone = _phone->getLastText().trimmed();
|
||||
if (firstName.isEmpty() && lastName.isEmpty()) {
|
||||
if (_invertOrder) {
|
||||
_last->setFocus();
|
||||
@@ -236,10 +287,10 @@ void AddContactBox::onRetry() {
|
||||
void AddContactBox::updateButtons() {
|
||||
clearButtons();
|
||||
if (_retrying) {
|
||||
addButton(lang(lng_try_other_contact), [this] { onRetry(); });
|
||||
addButton(langFactory(lng_try_other_contact), [this] { onRetry(); });
|
||||
} else {
|
||||
addButton(lang(_user ? lng_settings_save : lng_add_contact), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(_user ? lng_settings_save : lng_add_contact), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,18 +298,18 @@ GroupInfoBox::GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeCh
|
||||
: _creating(creating)
|
||||
, _fromTypeChoose(fromTypeChoose)
|
||||
, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition)
|
||||
, _title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) {
|
||||
, _title(this, st::defaultInputField, langFactory(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) {
|
||||
}
|
||||
|
||||
void GroupInfoBox::prepare() {
|
||||
setMouseTracking(true);
|
||||
|
||||
_title->setMaxLength(MaxGroupChannelTitle);
|
||||
_title->setMaxLength(kMaxGroupChannelTitle);
|
||||
|
||||
if (_creating == CreatingGroupChannel) {
|
||||
_description.create(this, st::newGroupDescription, lang(lng_create_group_description));
|
||||
_description.create(this, st::newGroupDescription, langFactory(lng_create_group_description));
|
||||
_description->show();
|
||||
_description->setMaxLength(MaxChannelDescription);
|
||||
_description->setMaxLength(kMaxChannelDescription);
|
||||
|
||||
connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
|
||||
connect(_description, SIGNAL(submitted(bool)), this, SLOT(onNext()));
|
||||
@@ -267,8 +318,8 @@ void GroupInfoBox::prepare() {
|
||||
|
||||
connect(_title, SIGNAL(submitted(bool)), this, SLOT(onNameSubmit()));
|
||||
|
||||
addButton(lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), [this] { onNext(); });
|
||||
addButton(lang(_fromTypeChoose ? lng_create_group_back : lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), [this] { onNext(); });
|
||||
addButton(langFactory(_fromTypeChoose ? lng_create_group_back : lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setupPhotoButton();
|
||||
|
||||
@@ -331,8 +382,8 @@ void GroupInfoBox::onNameSubmit() {
|
||||
void GroupInfoBox::onNext() {
|
||||
if (_creationRequestId) return;
|
||||
|
||||
auto title = prepareText(_title->getLastText());
|
||||
auto description = _description ? prepareText(_description->getLastText(), true) : QString();
|
||||
auto title = TextUtilities::PrepareForSending(_title->getLastText());
|
||||
auto description = _description ? TextUtilities::PrepareForSending(_description->getLastText(), TextUtilities::PrepareTextOption::CheckLinks) : QString();
|
||||
if (title.isEmpty()) {
|
||||
_title->setFocus();
|
||||
_title->showError();
|
||||
@@ -422,10 +473,10 @@ SetupChannelBox::SetupChannelBox(QWidget*, ChannelData *channel, bool existing)
|
||||
, _privacyGroup(std::make_shared<Ui::RadioenumGroup<Privacy>>(Privacy::Public))
|
||||
, _public(this, _privacyGroup, Privacy::Public, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), st::defaultBoxCheckbox)
|
||||
, _private(this, _privacyGroup, Privacy::Private, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title), st::defaultBoxCheckbox)
|
||||
, _aboutPublicWidth(st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultBoxCheckbox.textPosition.x())
|
||||
, _aboutPublicWidth(st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadio.diameter - st::defaultBoxCheckbox.textPosition.x())
|
||||
, _aboutPublic(st::defaultTextStyle, lang(channel->isMegagroup() ? lng_create_public_group_about : lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||
, _aboutPrivate(st::defaultTextStyle, lang(channel->isMegagroup() ? lng_create_private_group_about : lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||
, _link(this, st::setupChannelLink, QString(), channel->username, true) {
|
||||
, _link(this, st::setupChannelLink, base::lambda<QString()>(), channel->username, true) {
|
||||
}
|
||||
|
||||
void SetupChannelBox::prepare() {
|
||||
@@ -435,8 +486,8 @@ void SetupChannelBox::prepare() {
|
||||
|
||||
_checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail));
|
||||
|
||||
addButton(lang(lng_settings_save), [this] { onSave(); });
|
||||
addButton(lang(_existing ? lng_cancel : lng_create_group_skip), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { onSave(); });
|
||||
addButton(langFactory(_existing ? lng_cancel : lng_create_group_skip), [this] { closeBox(); });
|
||||
|
||||
connect(_link, SIGNAL(changed()), this, SLOT(onChange()));
|
||||
_link->setVisible(_privacyGroup->value() == Privacy::Public);
|
||||
@@ -445,6 +496,11 @@ void SetupChannelBox::prepare() {
|
||||
connect(&_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck()));
|
||||
|
||||
_privacyGroup->setChangedCallback([this](Privacy value) { privacyChanged(value); });
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::InviteLinkChanged, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _channel) {
|
||||
rtlupdate(_invitationLink);
|
||||
}
|
||||
}));
|
||||
|
||||
updateMaxHeight();
|
||||
}
|
||||
@@ -486,10 +542,10 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
|
||||
p.fillRect(e->rect(), st::boxBg);
|
||||
p.setPen(st::newGroupAboutFg);
|
||||
|
||||
QRect aboutPublic(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultBoxCheckbox.textPosition.x(), _public->bottomNoMargins(), _aboutPublicWidth, _aboutPublicHeight);
|
||||
QRect aboutPublic(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadio.diameter + st::defaultBoxCheckbox.textPosition.x(), _public->bottomNoMargins(), _aboutPublicWidth, _aboutPublicHeight);
|
||||
_aboutPublic.drawLeft(p, aboutPublic.x(), aboutPublic.y(), aboutPublic.width(), width());
|
||||
|
||||
QRect aboutPrivate(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultBoxCheckbox.textPosition.x(), _private->bottomNoMargins(), _aboutPublicWidth, _aboutPublicHeight);
|
||||
QRect aboutPrivate(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadio.diameter + st::defaultBoxCheckbox.textPosition.x(), _private->bottomNoMargins(), _aboutPublicWidth, _aboutPublicHeight);
|
||||
_aboutPrivate.drawLeft(p, aboutPrivate.x(), aboutPrivate.y(), aboutPrivate.width(), width());
|
||||
|
||||
if (!_channel->isMegagroup() || !_link->isHidden()) {
|
||||
@@ -504,7 +560,8 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
|
||||
option.setWrapMode(QTextOption::WrapAnywhere);
|
||||
p.setFont(_linkOver ? st::boxTextFont->underline() : st::boxTextFont);
|
||||
p.setPen(st::defaultLinkButton.color);
|
||||
p.drawText(_invitationLink, _channel->inviteLink(), option);
|
||||
auto inviteLinkText = _channel->inviteLink().isEmpty() ? lang(lng_group_invite_create) : _channel->inviteLink();
|
||||
p.drawText(_invitationLink, inviteLinkText, option);
|
||||
}
|
||||
} else {
|
||||
if (!_errorText.isEmpty()) {
|
||||
@@ -536,8 +593,12 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
|
||||
void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
|
||||
if (_linkOver) {
|
||||
QGuiApplication::clipboard()->setText(_channel->inviteLink());
|
||||
Ui::Toast::Show(lang(lng_create_channel_link_copied));
|
||||
if (_channel->inviteLink().isEmpty()) {
|
||||
App::api()->exportInviteLink(_channel);
|
||||
} else {
|
||||
QGuiApplication::clipboard()->setText(_channel->inviteLink());
|
||||
Ui::Toast::Show(lang(lng_create_channel_link_copied));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,7 +719,7 @@ void SetupChannelBox::privacyChanged(Privacy value) {
|
||||
}
|
||||
|
||||
void SetupChannelBox::onUpdateDone(const MTPBool &result) {
|
||||
_channel->setName(textOneLine(_channel->name), _sentUsername);
|
||||
_channel->setName(TextUtilities::SingleLine(_channel->name), _sentUsername);
|
||||
closeBox();
|
||||
}
|
||||
|
||||
@@ -668,7 +729,7 @@ bool SetupChannelBox::onUpdateFail(const RPCError &error) {
|
||||
_saveRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == "USERNAME_NOT_MODIFIED" || _sentUsername == _channel->username) {
|
||||
_channel->setName(textOneLine(_channel->name), textOneLine(_sentUsername));
|
||||
_channel->setName(TextUtilities::SingleLine(_channel->name), TextUtilities::SingleLine(_sentUsername));
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == "USERNAME_INVALID") {
|
||||
@@ -758,31 +819,31 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
|
||||
return true;
|
||||
}
|
||||
|
||||
EditNameTitleBox::EditNameTitleBox(QWidget*, PeerData *peer)
|
||||
EditNameTitleBox::EditNameTitleBox(QWidget*, gsl::not_null<PeerData*> peer)
|
||||
: _peer(peer)
|
||||
, _first(this, st::defaultInputField, lang(peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), peer->isUser() ? peer->asUser()->firstName : peer->name)
|
||||
, _last(this, st::defaultInputField, lang(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString())
|
||||
, _first(this, st::defaultInputField, langFactory(_peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), _peer->isUser() ? _peer->asUser()->firstName : _peer->name)
|
||||
, _last(this, st::defaultInputField, langFactory(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString())
|
||||
, _invertOrder(!peer->isChat() && langFirstNameGoesSecond()) {
|
||||
}
|
||||
|
||||
void EditNameTitleBox::prepare() {
|
||||
auto newHeight = st::contactPadding.top() + _first->height();
|
||||
if (_peer->isUser()) {
|
||||
setTitle(lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title));
|
||||
setTitle(langFactory(_peer->isSelf() ? lng_edit_self_title : lng_edit_contact_title));
|
||||
newHeight += st::contactSkip + _last->height();
|
||||
} else if (_peer->isChat()) {
|
||||
setTitle(lang(lng_edit_group_title));
|
||||
setTitle(langFactory(lng_edit_group_title));
|
||||
}
|
||||
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
|
||||
setDimensions(st::boxWideWidth, newHeight);
|
||||
|
||||
addButton(lang(lng_settings_save), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
if (_invertOrder) {
|
||||
setTabOrder(_last, _first);
|
||||
}
|
||||
_first->setMaxLength(MaxGroupChannelTitle);
|
||||
_last->setMaxLength(MaxGroupChannelTitle);
|
||||
_first->setMaxLength(kMaxGroupChannelTitle);
|
||||
_last->setMaxLength(kMaxGroupChannelTitle);
|
||||
|
||||
connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
||||
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
||||
@@ -835,7 +896,8 @@ void EditNameTitleBox::resizeEvent(QResizeEvent *e) {
|
||||
void EditNameTitleBox::onSave() {
|
||||
if (_requestId) return;
|
||||
|
||||
QString first = prepareText(_first->getLastText()), last = prepareText(_last->getLastText());
|
||||
auto first = TextUtilities::PrepareForSending(_first->getLastText());
|
||||
auto last = TextUtilities::PrepareForSending(_last->getLastText());
|
||||
if (first.isEmpty() && last.isEmpty()) {
|
||||
if (_invertOrder) {
|
||||
_last->setFocus();
|
||||
@@ -867,10 +929,11 @@ void EditNameTitleBox::onSaveSelfDone(const MTPUser &user) {
|
||||
bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
QString err(error.type());
|
||||
QString first = textOneLine(_first->getLastText().trimmed()), last = textOneLine(_last->getLastText().trimmed());
|
||||
auto err = error.type();
|
||||
auto first = TextUtilities::SingleLine(_first->getLastText().trimmed());
|
||||
auto last = TextUtilities::SingleLine(_last->getLastText().trimmed());
|
||||
if (err == "NAME_NOT_MODIFIED") {
|
||||
App::self()->setName(first, last, QString(), textOneLine(App::self()->username));
|
||||
App::self()->setName(first, last, QString(), TextUtilities::SingleLine(App::self()->username));
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == "FIRSTNAME_INVALID") {
|
||||
@@ -911,26 +974,99 @@ void EditNameTitleBox::onSaveChatDone(const MTPUpdates &updates) {
|
||||
closeBox();
|
||||
}
|
||||
|
||||
EditChannelBox::EditChannelBox(QWidget*, ChannelData *channel)
|
||||
EditBioBox::EditBioBox(QWidget*, gsl::not_null<UserData*> self) : BoxContent()
|
||||
, _dynamicFieldStyle(CreateBioFieldStyle())
|
||||
, _self(self)
|
||||
, _bio(this, _dynamicFieldStyle, langFactory(lng_bio_placeholder), _self->about())
|
||||
, _countdown(this, QString(), Ui::FlatLabel::InitType::Simple, st::editBioCountdownLabel)
|
||||
, _about(this, lang(lng_bio_about), Ui::FlatLabel::InitType::Simple, st::aboutRevokePublicLabel) {
|
||||
}
|
||||
|
||||
void EditBioBox::prepare() {
|
||||
setTitle(langFactory(lng_bio_title));
|
||||
|
||||
addButton(langFactory(lng_settings_save), [this] { save(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
_bio->setMaxLength(kMaxBioLength);
|
||||
_bio->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
|
||||
auto cursor = _bio->textCursor();
|
||||
cursor.setPosition(_bio->getLastText().size());
|
||||
_bio->setTextCursor(cursor);
|
||||
connect(_bio, &Ui::InputArea::submitted, this, [this](bool ctrlShiftEnter) { save(); });
|
||||
connect(_bio, &Ui::InputArea::resized, this, [this] { updateMaxHeight(); });
|
||||
connect(_bio, &Ui::InputArea::changed, this, [this] { handleBioUpdated(); });
|
||||
handleBioUpdated();
|
||||
updateMaxHeight();
|
||||
}
|
||||
|
||||
void EditBioBox::updateMaxHeight() {
|
||||
auto newHeight = st::contactPadding.top() + _bio->height() + st::boxLittleSkip + _about->height() + st::boxPadding.bottom() + st::contactPadding.bottom();
|
||||
setDimensions(st::boxWideWidth, newHeight);
|
||||
}
|
||||
|
||||
void EditBioBox::handleBioUpdated() {
|
||||
auto text = _bio->getLastText();
|
||||
if (text.indexOf('\n') >= 0) {
|
||||
auto position = _bio->textCursor().position();
|
||||
_bio->setText(text.replace('\n', ' '));
|
||||
auto cursor = _bio->textCursor();
|
||||
cursor.setPosition(position);
|
||||
_bio->setTextCursor(cursor);
|
||||
}
|
||||
auto countLeft = qMax(kMaxBioLength - text.size(), 0);
|
||||
_countdown->setText(QString::number(countLeft));
|
||||
}
|
||||
|
||||
void EditBioBox::setInnerFocus() {
|
||||
_bio->setFocusFast();
|
||||
}
|
||||
|
||||
void EditBioBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_bio->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _bio->height());
|
||||
_bio->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::contactPadding.top());
|
||||
_countdown->moveToRight(st::boxPadding.right(), _bio->y() + _dynamicFieldStyle.textMargins.top());
|
||||
_about->moveToLeft(st::boxPadding.left(), _bio->y() + _bio->height() + st::boxLittleSkip);
|
||||
}
|
||||
|
||||
void EditBioBox::save() {
|
||||
if (_requestId) return;
|
||||
|
||||
auto text = TextUtilities::PrepareForSending(_bio->getLastText());
|
||||
_sentBio = text;
|
||||
|
||||
auto flags = MTPaccount_UpdateProfile::Flag::f_about;
|
||||
_requestId = request(MTPaccount_UpdateProfile(MTP_flags(flags), MTPstring(), MTPstring(), MTP_string(text))).done([this](const MTPUser &result) {
|
||||
App::feedUsers(MTP_vector<MTPUser>(1, result));
|
||||
_self->setAbout(_sentBio);
|
||||
closeBox();
|
||||
}).send();
|
||||
}
|
||||
|
||||
EditChannelBox::EditChannelBox(QWidget*, gsl::not_null<ChannelData*> channel)
|
||||
: _channel(channel)
|
||||
, _title(this, st::defaultInputField, lang(channel->isMegagroup() ? lng_dlg_new_group_name : lng_dlg_new_channel_name), _channel->name)
|
||||
, _description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about())
|
||||
, _title(this, st::defaultInputField, langFactory(_channel->isMegagroup() ? lng_dlg_new_group_name : lng_dlg_new_channel_name), _channel->name)
|
||||
, _description(this, st::newGroupDescription, langFactory(lng_create_group_description), _channel->about())
|
||||
, _sign(this, lang(lng_edit_sign_messages), channel->addsSignature(), st::defaultBoxCheckbox)
|
||||
, _inviteGroup(std::make_shared<Ui::RadioenumGroup<Invites>>(channel->anyoneCanAddMembers() ? Invites::Everybody : Invites::OnlyAdmins))
|
||||
, _inviteEverybody(this, _inviteGroup, Invites::Everybody, lang(lng_edit_group_invites_everybody))
|
||||
, _inviteOnlyAdmins(this, _inviteGroup, Invites::OnlyAdmins, lang(lng_edit_group_invites_only_admins))
|
||||
, _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::boxLinkButton) {
|
||||
}
|
||||
|
||||
void EditChannelBox::prepare() {
|
||||
setTitle(lang(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title));
|
||||
setTitle(langFactory(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title));
|
||||
|
||||
addButton(lang(lng_settings_save), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
_title->setMaxLength(MaxGroupChannelTitle);
|
||||
_description->setMaxLength(MaxChannelDescription);
|
||||
_title->setMaxLength(kMaxGroupChannelTitle);
|
||||
_description->setMaxLength(kMaxChannelDescription);
|
||||
|
||||
connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
|
||||
connect(_description, SIGNAL(submitted(bool)), this, SLOT(onSave()));
|
||||
@@ -938,7 +1074,9 @@ void EditChannelBox::prepare() {
|
||||
|
||||
connect(_publicLink, SIGNAL(clicked()), this, SLOT(onPublicLink()));
|
||||
_publicLink->setVisible(_channel->canEditUsername());
|
||||
_sign->setVisible(!_channel->isMegagroup());
|
||||
_sign->setVisible(canEditSignatures());
|
||||
_inviteEverybody->setVisible(canEditInvites());
|
||||
_inviteOnlyAdmins->setVisible(canEditInvites());
|
||||
|
||||
updateMaxHeight();
|
||||
}
|
||||
@@ -969,12 +1107,24 @@ void EditChannelBox::onDescriptionResized() {
|
||||
update();
|
||||
}
|
||||
|
||||
bool EditChannelBox::canEditSignatures() const {
|
||||
return _channel->canEditInformation() && !_channel->isMegagroup();
|
||||
}
|
||||
|
||||
bool EditChannelBox::canEditInvites() const {
|
||||
return _channel->canEditInformation() && _channel->isMegagroup();
|
||||
}
|
||||
|
||||
void EditChannelBox::updateMaxHeight() {
|
||||
auto newHeight = st::newGroupInfoPadding.top() + _title->height();
|
||||
newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
|
||||
if (!_channel->isMegagroup()) {
|
||||
if (canEditSignatures()) {
|
||||
newHeight += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom();
|
||||
}
|
||||
if (canEditInvites()) {
|
||||
newHeight += st::boxTitleHeight + _inviteEverybody->heightNoMargins();
|
||||
newHeight += st::boxLittleSkip + _inviteOnlyAdmins->heightNoMargins();
|
||||
}
|
||||
if (_channel->canEditUsername()) {
|
||||
newHeight += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom();
|
||||
}
|
||||
@@ -993,17 +1143,34 @@ void EditChannelBox::resizeEvent(QResizeEvent *e) {
|
||||
|
||||
_sign->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
|
||||
if (_channel->isMegagroup()) {
|
||||
_publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
} else {
|
||||
_inviteEverybody->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::boxTitleHeight);
|
||||
_inviteOnlyAdmins->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _inviteEverybody->bottomNoMargins() + st::boxLittleSkip);
|
||||
|
||||
if (canEditSignatures()) {
|
||||
_publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign->bottomNoMargins() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
} else if (canEditInvites()) {
|
||||
_publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _inviteOnlyAdmins->bottomNoMargins() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
} else {
|
||||
_publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
}
|
||||
}
|
||||
|
||||
void EditChannelBox::paintEvent(QPaintEvent *e) {
|
||||
BoxContent::paintEvent(e);
|
||||
|
||||
if (canEditInvites()) {
|
||||
Painter p(this);
|
||||
p.setPen(st::boxTitleFg);
|
||||
p.setFont(st::autoDownloadTitleFont);
|
||||
p.drawTextLeft(st::boxTitlePosition.x(), _description->y() + _description->height() + st::boxTitlePosition.y(), width(), lang(lng_edit_group_who_invites));
|
||||
}
|
||||
}
|
||||
|
||||
void EditChannelBox::onSave() {
|
||||
if (_saveTitleRequestId || _saveDescriptionRequestId || _saveSignRequestId) return;
|
||||
if (_saveTitleRequestId || _saveDescriptionRequestId || _saveSignRequestId || _saveInvitesRequestId) return;
|
||||
|
||||
QString title = prepareText(_title->getLastText()), description = prepareText(_description->getLastText(), true);
|
||||
auto title = TextUtilities::PrepareForSending(_title->getLastText());
|
||||
auto description = TextUtilities::PrepareForSending(_description->getLastText(), TextUtilities::PrepareTextOption::CheckLinks);
|
||||
if (title.isEmpty()) {
|
||||
_title->setFocus();
|
||||
_title->showError();
|
||||
@@ -1031,13 +1198,21 @@ void EditChannelBox::saveDescription() {
|
||||
}
|
||||
|
||||
void EditChannelBox::saveSign() {
|
||||
if (_channel->isMegagroup() || _channel->addsSignature() == _sign->checked()) {
|
||||
closeBox();
|
||||
if (!canEditSignatures() || _channel->addsSignature() == _sign->checked()) {
|
||||
saveInvites();
|
||||
} else {
|
||||
_saveSignRequestId = MTP::send(MTPchannels_ToggleSignatures(_channel->inputChannel, MTP_bool(_sign->checked())), rpcDone(&EditChannelBox::onSaveSignDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
}
|
||||
}
|
||||
|
||||
void EditChannelBox::saveInvites() {
|
||||
if (!canEditInvites() || _channel->anyoneCanAddMembers() == (_inviteGroup->value() == Invites::Everybody)) {
|
||||
closeBox();
|
||||
} else {
|
||||
_saveInvitesRequestId = MTP::send(MTPchannels_ToggleInvites(_channel->inputChannel, MTP_bool(_inviteGroup->value() == Invites::Everybody)), rpcDone(&EditChannelBox::onSaveInvitesDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
}
|
||||
}
|
||||
|
||||
bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
@@ -1070,6 +1245,12 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
|
||||
}
|
||||
} else if (req == _saveSignRequestId) {
|
||||
_saveSignRequestId = 0;
|
||||
if (err == qstr("CHAT_NOT_MODIFIED")) {
|
||||
saveInvites();
|
||||
return true;
|
||||
}
|
||||
} else if (req == _saveInvitesRequestId) {
|
||||
_saveInvitesRequestId = 0;
|
||||
if (err == qstr("CHAT_NOT_MODIFIED")) {
|
||||
closeBox();
|
||||
return true;
|
||||
@@ -1078,11 +1259,9 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveTitleDone(const MTPUpdates &updates) {
|
||||
void EditChannelBox::onSaveTitleDone(const MTPUpdates &result) {
|
||||
_saveTitleRequestId = 0;
|
||||
if (App::main()) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
AuthSession::Current().api().applyUpdates(result);
|
||||
saveDescription();
|
||||
}
|
||||
|
||||
@@ -1096,43 +1275,74 @@ void EditChannelBox::onSaveDescriptionDone(const MTPBool &result) {
|
||||
saveSign();
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveSignDone(const MTPUpdates &updates) {
|
||||
void EditChannelBox::onSaveSignDone(const MTPUpdates &result) {
|
||||
_saveSignRequestId = 0;
|
||||
if (App::main()) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
AuthSession::Current().api().applyUpdates(result);
|
||||
saveInvites();
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveInvitesDone(const MTPUpdates &result) {
|
||||
_saveSignRequestId = 0;
|
||||
AuthSession::Current().api().applyUpdates(result);
|
||||
closeBox();
|
||||
}
|
||||
|
||||
RevokePublicLinkBox::RevokePublicLinkBox(QWidget*, base::lambda<void()> revokeCallback)
|
||||
: _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
RevokePublicLinkBox::Inner::Inner(QWidget *parent, base::lambda<void()> revokeCallback) : TWidget(parent)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _revokeWidth(st::normalFont->width(lang(lng_channels_too_much_public_revoke)))
|
||||
, _aboutRevoke(this, lang(lng_channels_too_much_public_about), Ui::FlatLabel::InitType::Simple, st::aboutRevokePublicLabel)
|
||||
, _revokeCallback(std::move(revokeCallback)) {
|
||||
setMouseTracking(true);
|
||||
|
||||
resize(width(), 5 * _rowHeight);
|
||||
|
||||
request(MTPchannels_GetAdminedPublicChannels()).done([this](const MTPmessages_Chats &result) {
|
||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
||||
for_const (auto &chat, chats->v) {
|
||||
if (auto peer = App::feedChat(chat)) {
|
||||
if (!peer->isChannel() || peer->userName().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto row = ChatRow(peer);
|
||||
row.peer = peer;
|
||||
row.name.setText(st::contactsNameStyle, peer->name, _textNameOptions);
|
||||
row.status.setText(st::defaultTextStyle, Messenger::Instance().createInternalLink(textcmdLink(1, peer->userName())), _textDlgOptions);
|
||||
_rows.push_back(std::move(row));
|
||||
}
|
||||
}
|
||||
}
|
||||
resize(width(), _rows.size() * _rowHeight);
|
||||
update();
|
||||
}).send();
|
||||
}
|
||||
|
||||
RevokePublicLinkBox::RevokePublicLinkBox(QWidget*, base::lambda<void()> revokeCallback)
|
||||
: _aboutRevoke(this, lang(lng_channels_too_much_public_about), Ui::FlatLabel::InitType::Simple, st::aboutRevokePublicLabel)
|
||||
, _revokeCallback(std::move(revokeCallback)) {
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::prepare() {
|
||||
setMouseTracking(true);
|
||||
_innerTop = st::boxPadding.top() + _aboutRevoke->height() + st::boxPadding.top();
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, [this] {
|
||||
closeBox();
|
||||
if (_revokeCallback) {
|
||||
_revokeCallback();
|
||||
}
|
||||
}), st::boxLayerScroll, _innerTop);
|
||||
|
||||
MTP::send(MTPchannels_GetAdminedPublicChannels(), rpcDone(&RevokePublicLinkBox::getPublicDone), rpcFail(&RevokePublicLinkBox::getPublicFail));
|
||||
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||
|
||||
updateMaxHeight();
|
||||
_inner->resizeToWidth(st::boxWideWidth);
|
||||
setDimensions(st::boxWideWidth, _innerTop + _inner->height());
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::updateMaxHeight() {
|
||||
_rowsTop = st::boxPadding.top() + _aboutRevoke->height() + st::boxPadding.top();
|
||||
setDimensions(st::boxWideWidth, _rowsTop + (5 * _rowHeight));
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
void RevokePublicLinkBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
updateSelected();
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::updateSelected() {
|
||||
void RevokePublicLinkBox::Inner::updateSelected() {
|
||||
auto point = mapFromGlobal(QCursor::pos());
|
||||
PeerData *selected = nullptr;
|
||||
auto top = _rowsTop;
|
||||
@@ -1151,14 +1361,14 @@ void RevokePublicLinkBox::updateSelected() {
|
||||
}
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::mousePressEvent(QMouseEvent *e) {
|
||||
void RevokePublicLinkBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||
if (_pressed != _selected) {
|
||||
_pressed = _selected;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||
void RevokePublicLinkBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
auto pressed = base::take(_pressed);
|
||||
setCursor((_selected || _pressed) ? style::cur_pointer : style::cur_default);
|
||||
if (pressed && pressed == _selected) {
|
||||
@@ -1167,14 +1377,19 @@ void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||
auto confirmText = lang(lng_channels_too_much_public_revoke);
|
||||
_weakRevokeConfirmBox = Ui::show(Box<ConfirmBox>(text, confirmText, base::lambda_guarded(this, [this, pressed]() {
|
||||
if (_revokeRequestId) return;
|
||||
_revokeRequestId = MTP::send(MTPchannels_UpdateUsername(pressed->asChannel()->inputChannel, MTP_string("")), rpcDone(&RevokePublicLinkBox::revokeLinkDone), rpcFail(&RevokePublicLinkBox::revokeLinkFail));
|
||||
_revokeRequestId = request(MTPchannels_UpdateUsername(pressed->asChannel()->inputChannel, MTP_string(""))).done([this](const MTPBool &result) {
|
||||
if (_weakRevokeConfirmBox) {
|
||||
_weakRevokeConfirmBox->closeBox();
|
||||
}
|
||||
if (_revokeCallback) {
|
||||
_revokeCallback();
|
||||
}
|
||||
}).send();
|
||||
})), KeepOtherLayers);
|
||||
}
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
|
||||
BoxContent::paintEvent(e);
|
||||
|
||||
void RevokePublicLinkBox::Inner::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
p.translate(0, _rowsTop);
|
||||
for_const (auto &row, _rows) {
|
||||
@@ -1189,7 +1404,7 @@ void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) {
|
||||
_aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected) const {
|
||||
void RevokePublicLinkBox::Inner::paintChat(Painter &p, const ChatRow &row, bool selected) const {
|
||||
auto peer = row.peer;
|
||||
peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize);
|
||||
|
||||
@@ -1213,46 +1428,3 @@ void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selecte
|
||||
row.status.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsStatusTop, namew, width());
|
||||
p.restoreTextPalette();
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::getPublicDone(const MTPmessages_Chats &result) {
|
||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
||||
for_const (auto &chat, chats->v) {
|
||||
if (auto peer = App::feedChat(chat)) {
|
||||
if (!peer->isChannel() || peer->userName().isEmpty()) continue;
|
||||
|
||||
ChatRow row;
|
||||
row.peer = peer;
|
||||
row.name.setText(st::contactsNameStyle, peer->name, _textNameOptions);
|
||||
row.status.setText(st::defaultTextStyle, Messenger::Instance().createInternalLink(textcmdLink(1, peer->userName())), _textDlgOptions);
|
||||
_rows.push_back(std::move(row));
|
||||
}
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
bool RevokePublicLinkBox::getPublicFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RevokePublicLinkBox::revokeLinkDone(const MTPBool &result) {
|
||||
if (_weakRevokeConfirmBox) {
|
||||
_weakRevokeConfirmBox->closeBox();
|
||||
}
|
||||
closeBox();
|
||||
if (_revokeCallback) {
|
||||
_revokeCallback();
|
||||
}
|
||||
}
|
||||
|
||||
bool RevokePublicLinkBox::revokeLinkFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class ConfirmBox;
|
||||
|
||||
@@ -199,7 +200,7 @@ class EditNameTitleBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditNameTitleBox(QWidget*, PeerData *peer);
|
||||
EditNameTitleBox(QWidget*, gsl::not_null<PeerData*> peer);
|
||||
|
||||
protected:
|
||||
void setInnerFocus() override;
|
||||
@@ -218,7 +219,7 @@ private:
|
||||
void onSaveChatDone(const MTPUpdates &updates);
|
||||
bool onSaveChatFail(const RPCError &e);
|
||||
|
||||
PeerData *_peer;
|
||||
gsl::not_null<PeerData*> _peer;
|
||||
|
||||
object_ptr<Ui::InputField> _first;
|
||||
object_ptr<Ui::InputField> _last;
|
||||
@@ -230,11 +231,37 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class EditBioBox : public BoxContent, private MTP::Sender {
|
||||
public:
|
||||
EditBioBox(QWidget*, gsl::not_null<UserData*> self);
|
||||
|
||||
protected:
|
||||
void setInnerFocus() override;
|
||||
void prepare() override;
|
||||
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
void updateMaxHeight();
|
||||
void handleBioUpdated();
|
||||
void save();
|
||||
|
||||
style::InputField _dynamicFieldStyle;
|
||||
gsl::not_null<UserData*> _self;
|
||||
|
||||
object_ptr<Ui::InputArea> _bio;
|
||||
object_ptr<Ui::FlatLabel> _countdown;
|
||||
object_ptr<Ui::FlatLabel> _about;
|
||||
mtpRequestId _requestId = 0;
|
||||
QString _sentBio;
|
||||
|
||||
};
|
||||
|
||||
class EditChannelBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditChannelBox(QWidget*, ChannelData *channel);
|
||||
EditChannelBox(QWidget*, gsl::not_null<ChannelData*> channel);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
@@ -242,6 +269,7 @@ protected:
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private slots:
|
||||
void peerUpdated(PeerData *peer);
|
||||
@@ -255,26 +283,39 @@ private slots:
|
||||
|
||||
private:
|
||||
void updateMaxHeight();
|
||||
bool canEditSignatures() const;
|
||||
bool canEditInvites() const;
|
||||
|
||||
void onSaveTitleDone(const MTPUpdates &updates);
|
||||
void onSaveTitleDone(const MTPUpdates &result);
|
||||
void onSaveDescriptionDone(const MTPBool &result);
|
||||
void onSaveSignDone(const MTPUpdates &updates);
|
||||
bool onSaveFail(const RPCError &e, mtpRequestId req);
|
||||
void onSaveSignDone(const MTPUpdates &result);
|
||||
void onSaveInvitesDone(const MTPUpdates &result);
|
||||
bool onSaveFail(const RPCError &error, mtpRequestId req);
|
||||
|
||||
void saveDescription();
|
||||
void saveSign();
|
||||
void saveInvites();
|
||||
|
||||
ChannelData *_channel;
|
||||
gsl::not_null<ChannelData*> _channel;
|
||||
|
||||
object_ptr<Ui::InputField> _title;
|
||||
object_ptr<Ui::InputArea> _description;
|
||||
object_ptr<Ui::Checkbox> _sign;
|
||||
|
||||
enum class Invites {
|
||||
Everybody,
|
||||
OnlyAdmins,
|
||||
};
|
||||
std::shared_ptr<Ui::RadioenumGroup<Invites>> _inviteGroup;
|
||||
object_ptr<Ui::Radioenum<Invites>> _inviteEverybody;
|
||||
object_ptr<Ui::Radioenum<Invites>> _inviteOnlyAdmins;
|
||||
|
||||
object_ptr<Ui::LinkButton> _publicLink;
|
||||
|
||||
mtpRequestId _saveTitleRequestId = 0;
|
||||
mtpRequestId _saveDescriptionRequestId = 0;
|
||||
mtpRequestId _saveSignRequestId = 0;
|
||||
mtpRequestId _saveInvitesRequestId = 0;
|
||||
|
||||
QString _sentTitle, _sentDescription;
|
||||
|
||||
@@ -287,41 +328,15 @@ public:
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
void updateMaxHeight();
|
||||
void updateSelected();
|
||||
|
||||
struct ChatRow {
|
||||
PeerData *peer;
|
||||
Text name, status;
|
||||
};
|
||||
void paintChat(Painter &p, const ChatRow &row, bool selected) const;
|
||||
|
||||
void getPublicDone(const MTPmessages_Chats &result);
|
||||
bool getPublicFail(const RPCError &error);
|
||||
|
||||
void revokeLinkDone(const MTPBool &result);
|
||||
bool revokeLinkFail(const RPCError &error);
|
||||
|
||||
PeerData *_selected = nullptr;
|
||||
PeerData *_pressed = nullptr;
|
||||
|
||||
QVector<ChatRow> _rows;
|
||||
|
||||
int _rowsTop = 0;
|
||||
int _rowHeight = 0;
|
||||
int _revokeWidth = 0;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _aboutRevoke;
|
||||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
int _innerTop = 0;
|
||||
base::lambda<void()> _revokeCallback;
|
||||
mtpRequestId _revokeRequestId = 0;
|
||||
QPointer<ConfirmBox> _weakRevokeConfirmBox;
|
||||
|
||||
};
|
||||
|
||||
@@ -20,31 +20,31 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/autolock_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
void AutoLockBox::prepare() {
|
||||
setTitle(lang(lng_passcode_autolock));
|
||||
setTitle(langFactory(lng_passcode_autolock));
|
||||
|
||||
addButton(lang(lng_box_ok), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
|
||||
|
||||
auto options = { 60, 300, 3600, 18000 };
|
||||
|
||||
auto group = std::make_shared<Ui::RadiobuttonGroup>(Global::AutoLock());
|
||||
auto y = st::boxOptionListPadding.top();
|
||||
auto y = st::boxOptionListPadding.top() + st::langsButton.margin.top();
|
||||
auto count = int(options.size());
|
||||
_options.reserve(count);
|
||||
for (auto seconds : options) {
|
||||
_options.emplace_back(this, group, seconds, (seconds % 3600) ? lng_passcode_autolock_minutes(lt_count, seconds / 60) : lng_passcode_autolock_hours(lt_count, seconds / 3600), st::langsButton);
|
||||
_options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
|
||||
_options.back()->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
|
||||
y += _options.back()->heightNoMargins() + st::boxOptionListSkip;
|
||||
}
|
||||
group->setChangedCallback([this](int value) { durationChanged(value); });
|
||||
|
||||
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + count * st::langsButton.height + (count - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
|
||||
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + count * _options.back()->heightNoMargins() + (count - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
|
||||
}
|
||||
|
||||
void AutoLockBox::durationChanged(int seconds) {
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/background_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
@@ -63,9 +63,9 @@ BackgroundBox::BackgroundBox(QWidget*) {
|
||||
}
|
||||
|
||||
void BackgroundBox::prepare() {
|
||||
setTitle(lang(lng_backgrounds_header));
|
||||
setTitle(langFactory(lng_backgrounds_header));
|
||||
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ attentionBoxButton: RoundButton(defaultBoxButton) {
|
||||
|
||||
defaultBoxCheckbox: Checkbox(defaultCheckbox) {
|
||||
width: -46px;
|
||||
textPosition: point(34px, 1px);
|
||||
textPosition: point(12px, 1px);
|
||||
style: boxTextStyle;
|
||||
}
|
||||
|
||||
@@ -202,6 +202,10 @@ aboutRevokePublicLabel: FlatLabel(defaultFlatLabel) {
|
||||
align: align(topleft);
|
||||
width: 320px;
|
||||
}
|
||||
editBioCountdownLabel: FlatLabel(defaultFlatLabel) {
|
||||
style: boxTextStyle;
|
||||
textFg: windowSubTextFg;
|
||||
}
|
||||
|
||||
contactUserIcon: icon {{ "add_contact_user", menuIconFg }};
|
||||
contactPhoneIcon: icon {{ "add_contact_phone", menuIconFg }};
|
||||
@@ -459,7 +463,7 @@ newGroupNamePosition: point(27px, 5px);
|
||||
newGroupDescriptionPadding: margins(0px, 13px, 0px, 4px);
|
||||
newGroupDescription: InputField(defaultInputField) {
|
||||
textMargins: margins(1px, 26px, 1px, 4px);
|
||||
heightMax: 135px;
|
||||
heightMax: 116px;
|
||||
}
|
||||
|
||||
setupChannelLink: InputField(defaultInputField) {
|
||||
@@ -563,10 +567,7 @@ passcodeTextStyle: TextStyle(defaultTextStyle) {
|
||||
|
||||
usernamePadding: margins(23px, 6px, 21px, 12px);
|
||||
usernameSkip: 49px;
|
||||
usernameTextStyle: TextStyle(passcodeTextStyle) {
|
||||
font: boxTextFont;
|
||||
linkFont: boxTextFont;
|
||||
linkFontOver: font(boxFontSize underline);
|
||||
usernameTextStyle: TextStyle(boxTextStyle, passcodeTextStyle) {
|
||||
}
|
||||
usernameDefaultFg: windowSubTextFg;
|
||||
|
||||
@@ -631,3 +632,55 @@ changePhoneLabel: FlatLabel(defaultFlatLabel) {
|
||||
changePhoneError: FlatLabel(changePhoneLabel) {
|
||||
textFg: boxTextFgError;
|
||||
}
|
||||
|
||||
adminLogFilterUserpicLeft: 15px;
|
||||
adminLogFilterLittleSkip: 16px;
|
||||
adminLogFilterCheckbox: Checkbox(defaultBoxCheckbox) {
|
||||
style: TextStyle(boxTextStyle) {
|
||||
font: font(boxFontSize semibold);
|
||||
linkFont: font(boxFontSize semibold);
|
||||
linkFontOver: font(boxFontSize semibold underline);
|
||||
}
|
||||
}
|
||||
adminLogFilterSkip: 32px;
|
||||
adminLogFilterUserCheckbox: Checkbox(defaultBoxCheckbox) {
|
||||
margin: margins(8px, 6px, 8px, 6px);
|
||||
}
|
||||
|
||||
rightsCheckbox: Checkbox(defaultBoxCheckbox) {
|
||||
rippleBg: attentionButtonBgOver;
|
||||
}
|
||||
rightsToggle: Toggle(defaultToggle) {
|
||||
toggledFg: windowBgActive;
|
||||
untoggledFg: attentionButtonFg;
|
||||
xsize: 8px;
|
||||
vsize: 5px;
|
||||
vshift: 1px;
|
||||
stroke: 2px;
|
||||
duration: 120;
|
||||
}
|
||||
rightsDividerHeight: 11px;
|
||||
rightsHeaderMargin: margins(23px, 20px, 23px, 8px);
|
||||
rightsToggleMargin: margins(23px, 8px, 23px, 8px);
|
||||
rightsAboutMargin: margins(23px, 8px, 23px, 8px);
|
||||
rightsPhotoButton: PeerAvatarButton {
|
||||
size: 60px;
|
||||
photoSize: 60px;
|
||||
}
|
||||
rightsPhotoMargin: margins(20px, 0px, 15px, 18px);
|
||||
rightsNameStyle: TextStyle(semiboldTextStyle) {
|
||||
font: font(15px semibold);
|
||||
linkFont: font(15px semibold);
|
||||
linkFontOver: font(15px semibold underline);
|
||||
}
|
||||
rightsNameTop: 8px;
|
||||
rightsStatusTop: 32px;
|
||||
rightsHeaderLabel: FlatLabel(boxLabel) {
|
||||
style: TextStyle(semiboldTextStyle) {
|
||||
font: font(boxFontSize semibold);
|
||||
linkFont: font(boxFontSize semibold);
|
||||
linkFontOver: font(boxFontSize semibold underline);
|
||||
}
|
||||
textFg: windowActiveTextFg;
|
||||
}
|
||||
rightsUntilMargin: margins(0px, 8px, 0px, 0px);
|
||||
|
||||
@@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
|
||||
namespace {
|
||||
@@ -463,7 +463,7 @@ void CalendarBox::prepare() {
|
||||
// _inner = setInnerWidget(object_ptr<Inner>(this, _context.get()), st::calendarScroll, st::calendarTitleHeight);
|
||||
_inner->setDateChosenCallback(std::move(_callback));
|
||||
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
||||
subscribe(_context->month(), [this](QDate month) { monthChanged(month); });
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/change_phone_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
@@ -113,10 +113,10 @@ private:
|
||||
};
|
||||
|
||||
void ChangePhoneBox::EnterPhone::prepare() {
|
||||
setTitle(lang(lng_change_phone_title));
|
||||
setTitle(langFactory(lng_change_phone_title));
|
||||
|
||||
auto phoneValue = QString();
|
||||
_phone.create(this, st::defaultInputField, lang(lng_change_phone_new_title), phoneValue);
|
||||
_phone.create(this, st::defaultInputField, langFactory(lng_change_phone_new_title), phoneValue);
|
||||
|
||||
_phone->resize(st::boxWidth - 2 * st::boxPadding.left(), _phone->height());
|
||||
_phone->moveToLeft(st::boxPadding.left(), st::boxLittleSkip);
|
||||
@@ -128,8 +128,8 @@ void ChangePhoneBox::EnterPhone::prepare() {
|
||||
|
||||
setDimensions(st::boxWidth, description->bottomNoMargins() + st::boxLittleSkip);
|
||||
|
||||
addButton(lang(lng_change_phone_new_submit), [this] { submit(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_change_phone_new_submit), [this] { submit(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterPhone::submit() {
|
||||
@@ -206,14 +206,14 @@ ChangePhoneBox::EnterCode::EnterCode(QWidget*, const QString &phone, const QStri
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterCode::prepare() {
|
||||
setTitle(lang(lng_change_phone_title));
|
||||
setTitle(langFactory(lng_change_phone_title));
|
||||
|
||||
auto descriptionText = lng_change_phone_code_description(lt_phone, textcmdStartSemibold() + App::formatPhone(_phone) + textcmdStopSemibold());
|
||||
auto description = object_ptr<Ui::FlatLabel>(this, descriptionText, Ui::FlatLabel::InitType::Rich, st::changePhoneLabel);
|
||||
description->moveToLeft(st::boxPadding.left(), 0);
|
||||
|
||||
auto phoneValue = QString();
|
||||
_code.create(this, st::defaultInputField, lang(lng_change_phone_code_title), phoneValue);
|
||||
_code.create(this, st::defaultInputField, langFactory(lng_change_phone_code_title), phoneValue);
|
||||
_code->setAutoSubmit(_codeLength, [this] { submit(); });
|
||||
_code->setChangedCallback([this] { hideError(); });
|
||||
|
||||
@@ -228,8 +228,8 @@ void ChangePhoneBox::EnterCode::prepare() {
|
||||
updateCall();
|
||||
}
|
||||
|
||||
addButton(lang(lng_change_phone_new_submit), [this] { submit(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_change_phone_new_submit), [this] { submit(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}
|
||||
|
||||
int ChangePhoneBox::EnterCode::countHeight() {
|
||||
@@ -302,13 +302,13 @@ bool ChangePhoneBox::EnterCode::sendCodeFail(const RPCError &error) {
|
||||
}
|
||||
|
||||
void ChangePhoneBox::prepare() {
|
||||
setTitle(lang(lng_change_phone_title));
|
||||
addButton(lang(lng_change_phone_button), [] {
|
||||
setTitle(langFactory(lng_change_phone_title));
|
||||
addButton(langFactory(lng_change_phone_button), [] {
|
||||
Ui::show(Box<ConfirmBox>(lang(lng_change_phone_warning), [] {
|
||||
Ui::show(Box<EnterPhone>());
|
||||
}));
|
||||
});
|
||||
addButton(lang(lng_cancel), [this] {
|
||||
addButton(langFactory(lng_cancel), [this] {
|
||||
closeBox();
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/confirm_box.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
@@ -33,6 +33,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "core/click_handler_types.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "auth_session.h"
|
||||
#include "observer_peer.h"
|
||||
|
||||
TextParseOptions _confirmBoxTextOptions = {
|
||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||
@@ -115,9 +116,9 @@ void ConfirmBox::init(const QString &text) {
|
||||
}
|
||||
|
||||
void ConfirmBox::prepare() {
|
||||
addButton(_confirmText, [this] { confirmed(); }, _confirmStyle);
|
||||
addButton([this] { return _confirmText; }, [this] { confirmed(); }, _confirmStyle);
|
||||
if (!_informative) {
|
||||
addButton(_cancelText, [this] { _cancelled = true; closeBox(); });
|
||||
addButton([this] { return _cancelText; }, [this] { _cancelled = true; closeBox(); });
|
||||
}
|
||||
textUpdated();
|
||||
}
|
||||
@@ -186,9 +187,8 @@ void ConfirmBox::updateLink() {
|
||||
}
|
||||
|
||||
void ConfirmBox::updateHover() {
|
||||
QPoint m(mapFromGlobal(_lastMousePos));
|
||||
|
||||
auto state = _text.getStateLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width());
|
||||
auto m = mapFromGlobal(_lastMousePos);
|
||||
auto state = _text.getStateLeft(m - QPoint(st::boxPadding.left(), st::boxPadding.top()), _textWidth, width());
|
||||
|
||||
ClickHandler::setActive(state.link, this);
|
||||
}
|
||||
@@ -217,19 +217,25 @@ InformBox::InformBox(QWidget*, const QString &text, base::lambda<void()> closedC
|
||||
InformBox::InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda<void()> closedCallback) : ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, std::move(closedCallback)) {
|
||||
}
|
||||
|
||||
MaxInviteBox::MaxInviteBox(QWidget*, const QString &link)
|
||||
: _text(st::boxLabelStyle, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
|
||||
, _link(link) {
|
||||
MaxInviteBox::MaxInviteBox(QWidget*, gsl::not_null<ChannelData*> channel) : BoxContent()
|
||||
, _channel(channel)
|
||||
, _text(st::boxLabelStyle, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) {
|
||||
}
|
||||
|
||||
void MaxInviteBox::prepare() {
|
||||
setMouseTracking(true);
|
||||
|
||||
addButton(lang(lng_box_ok), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
|
||||
|
||||
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
|
||||
_textHeight = qMin(_text.countHeight(_textWidth), 16 * st::boxLabelStyle.lineHeight);
|
||||
setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom());
|
||||
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::InviteLinkChanged, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _channel) {
|
||||
rtlupdate(_invitationLink);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
@@ -239,8 +245,12 @@ void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
|
||||
mouseMoveEvent(e);
|
||||
if (_linkOver) {
|
||||
Application::clipboard()->setText(_link);
|
||||
Ui::Toast::Show(lang(lng_create_channel_link_copied));
|
||||
if (_channel->inviteLink().isEmpty()) {
|
||||
App::api()->exportInviteLink(_channel);
|
||||
} else {
|
||||
QGuiApplication::clipboard()->setText(_channel->inviteLink());
|
||||
Ui::Toast::Show(lang(lng_create_channel_link_copied));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +282,8 @@ void MaxInviteBox::paintEvent(QPaintEvent *e) {
|
||||
option.setWrapMode(QTextOption::WrapAnywhere);
|
||||
p.setFont(_linkOver ? st::defaultInputField.font->underline() : st::defaultInputField.font);
|
||||
p.setPen(st::defaultLinkButton.color);
|
||||
p.drawText(_invitationLink, _link, option);
|
||||
auto inviteLinkText = _channel->inviteLink().isEmpty() ? lang(lng_group_invite_create) : _channel->inviteLink();
|
||||
p.drawText(_invitationLink, inviteLinkText, option);
|
||||
}
|
||||
|
||||
void MaxInviteBox::resizeEvent(QResizeEvent *e) {
|
||||
@@ -293,10 +304,10 @@ void ConvertToSupergroupBox::prepare() {
|
||||
text.push_back(lang(lng_profile_convert_feature3));
|
||||
text.push_back(lang(lng_profile_convert_feature4));
|
||||
|
||||
setTitle(lang(lng_profile_convert_title));
|
||||
setTitle(langFactory(lng_profile_convert_title));
|
||||
|
||||
addButton(lang(lng_profile_convert_confirm), [this] { convertToSupergroup(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_profile_convert_confirm), [this] { convertToSupergroup(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
_text.setText(st::boxLabelStyle, text.join('\n'), _confirmBoxTextOptions);
|
||||
_note.setText(st::boxLabelStyle, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions);
|
||||
@@ -363,8 +374,8 @@ PinMessageBox::PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId)
|
||||
}
|
||||
|
||||
void PinMessageBox::prepare() {
|
||||
addButton(lang(lng_pinned_pin), [this] { pinMessage(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_pinned_pin), [this] { pinMessage(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom());
|
||||
}
|
||||
@@ -408,9 +419,13 @@ bool PinMessageBox::pinFail(const RPCError &error) {
|
||||
|
||||
DeleteMessagesBox::DeleteMessagesBox(QWidget*, HistoryItem *item, bool suggestModerateActions) : _singleItem(true) {
|
||||
_ids.push_back(item->fullId());
|
||||
if (suggestModerateActions && item->suggestBanReportDeleteAll()) {
|
||||
_moderateFrom = item->from()->asUser();
|
||||
_moderateInChannel = item->history()->peer->asChannel();
|
||||
if (suggestModerateActions) {
|
||||
_moderateBan = item->suggestBanReport();
|
||||
_moderateDeleteAll = item->suggestDeleteAllReport();
|
||||
if (_moderateBan || _moderateDeleteAll) {
|
||||
_moderateFrom = item->from()->asUser();
|
||||
_moderateInChannel = item->history()->peer->asChannel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,9 +443,13 @@ void DeleteMessagesBox::prepare() {
|
||||
if (_moderateFrom) {
|
||||
t_assert(_moderateInChannel != nullptr);
|
||||
text = lang(lng_selected_delete_sure_this);
|
||||
_banUser.create(this, lang(lng_ban_user), false, st::defaultBoxCheckbox);
|
||||
if (_moderateBan) {
|
||||
_banUser.create(this, lang(lng_ban_user), false, st::defaultBoxCheckbox);
|
||||
}
|
||||
_reportSpam.create(this, lang(lng_report_spam), false, st::defaultBoxCheckbox);
|
||||
_deleteAll.create(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox);
|
||||
if (_moderateDeleteAll) {
|
||||
_deleteAll.create(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox);
|
||||
}
|
||||
} else {
|
||||
text = _singleItem ? lang(lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, _ids.size());
|
||||
auto canDeleteAllForEveryone = true;
|
||||
@@ -471,12 +490,19 @@ void DeleteMessagesBox::prepare() {
|
||||
}
|
||||
_text.create(this, text, Ui::FlatLabel::InitType::Simple, st::boxLabel);
|
||||
|
||||
addButton(lang(lng_box_delete), [this] { deleteAndClear(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_box_delete), [this] { deleteAndClear(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
auto fullHeight = st::boxPadding.top() + _text->height() + st::boxPadding.bottom();
|
||||
if (_moderateFrom) {
|
||||
fullHeight += st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins();
|
||||
fullHeight += st::boxMediumSkip;
|
||||
if (_banUser) {
|
||||
fullHeight += _banUser->heightNoMargins() + st::boxLittleSkip;
|
||||
}
|
||||
fullHeight += _reportSpam->heightNoMargins();
|
||||
if (_deleteAll) {
|
||||
fullHeight += st::boxLittleSkip + _deleteAll->heightNoMargins();
|
||||
}
|
||||
} else if (_forEveryone) {
|
||||
fullHeight += st::boxMediumSkip + _forEveryone->heightNoMargins();
|
||||
}
|
||||
@@ -487,9 +513,16 @@ void DeleteMessagesBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
_text->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
|
||||
if (_moderateFrom) {
|
||||
_banUser->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip);
|
||||
_reportSpam->moveToLeft(st::boxPadding.left(), _banUser->bottomNoMargins() + st::boxLittleSkip);
|
||||
_deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->bottomNoMargins() + st::boxLittleSkip);
|
||||
auto top = _text->bottomNoMargins() + st::boxMediumSkip;
|
||||
if (_banUser) {
|
||||
_banUser->moveToLeft(st::boxPadding.left(), top);
|
||||
top += _banUser->heightNoMargins() + st::boxLittleSkip;
|
||||
}
|
||||
_reportSpam->moveToLeft(st::boxPadding.left(), top);
|
||||
top += _reportSpam->heightNoMargins() + st::boxLittleSkip;
|
||||
if (_deleteAll) {
|
||||
_deleteAll->moveToLeft(st::boxPadding.left(), top);
|
||||
}
|
||||
} else if (_forEveryone) {
|
||||
_forEveryone->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip);
|
||||
}
|
||||
@@ -509,13 +542,13 @@ void DeleteMessagesBox::deleteAndClear() {
|
||||
}
|
||||
|
||||
if (_moderateFrom) {
|
||||
if (_banUser->checked()) {
|
||||
MTP::send(MTPchannels_KickFromChannel(_moderateInChannel->inputChannel, _moderateFrom->inputUser, MTP_boolTrue()), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
|
||||
if (_banUser && _banUser->checked()) {
|
||||
App::api()->kickParticipant(_moderateInChannel, _moderateFrom, MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
|
||||
}
|
||||
if (_reportSpam->checked()) {
|
||||
MTP::send(MTPchannels_ReportSpam(_moderateInChannel->inputChannel, _moderateFrom->inputUser, MTP_vector<MTPint>(1, MTP_int(_ids[0].msg))));
|
||||
}
|
||||
if (_deleteAll->checked()) {
|
||||
if (_deleteAll && _deleteAll->checked()) {
|
||||
App::main()->deleteAllFromUser(_moderateInChannel, _moderateFrom);
|
||||
}
|
||||
}
|
||||
@@ -547,14 +580,18 @@ void DeleteMessagesBox::deleteAndClear() {
|
||||
Ui::hideLayer();
|
||||
}
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
|
||||
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
|
||||
: _title(this, st::confirmInviteTitle)
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _participants(participants) {
|
||||
_title->setText(title);
|
||||
QString status;
|
||||
if (_participants.isEmpty() || _participants.size() >= count) {
|
||||
status = lng_chat_status_members(lt_count, count);
|
||||
if (count > 0) {
|
||||
status = lng_chat_status_members(lt_count, count);
|
||||
} else {
|
||||
status = lang(isChannel ? lng_channel_status : lng_group_status);
|
||||
}
|
||||
} else {
|
||||
status = lng_group_invite_members(lt_count, count);
|
||||
}
|
||||
@@ -576,12 +613,12 @@ ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChat
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::prepare() {
|
||||
addButton(lang(lng_group_invite_join), [this] {
|
||||
addButton(langFactory(lng_group_invite_join), [this] {
|
||||
if (auto main = App::main()) {
|
||||
main->onInviteImport();
|
||||
}
|
||||
});
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
if (_participants.size() > 4) {
|
||||
_participants.resize(4);
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
|
||||
class MaxInviteBox : public BoxContent {
|
||||
public:
|
||||
MaxInviteBox(QWidget*, const QString &link);
|
||||
MaxInviteBox(QWidget*, gsl::not_null<ChannelData*> channel);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
@@ -114,10 +114,11 @@ protected:
|
||||
private:
|
||||
void updateSelected(const QPoint &cursorGlobalPosition);
|
||||
|
||||
gsl::not_null<ChannelData*> _channel;
|
||||
|
||||
Text _text;
|
||||
int32 _textWidth, _textHeight;
|
||||
|
||||
QString _link;
|
||||
QRect _invitationLink;
|
||||
bool _linkOver = false;
|
||||
|
||||
@@ -189,6 +190,8 @@ private:
|
||||
bool _singleItem = false;
|
||||
UserData *_moderateFrom = nullptr;
|
||||
ChannelData *_moderateInChannel = nullptr;
|
||||
bool _moderateBan = false;
|
||||
bool _moderateDeleteAll = false;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _text = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _forEveryone = { nullptr };
|
||||
@@ -200,7 +203,7 @@ private:
|
||||
|
||||
class ConfirmInviteBox : public BoxContent, public RPCSender {
|
||||
public:
|
||||
ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
|
||||
ConfirmInviteBox(QWidget*, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
@@ -26,7 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "mainwidget.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -210,14 +210,14 @@ void ConfirmPhoneBox::prepare() {
|
||||
}
|
||||
_about->setMarkedText(aboutText);
|
||||
|
||||
_code.create(this, st::confirmPhoneCodeField, lang(lng_code_ph));
|
||||
_code.create(this, st::confirmPhoneCodeField, langFactory(lng_code_ph));
|
||||
_code->setAutoSubmit(_sentCodeLength, [this] { onSendCode(); });
|
||||
_code->setChangedCallback([this] { showError(QString()); });
|
||||
|
||||
setTitle(lang(lng_confirm_phone_title));
|
||||
setTitle(langFactory(lng_confirm_phone_title));
|
||||
|
||||
addButton(lang(lng_confirm_phone_send), [this] { onSendCode(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_confirm_phone_send), [this] { onSendCode(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class FlatLabel;
|
||||
|
||||
class SentCodeField : public Ui::InputField {
|
||||
public:
|
||||
SentCodeField(QWidget *parent, const style::InputField &st, const QString &ph = QString(), const QString &val = QString()) : Ui::InputField(parent, st, ph, val) {
|
||||
SentCodeField(QWidget *parent, const style::InputField &st, base::lambda<QString()> placeholderFactory = base::lambda<QString()>(), const QString &val = QString()) : Ui::InputField(parent, st, std::move(placeholderFactory), val) {
|
||||
connect(this, &Ui::InputField::changed, [this] { fix(); });
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/connection_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
@@ -30,11 +31,36 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "history/history_location_manager.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
void ConnectionBox::ShowApplyProxyConfirmation(const QMap<QString, QString> &fields) {
|
||||
auto server = fields.value(qsl("server"));
|
||||
auto port = fields.value(qsl("port")).toInt();
|
||||
if (!server.isEmpty() && port != 0) {
|
||||
auto weakBox = std::make_shared<QPointer<ConfirmBox>>(nullptr);
|
||||
auto box = Ui::show(Box<ConfirmBox>(lng_sure_enable_socks(lt_server, server, lt_port, QString::number(port)), lang(lng_sure_enable), [fields, weakBox] {
|
||||
auto p = ProxyData();
|
||||
p.host = fields.value(qsl("server"));
|
||||
p.user = fields.value(qsl("user"));
|
||||
p.password = fields.value(qsl("pass"));
|
||||
p.port = fields.value(qsl("port")).toInt();
|
||||
Global::SetConnectionType(dbictTcpProxy);
|
||||
Global::SetLastProxyType(dbictTcpProxy);
|
||||
Global::SetConnectionProxy(p);
|
||||
Local::writeSettings();
|
||||
Global::RefConnectionTypeChanged().notify();
|
||||
MTP::restart();
|
||||
reinitLocationManager();
|
||||
reinitWebLoadManager();
|
||||
if (*weakBox) (*weakBox)->closeBox();
|
||||
}), KeepOtherLayers);
|
||||
*weakBox = box;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionBox::ConnectionBox(QWidget *parent)
|
||||
: _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host)
|
||||
, _portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port))
|
||||
, _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), Global::ConnectionProxy().user)
|
||||
, _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), Global::ConnectionProxy().password)
|
||||
: _hostInput(this, st::connectionHostInputField, langFactory(lng_connection_host_ph), Global::ConnectionProxy().host)
|
||||
, _portInput(this, st::connectionPortInputField, langFactory(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port))
|
||||
, _userInput(this, st::connectionUserInputField, langFactory(lng_connection_user_ph), Global::ConnectionProxy().user)
|
||||
, _passwordInput(this, st::connectionPasswordInputField, langFactory(lng_connection_password_ph), Global::ConnectionProxy().password)
|
||||
, _typeGroup(std::make_shared<Ui::RadioenumGroup<DBIConnectionType>>(Global::ConnectionType()))
|
||||
, _autoRadio(this, _typeGroup, dbictAuto, lang(lng_connection_auto_rb), st::defaultBoxCheckbox)
|
||||
, _httpProxyRadio(this, _typeGroup, dbictHttpProxy, lang(lng_connection_http_proxy_rb), st::defaultBoxCheckbox)
|
||||
@@ -43,10 +69,10 @@ ConnectionBox::ConnectionBox(QWidget *parent)
|
||||
}
|
||||
|
||||
void ConnectionBox::prepare() {
|
||||
setTitle(lang(lng_connection_header));
|
||||
setTitle(langFactory(lng_connection_header));
|
||||
|
||||
addButton(lang(lng_connection_save), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_connection_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
_typeGroup->setChangedCallback([this](DBIConnectionType value) { typeChanged(value); });
|
||||
|
||||
@@ -54,13 +80,21 @@ void ConnectionBox::prepare() {
|
||||
connect(_portInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
||||
connect(_userInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
||||
connect(_passwordInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
||||
connect(_hostInput, SIGNAL(focused()), this, SLOT(onFieldFocus()));
|
||||
connect(_portInput, SIGNAL(focused()), this, SLOT(onFieldFocus()));
|
||||
connect(_userInput, SIGNAL(focused()), this, SLOT(onFieldFocus()));
|
||||
connect(_passwordInput, SIGNAL(focused()), this, SLOT(onFieldFocus()));
|
||||
|
||||
updateControlsVisibility();
|
||||
}
|
||||
|
||||
bool ConnectionBox::badProxyValue() const {
|
||||
return (_hostInput->getLastText().isEmpty() || !_portInput->getLastText().toInt());
|
||||
}
|
||||
|
||||
void ConnectionBox::updateControlsVisibility() {
|
||||
auto newHeight = st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListSkip + _httpProxyRadio->heightNoMargins() + st::boxOptionListSkip + _tcpProxyRadio->heightNoMargins() + st::boxOptionListSkip + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
|
||||
if (_typeGroup->value() == dbictAuto) {
|
||||
if (_typeGroup->value() == dbictAuto && badProxyValue()) {
|
||||
_hostInput->hide();
|
||||
_portInput->hide();
|
||||
_userInput->hide();
|
||||
@@ -78,7 +112,7 @@ void ConnectionBox::updateControlsVisibility() {
|
||||
}
|
||||
|
||||
void ConnectionBox::setInnerFocus() {
|
||||
if (_hostInput->isHidden()) {
|
||||
if (_typeGroup->value() == dbictAuto) {
|
||||
setFocus();
|
||||
} else {
|
||||
_hostInput->setFocusFast();
|
||||
@@ -93,34 +127,41 @@ void ConnectionBox::resizeEvent(QResizeEvent *e) {
|
||||
|
||||
void ConnectionBox::updateControlsPosition() {
|
||||
auto type = _typeGroup->value();
|
||||
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
|
||||
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->getMargins().top() + st::boxOptionListPadding.top());
|
||||
_httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListSkip);
|
||||
|
||||
auto inputy = 0;
|
||||
if (type == dbictHttpProxy) {
|
||||
auto fieldsVisible = (type != dbictAuto) || (!badProxyValue() && Global::LastProxyType() != dbictAuto);
|
||||
auto fieldsBelowHttp = fieldsVisible && (type == dbictHttpProxy || (type == dbictAuto && Global::LastProxyType() == dbictHttpProxy));
|
||||
auto fieldsBelowTcp = fieldsVisible && (type == dbictTcpProxy || (type == dbictAuto && Global::LastProxyType() == dbictTcpProxy));
|
||||
if (fieldsBelowHttp) {
|
||||
inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
|
||||
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip);
|
||||
} else {
|
||||
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListSkip);
|
||||
if (type == dbictTcpProxy) {
|
||||
if (fieldsBelowTcp) {
|
||||
inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
|
||||
}
|
||||
}
|
||||
|
||||
if (inputy) {
|
||||
_hostInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), inputy);
|
||||
_hostInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), inputy);
|
||||
_portInput->moveToRight(st::boxPadding.right(), inputy);
|
||||
_userInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), _hostInput->y() + _hostInput->height() + st::boxOptionInputSkip);
|
||||
_userInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), _hostInput->y() + _hostInput->height() + st::boxOptionInputSkip);
|
||||
_passwordInput->moveToRight(st::boxPadding.right(), _userInput->y());
|
||||
}
|
||||
|
||||
auto tryipv6y = ((type == dbictTcpProxy) ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListSkip + st::connectionIPv6Skip;
|
||||
auto tryipv6y = (fieldsBelowTcp ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListSkip + st::connectionIPv6Skip;
|
||||
_tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y);
|
||||
}
|
||||
|
||||
void ConnectionBox::typeChanged(DBIConnectionType type) {
|
||||
if (type == dbictAuto) {
|
||||
setFocus();
|
||||
}
|
||||
updateControlsVisibility();
|
||||
if (type != dbictAuto) {
|
||||
Global::SetLastProxyType(type);
|
||||
if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() && !_passwordInput->hasFocus()) {
|
||||
_hostInput->setFocusFast();
|
||||
}
|
||||
@@ -132,7 +173,16 @@ void ConnectionBox::typeChanged(DBIConnectionType type) {
|
||||
update();
|
||||
}
|
||||
|
||||
void ConnectionBox::onFieldFocus() {
|
||||
if (Global::LastProxyType() == dbictHttpProxy) {
|
||||
_typeGroup->setValue(dbictHttpProxy);
|
||||
} else if (Global::LastProxyType() == dbictTcpProxy) {
|
||||
_typeGroup->setValue(dbictTcpProxy);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionBox::onSubmit() {
|
||||
onFieldFocus();
|
||||
if (_hostInput->hasFocus()) {
|
||||
if (!_hostInput->getLastText().trimmed().isEmpty()) {
|
||||
_portInput->setFocus();
|
||||
@@ -161,30 +211,33 @@ void ConnectionBox::onSubmit() {
|
||||
}
|
||||
|
||||
void ConnectionBox::onSave() {
|
||||
auto p = ProxyData();
|
||||
p.host = _hostInput->getLastText().trimmed();
|
||||
p.user = _userInput->getLastText().trimmed();
|
||||
p.password = _passwordInput->getLastText().trimmed();
|
||||
p.port = _portInput->getLastText().toInt();
|
||||
|
||||
auto type = _typeGroup->value();
|
||||
if (type == dbictAuto) {
|
||||
Global::SetConnectionType(type);
|
||||
Global::SetConnectionProxy(ProxyData());
|
||||
if (p.host.isEmpty() || !p.port) {
|
||||
p = ProxyData();
|
||||
}
|
||||
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(false);
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
} else {
|
||||
ProxyData p;
|
||||
p.host = _hostInput->getLastText().trimmed();
|
||||
p.user = _userInput->getLastText().trimmed();
|
||||
p.password = _passwordInput->getLastText().trimmed();
|
||||
p.port = _portInput->getLastText().toInt();
|
||||
if (p.host.isEmpty()) {
|
||||
_hostInput->setFocus();
|
||||
_hostInput->showError();
|
||||
return;
|
||||
} else if (!p.port) {
|
||||
_portInput->setFocus();
|
||||
_portInput->showError();
|
||||
return;
|
||||
}
|
||||
Global::SetConnectionType(type);
|
||||
Global::SetConnectionProxy(p);
|
||||
Global::SetLastProxyType(type);
|
||||
}
|
||||
Global::SetConnectionType(type);
|
||||
Global::SetConnectionProxy(p);
|
||||
if (cPlatform() == dbipWindows && Global::TryIPv6() != _tryIPv6->checked()) {
|
||||
Global::SetTryIPv6(_tryIPv6->checked());
|
||||
Local::writeSettings();
|
||||
@@ -211,12 +264,12 @@ AutoDownloadBox::AutoDownloadBox(QWidget *parent)
|
||||
, _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate), st::defaultBoxCheckbox)
|
||||
, _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups), st::defaultBoxCheckbox)
|
||||
, _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif(), st::defaultBoxCheckbox)
|
||||
, _sectionHeight(st::boxTitleHeight + 2 * (st::defaultBoxCheckbox.height + st::setLittleSkip)) {
|
||||
, _sectionHeight(st::boxTitleHeight + 2 * (st::defaultCheck.diameter + st::setLittleSkip)) {
|
||||
}
|
||||
|
||||
void AutoDownloadBox::prepare() {
|
||||
addButton(lang(lng_connection_save), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_connection_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, 3 * _sectionHeight - st::autoDownloadTopDelta + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ class ConnectionBox : public BoxContent {
|
||||
public:
|
||||
ConnectionBox(QWidget *parent);
|
||||
|
||||
static void ShowApplyProxyConfirmation(const QMap<QString, QString> &fields);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
void setInnerFocus() override;
|
||||
@@ -47,12 +49,14 @@ protected:
|
||||
|
||||
private slots:
|
||||
void onSubmit();
|
||||
void onFieldFocus();
|
||||
void onSave();
|
||||
|
||||
private:
|
||||
void typeChanged(DBIConnectionType type);
|
||||
void updateControlsVisibility();
|
||||
void updateControlsPosition();
|
||||
bool badProxyValue() const;
|
||||
|
||||
object_ptr<Ui::InputField> _hostInput;
|
||||
object_ptr<Ui::PortInput> _portInput;
|
||||
|
||||
@@ -25,7 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "boxes/add_contact_box.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
@@ -39,12 +39,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "boxes/photo_crop_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/edit_participant_box.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "observer_peer.h"
|
||||
#include "apiwrap.h"
|
||||
#include "auth_session.h"
|
||||
#include "storage/file_download.h"
|
||||
|
||||
// Not used for now.
|
||||
//
|
||||
//MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||
//, _st(st) {
|
||||
// resize(_st.width, _st.height);
|
||||
// setCursor(style::cur_pointer);
|
||||
//}
|
||||
//
|
||||
//void MembersAddButton::paintEvent(QPaintEvent *e) {
|
||||
// Painter p(this);
|
||||
//
|
||||
// auto ms = getms();
|
||||
// auto over = isOver();
|
||||
// auto down = isDown();
|
||||
//
|
||||
// ((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||
// paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
// ((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||
//}
|
||||
//
|
||||
//QImage MembersAddButton::prepareRippleMask() const {
|
||||
// return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||
//}
|
||||
//
|
||||
//QPoint MembersAddButton::prepareRippleStartPosition() const {
|
||||
// return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||
//}
|
||||
|
||||
QString PeerFloodErrorText(PeerFloodType type) {
|
||||
auto link = textcmdLink(Messenger::Instance().createInternalLinkFull(qsl("spambot")), lang(lng_cant_more_info));
|
||||
if (type == PeerFloodType::InviteGroup) {
|
||||
@@ -113,24 +142,24 @@ void ContactsBox::prepare() {
|
||||
updateTitle();
|
||||
if (_chat) {
|
||||
if (_membersFilter == MembersFilter::Admins) {
|
||||
addButton(lang(lng_settings_save), [this] { saveChatAdmins(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { saveChatAdmins(); });
|
||||
} else {
|
||||
addButton(lang(lng_participant_invite), [this] { inviteParticipants(); });
|
||||
addButton(langFactory(lng_participant_invite), [this] { inviteParticipants(); });
|
||||
}
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
} else if (_channel) {
|
||||
if (_membersFilter != MembersFilter::Admins) {
|
||||
addButton(lang(lng_participant_invite), [this] { inviteParticipants(); });
|
||||
addButton(langFactory(lng_participant_invite), [this] { inviteParticipants(); });
|
||||
}
|
||||
addButton(lang((_creating == CreatingGroupChannel) ? lng_create_group_skip : lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory((_creating == CreatingGroupChannel) ? lng_create_group_skip : lng_cancel), [this] { closeBox(); });
|
||||
} else if (_bot) {
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
} else if (_creating == CreatingGroupGroup) {
|
||||
addButton(lang(lng_create_group_create), [this] { createGroup(); });
|
||||
addButton(lang(lng_create_group_back), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_create_group_create), [this] { createGroup(); });
|
||||
addButton(langFactory(lng_create_group_back), [this] { closeBox(); });
|
||||
} else {
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addLeftButton(lang(lng_profile_add_contact), [] { App::wnd()->onShowAddContact(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
addLeftButton(langFactory(lng_profile_add_contact), [] { App::wnd()->onShowAddContact(); });
|
||||
}
|
||||
|
||||
_inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) {
|
||||
@@ -199,19 +228,18 @@ bool ContactsBox::onSearchByUsername(bool searchCache) {
|
||||
|
||||
void ContactsBox::updateTitle() {
|
||||
if (_chat && _membersFilter == MembersFilter::Admins) {
|
||||
setTitle(lang(lng_channel_admins));
|
||||
setTitle(langFactory(lng_channel_admins));
|
||||
} else if (_chat || _creating != CreatingGroupNone) {
|
||||
auto addingAdmin = _channel && (_membersFilter == MembersFilter::Admins);
|
||||
auto title = lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant);
|
||||
auto additional = (addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax());
|
||||
setTitle(title);
|
||||
setAdditionalTitle(additional);
|
||||
setTitle(langFactory(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant));
|
||||
setAdditionalTitle([additional] { return additional; });
|
||||
} else if (_inner->sharingBotGame()) {
|
||||
setTitle(lang(lng_bot_choose_chat));
|
||||
setTitle(langFactory(lng_bot_choose_chat));
|
||||
} else if (_inner->bot()) {
|
||||
setTitle(lang(lng_bot_choose_group));
|
||||
setTitle(langFactory(lng_bot_choose_group));
|
||||
} else {
|
||||
setTitle(lang(lng_contacts_header));
|
||||
setTitle(langFactory(lng_contacts_header));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +315,7 @@ void ContactsBox::keyPressEvent(QKeyEvent *e) {
|
||||
}
|
||||
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> ContactsBox::createMultiSelect() {
|
||||
auto entity = object_ptr<Ui::MultiSelect>(this, st::contactsMultiSelect, lang(lng_participant_filter));
|
||||
auto entity = object_ptr<Ui::MultiSelect>(this, st::contactsMultiSelect, langFactory(lng_participant_filter));
|
||||
auto margins = style::margins(0, 0, 0, 0);
|
||||
auto callback = [this] { updateScrollSkips(); };
|
||||
return object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>>(this, std::move(entity), margins, std::move(callback));
|
||||
@@ -316,6 +344,13 @@ void ContactsBox::resizeEvent(QResizeEvent *e) {
|
||||
_inner->resize(width(), _inner->height());
|
||||
}
|
||||
|
||||
void ContactsBox::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
for (auto rect : e->region().rects()) {
|
||||
p.fillRect(rect, st::contactsBg);
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::closeHook() {
|
||||
if (_channel && _creating == CreatingGroupChannel) {
|
||||
Ui::showPeerHistory(_channel, ShowAtTheEndMsgId);
|
||||
@@ -344,8 +379,8 @@ void ContactsBox::onPeerSelectedChanged(PeerData *peer, bool checked) {
|
||||
}
|
||||
|
||||
void ContactsBox::inviteParticipants() {
|
||||
QVector<UserData*> users(_inner->selected());
|
||||
if (users.isEmpty()) {
|
||||
auto users = _inner->selected();
|
||||
if (users.empty()) {
|
||||
_select->entity()->setInnerFocus();
|
||||
return;
|
||||
}
|
||||
@@ -363,7 +398,7 @@ void ContactsBox::createGroup() {
|
||||
if (_saveRequestId) return;
|
||||
|
||||
auto users = _inner->selectedInputs();
|
||||
if (users.isEmpty() || (users.size() == 1 && users.at(0).type() == mtpc_inputUserSelf)) {
|
||||
if (users.empty() || (users.size() == 1 && users.at(0).type() == mtpc_inputUserSelf)) {
|
||||
_select->entity()->setInnerFocus();
|
||||
return;
|
||||
}
|
||||
@@ -396,15 +431,16 @@ void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
|
||||
closeBox();
|
||||
return;
|
||||
}
|
||||
ChatData::Admins curadmins = _inner->chat()->admins;
|
||||
QVector<UserData*> newadmins = _inner->selected(), appoint;
|
||||
if (!newadmins.isEmpty()) {
|
||||
auto curadmins = _inner->chat()->admins;
|
||||
auto newadmins = _inner->selected();
|
||||
auto appoint = decltype(newadmins)();
|
||||
if (!newadmins.empty()) {
|
||||
appoint.reserve(newadmins.size());
|
||||
for (int32 i = 0, l = newadmins.size(); i < l; ++i) {
|
||||
ChatData::Admins::iterator c = curadmins.find(newadmins.at(i));
|
||||
for (auto &user : newadmins) {
|
||||
auto c = curadmins.find(user);
|
||||
if (c == curadmins.cend()) {
|
||||
if (newadmins.at(i)->id != peerFromUser(_inner->chat()->creator)) {
|
||||
appoint.push_back(newadmins.at(i));
|
||||
if (user->id != peerFromUser(_inner->chat()->creator)) {
|
||||
appoint.push_back(user);
|
||||
}
|
||||
} else {
|
||||
curadmins.erase(c);
|
||||
@@ -413,10 +449,10 @@ void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
|
||||
}
|
||||
_saveRequestId = 0;
|
||||
|
||||
for_const (UserData *user, curadmins) {
|
||||
for_const (auto user, curadmins) {
|
||||
MTP::send(MTPmessages_EditChatAdmin(_inner->chat()->inputChat, user->inputUser, MTP_boolFalse()), rpcDone(&ContactsBox::removeAdminDone, user), rpcFail(&ContactsBox::editAdminFail), 0, 10);
|
||||
}
|
||||
for_const (UserData *user, appoint) {
|
||||
for_const (auto user, appoint) {
|
||||
MTP::send(MTPmessages_EditChatAdmin(_inner->chat()->inputChat, user->inputUser, MTP_boolTrue()), rpcDone(&ContactsBox::setAdminDone, user), rpcFail(&ContactsBox::editAdminFail), 0, 10);
|
||||
}
|
||||
MTP::sendAnything();
|
||||
@@ -427,7 +463,7 @@ void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::setAdminDone(UserData *user, const MTPBool &result) {
|
||||
void ContactsBox::setAdminDone(gsl::not_null<UserData*> user, const MTPBool &result) {
|
||||
if (mtpIsTrue(result)) {
|
||||
if (_inner->chat()->noParticipantInfo()) {
|
||||
App::api()->requestFullPeer(_inner->chat());
|
||||
@@ -442,7 +478,7 @@ void ContactsBox::setAdminDone(UserData *user, const MTPBool &result) {
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::removeAdminDone(UserData *user, const MTPBool &result) {
|
||||
void ContactsBox::removeAdminDone(gsl::not_null<UserData*> user, const MTPBool &result) {
|
||||
if (mtpIsTrue(result)) {
|
||||
_inner->chat()->admins.remove(user);
|
||||
}
|
||||
@@ -610,7 +646,7 @@ ContactsBox::Inner::Inner(QWidget *parent, UserData *bot) : TWidget(parent)
|
||||
addDialogsToList([](PeerData *peer) {
|
||||
if (peer->isChat() && peer->asChat()->canEdit()) {
|
||||
return true;
|
||||
} else if (peer->isMegagroup() && (peer->asChannel()->amCreator() || peer->asChannel()->amEditor())) {
|
||||
} else if (peer->isMegagroup()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -622,7 +658,7 @@ ContactsBox::Inner::Inner(QWidget *parent, UserData *bot) : TWidget(parent)
|
||||
void ContactsBox::Inner::init() {
|
||||
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||
connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
|
||||
connect(_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged()));
|
||||
subscribe(_allAdmins->checkedChanged, [this](bool checked) { onAllAdminsChanged(); });
|
||||
|
||||
_rowsTop = st::contactsMarginTop;
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
@@ -719,10 +755,10 @@ void ContactsBox::Inner::addBot() {
|
||||
} else if (!info->startGroupToken.isEmpty()) {
|
||||
MTP::send(MTPmessages_StartBot(_bot->inputUser, _addToPeer->input, MTP_long(rand_value<uint64>()), MTP_string(info->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, { _bot, _addToPeer }));
|
||||
} else {
|
||||
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
||||
App::main()->addParticipants(_addToPeer, std::vector<gsl::not_null<UserData*>>(1, _bot));
|
||||
}
|
||||
} else {
|
||||
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
||||
App::main()->addParticipants(_addToPeer, std::vector<gsl::not_null<UserData*>>(1, _bot));
|
||||
}
|
||||
Ui::hideLayer();
|
||||
Ui::showPeerHistory(_addToPeer, ShowAtUnreadMsgId);
|
||||
@@ -737,50 +773,6 @@ void ContactsBox::Inner::onAllAdminsChanged() {
|
||||
update();
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::addAdminDone(const MTPUpdates &result, mtpRequestId req) {
|
||||
if (App::main()) App::main()->sentUpdatesReceived(result);
|
||||
if (req != _addAdminRequestId) return;
|
||||
|
||||
_addAdminRequestId = 0;
|
||||
if (_addAdmin && _channel && _channel->isMegagroup()) {
|
||||
Notify::PeerUpdate update(_channel);
|
||||
if (_channel->mgInfo->lastParticipants.indexOf(_addAdmin) < 0) {
|
||||
_channel->mgInfo->lastParticipants.push_front(_addAdmin);
|
||||
update.flags |= Notify::PeerUpdate::Flag::MembersChanged;
|
||||
}
|
||||
_channel->mgInfo->lastAdmins.insert(_addAdmin);
|
||||
update.flags |= Notify::PeerUpdate::Flag::AdminsChanged;
|
||||
if (_addAdmin->botInfo) {
|
||||
_channel->mgInfo->bots.insert(_addAdmin);
|
||||
if (_channel->mgInfo->botStatus != 0 && _channel->mgInfo->botStatus < 2) {
|
||||
_channel->mgInfo->botStatus = 2;
|
||||
}
|
||||
}
|
||||
Notify::peerUpdatedDelayed(update);
|
||||
}
|
||||
if (_addAdminBox) _addAdminBox->closeBox();
|
||||
emit adminAdded();
|
||||
}
|
||||
|
||||
bool ContactsBox::Inner::addAdminFail(const RPCError &error, mtpRequestId req) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
if (req != _addAdminRequestId) return true;
|
||||
|
||||
_addAdminRequestId = 0;
|
||||
if (_addAdminBox) _addAdminBox->closeBox();
|
||||
if (error.type() == "USERS_TOO_MUCH") {
|
||||
Ui::show(Box<MaxInviteBox>(_channel->inviteLink()), KeepOtherLayers);
|
||||
} else if (error.type() == "ADMINS_TOO_MUCH") {
|
||||
Ui::show(Box<InformBox>(lang(lng_channel_admins_too_much)), KeepOtherLayers);
|
||||
} else if (error.type() == qstr("USER_RESTRICTED")) {
|
||||
Ui::show(Box<InformBox>(lang(lng_cant_do_this)), KeepOtherLayers);
|
||||
} else {
|
||||
emit adminAdded();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::saving(bool flag) {
|
||||
_saving = flag;
|
||||
_allAdminsChecked = _allAdmins->checked();
|
||||
@@ -899,11 +891,13 @@ ContactsBox::Inner::ContactData *ContactsBox::Inner::contactData(Dialogs::Row *r
|
||||
data->statusText = App::onlineText(peer->asUser(), _time);
|
||||
data->statusHasOnlineColor = App::onlineColorUse(peer->asUser(), _time);
|
||||
} else if (peer->isChat()) {
|
||||
ChatData *chat = peer->asChat();
|
||||
auto chat = peer->asChat();
|
||||
if (!chat->amIn()) {
|
||||
data->statusText = lang(lng_chat_status_unaccessible);
|
||||
} else {
|
||||
} else if (chat->count > 0) {
|
||||
data->statusText = lng_chat_status_members(lt_count, chat->count);
|
||||
} else {
|
||||
data->statusText = lang(lng_group_status);
|
||||
}
|
||||
} else if (peer->isMegagroup()) {
|
||||
data->statusText = lang(lng_group_status);
|
||||
@@ -1241,9 +1235,12 @@ void ContactsBox::Inner::leaveEventHook(QEvent *e) {
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
_mouseSelection = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSelection();
|
||||
auto position = e->globalPos();
|
||||
if (_mouseSelection || _lastMousePos != position) {
|
||||
_mouseSelection = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||
@@ -1334,112 +1331,133 @@ void ContactsBox::Inner::setSearchedPressed(int pressed) {
|
||||
_searchedPressed = pressed;
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::chooseParticipant() {
|
||||
if (_saving) return;
|
||||
bool addingAdmin = (_channel && _membersFilter == MembersFilter::Admins);
|
||||
if (!addingAdmin && usingMultiSelect()) {
|
||||
_time = unixtime();
|
||||
if (_filter.isEmpty()) {
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsername.size()) {
|
||||
auto data = d_byUsername[_searchedSelected];
|
||||
auto peer = _byUsername[_searchedSelected];
|
||||
if (data->disabledChecked) return;
|
||||
void ContactsBox::Inner::changeMultiSelectCheckState() {
|
||||
_time = unixtime();
|
||||
if (_filter.isEmpty()) {
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsername.size()) {
|
||||
auto data = d_byUsername[_searchedSelected];
|
||||
auto peer = _byUsername[_searchedSelected];
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
changeCheckState(data, peer);
|
||||
} else if (_selected) {
|
||||
auto data = contactData(_selected);
|
||||
auto peer = _selected->history()->peer;
|
||||
if (data->disabledChecked) return;
|
||||
changeCheckState(data, peer);
|
||||
} else if (_selected) {
|
||||
auto data = contactData(_selected);
|
||||
auto peer = _selected->history()->peer;
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
changeCheckState(_selected);
|
||||
}
|
||||
} else {
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsernameFiltered.size()) {
|
||||
auto data = d_byUsernameFiltered[_searchedSelected];
|
||||
auto peer = _byUsernameFiltered[_searchedSelected];
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
int i = 0, l = d_byUsername.size();
|
||||
for (; i < l; ++i) {
|
||||
if (d_byUsername[i] == data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == l) {
|
||||
d_byUsername.push_back(data);
|
||||
_byUsername.push_back(peer);
|
||||
for (i = 0, l = _byUsernameDatas.size(); i < l;) {
|
||||
if (_byUsernameDatas[i] == data) {
|
||||
_byUsernameDatas.removeAt(i);
|
||||
--l;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
changeCheckState(data, peer);
|
||||
} else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) {
|
||||
auto data = contactData(_filtered[_filteredSelected]);
|
||||
auto peer = _filtered[_filteredSelected]->history()->peer;
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
changeCheckState(data, peer);
|
||||
}
|
||||
changeCheckState(_selected);
|
||||
}
|
||||
} else {
|
||||
PeerData *peer = 0;
|
||||
if (_filter.isEmpty()) {
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsername.size()) {
|
||||
peer = _byUsername[_searchedSelected];
|
||||
} else if (_selected) {
|
||||
peer = _selected->history()->peer;
|
||||
}
|
||||
} else {
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsernameFiltered.size()) {
|
||||
peer = _byUsernameFiltered[_searchedSelected];
|
||||
} else {
|
||||
if (_filteredSelected < 0 || _filteredSelected >= _filtered.size()) return;
|
||||
peer = _filtered[_filteredSelected]->history()->peer;
|
||||
}
|
||||
}
|
||||
if (peer) {
|
||||
if (addingAdmin) {
|
||||
_addAdmin = peer->asUser();
|
||||
if (_addAdminRequestId) {
|
||||
MTP::cancel(_addAdminRequestId);
|
||||
_addAdminRequestId = 0;
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsernameFiltered.size()) {
|
||||
auto data = d_byUsernameFiltered[_searchedSelected];
|
||||
auto peer = _byUsernameFiltered[_searchedSelected];
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
int i = 0, l = d_byUsername.size();
|
||||
for (; i < l; ++i) {
|
||||
if (d_byUsername[i] == data) {
|
||||
break;
|
||||
}
|
||||
if (_addAdminBox) _addAdminBox->deleteLater();
|
||||
_addAdminBox = Ui::show(Box<ConfirmBox>(lng_channel_admin_sure(lt_user, _addAdmin->firstName), base::lambda_guarded(this, [this] {
|
||||
if (_addAdminRequestId) return;
|
||||
_addAdminRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _addAdmin->inputUser, MTP_channelRoleEditor()), rpcDone(&Inner::addAdminDone), rpcFail(&Inner::addAdminFail));
|
||||
})), KeepOtherLayers);
|
||||
} else if (sharingBotGame()) {
|
||||
_addToPeer = peer;
|
||||
auto confirmText = [peer] {
|
||||
if (peer->isUser()) {
|
||||
return lng_bot_sure_share_game(lt_user, App::peerName(peer));
|
||||
}
|
||||
return lng_bot_sure_share_game_group(lt_group, peer->name);
|
||||
};
|
||||
Ui::show(Box<ConfirmBox>(confirmText(), base::lambda_guarded(this, [this] {
|
||||
addBot();
|
||||
})), KeepOtherLayers);
|
||||
} else if (bot() && (peer->isChat() || peer->isMegagroup())) {
|
||||
_addToPeer = peer;
|
||||
Ui::show(Box<ConfirmBox>(lng_bot_sure_invite(lt_group, peer->name), base::lambda_guarded(this, [this] {
|
||||
addBot();
|
||||
})), KeepOtherLayers);
|
||||
} else {
|
||||
Ui::hideSettingsAndLayer(true);
|
||||
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
|
||||
}
|
||||
if (i == l) {
|
||||
d_byUsername.push_back(data);
|
||||
_byUsername.push_back(peer);
|
||||
for (i = 0, l = _byUsernameDatas.size(); i < l;) {
|
||||
if (_byUsernameDatas[i] == data) {
|
||||
_byUsernameDatas.removeAt(i);
|
||||
--l;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
changeCheckState(data, peer);
|
||||
} else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) {
|
||||
auto data = contactData(_filtered[_filteredSelected]);
|
||||
auto peer = _filtered[_filteredSelected]->history()->peer;
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
changeCheckState(data, peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PeerData *ContactsBox::Inner::selectedPeer() const {
|
||||
if (_filter.isEmpty()) {
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsername.size()) {
|
||||
return _byUsername[_searchedSelected];
|
||||
} else if (_selected) {
|
||||
return _selected->history()->peer;
|
||||
}
|
||||
} else {
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsernameFiltered.size()) {
|
||||
return _byUsernameFiltered[_searchedSelected];
|
||||
} else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) {
|
||||
return _filtered[_filteredSelected]->history()->peer;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::chooseParticipant() {
|
||||
if (_saving) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (usingMultiSelect()) {
|
||||
changeMultiSelectCheckState();
|
||||
} else {
|
||||
if (_channel && _membersFilter == MembersFilter::Admins) {
|
||||
Unexpected("Not supported any more");
|
||||
} else if (sharingBotGame()) {
|
||||
shareBotGameToSelected();
|
||||
} else if (bot()) {
|
||||
addBotToSelectedGroup();
|
||||
} else if (auto peer = selectedPeer()) {
|
||||
Ui::hideSettingsAndLayer(true);
|
||||
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::shareBotGameToSelected() {
|
||||
_addToPeer = selectedPeer();
|
||||
if (!_addToPeer) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto confirmText = [this] {
|
||||
if (_addToPeer->isUser()) {
|
||||
return lng_bot_sure_share_game(lt_user, App::peerName(_addToPeer));
|
||||
}
|
||||
return lng_bot_sure_share_game_group(lt_group, _addToPeer->name);
|
||||
};
|
||||
Ui::show(Box<ConfirmBox>(confirmText(), base::lambda_guarded(this, [this] {
|
||||
addBot();
|
||||
})), KeepOtherLayers);
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::addBotToSelectedGroup() {
|
||||
_addToPeer = selectedPeer();
|
||||
if (!_addToPeer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto megagroup = _addToPeer->asMegagroup()) {
|
||||
if (!megagroup->canAddMembers()) {
|
||||
Ui::show(Box<InformBox>(lang(lng_error_cant_add_member)), KeepOtherLayers);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_addToPeer->isChat() || _addToPeer->isMegagroup()) {
|
||||
Ui::show(Box<ConfirmBox>(lng_bot_sure_invite(lt_group, _addToPeer->name), base::lambda_guarded(this, [this] {
|
||||
addBot();
|
||||
})), KeepOtherLayers);
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::changeCheckState(Dialogs::Row *row) {
|
||||
changeCheckState(contactData(row), row->history()->peer);
|
||||
}
|
||||
@@ -1453,7 +1471,7 @@ void ContactsBox::Inner::changeCheckState(ContactData *data, PeerData *peer) {
|
||||
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
|
||||
changePeerCheckState(data, peer, true);
|
||||
} else if (_channel && !_channel->isMegagroup()) {
|
||||
Ui::show(Box<MaxInviteBox>(_channel->inviteLink()), KeepOtherLayers);
|
||||
Ui::show(Box<MaxInviteBox>(_channel), KeepOtherLayers);
|
||||
} else if (!_channel && selectedCount() >= Global::ChatSizeMax() && selectedCount() < Global::MegagroupSizeMax()) {
|
||||
Ui::show(Box<InformBox>(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers);
|
||||
}
|
||||
@@ -1539,22 +1557,11 @@ void ContactsBox::Inner::updateSelection() {
|
||||
|
||||
void ContactsBox::Inner::updateFilter(QString filter) {
|
||||
_lastQuery = filter.toLower().trimmed();
|
||||
filter = textSearchKey(filter);
|
||||
|
||||
auto words = TextUtilities::PrepareSearchWords(_lastQuery);
|
||||
filter = words.isEmpty() ? QString() : words.join(' ');
|
||||
|
||||
_time = unixtime();
|
||||
QStringList f;
|
||||
if (!filter.isEmpty()) {
|
||||
QStringList filterList = filter.split(cWordSplit(), QString::SkipEmptyParts);
|
||||
int l = filterList.size();
|
||||
|
||||
f.reserve(l);
|
||||
for (int i = 0; i < l; ++i) {
|
||||
QString filterName = filterList[i].trimmed();
|
||||
if (filterName.isEmpty()) continue;
|
||||
f.push_back(filterName);
|
||||
}
|
||||
filter = f.join(' ');
|
||||
}
|
||||
if (_filter != filter) {
|
||||
_filter = filter;
|
||||
|
||||
@@ -1573,10 +1580,10 @@ void ContactsBox::Inner::updateFilter(QString filter) {
|
||||
} else {
|
||||
if (!_addContactLnk->isHidden()) _addContactLnk->hide();
|
||||
if (!_allAdmins->isHidden()) _allAdmins->hide();
|
||||
QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi;
|
||||
QStringList::const_iterator fb = words.cbegin(), fe = words.cend(), fi;
|
||||
|
||||
_filtered.clear();
|
||||
if (!f.isEmpty()) {
|
||||
if (!words.isEmpty()) {
|
||||
const Dialogs::List *toFilter = nullptr;
|
||||
if (!_contacts->isEmpty()) {
|
||||
for (fi = fb; fi != fe; ++fi) {
|
||||
@@ -1967,8 +1974,8 @@ void ContactsBox::Inner::selectSkipPage(int32 h, int32 dir) {
|
||||
selectSkip(points * dir);
|
||||
}
|
||||
|
||||
QVector<UserData*> ContactsBox::Inner::selected() {
|
||||
QVector<UserData*> result;
|
||||
std::vector<gsl::not_null<UserData*>> ContactsBox::Inner::selected() {
|
||||
std::vector<gsl::not_null<UserData*>> result;
|
||||
if (!usingMultiSelect()) {
|
||||
return result;
|
||||
}
|
||||
@@ -1980,13 +1987,17 @@ QVector<UserData*> ContactsBox::Inner::selected() {
|
||||
}
|
||||
result.reserve(_contactsData.size());
|
||||
for (auto i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
|
||||
if (i.value()->checkbox->checked() && i.key()->isUser()) {
|
||||
result.push_back(i.key()->asUser());
|
||||
if (i.value()->checkbox->checked()) {
|
||||
if (auto user = i.key()->asUser()) {
|
||||
result.push_back(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
if (d_byUsername[i]->checkbox->checked() && _byUsername[i]->isUser()) {
|
||||
result.push_back(_byUsername[i]->asUser());
|
||||
if (d_byUsername[i]->checkbox->checked()) {
|
||||
if (auto user = _byUsername[i]->asUser()) {
|
||||
result.push_back(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -23,7 +23,29 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "core/single_timer.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
#include "boxes/members_box.h"
|
||||
|
||||
enum class MembersFilter {
|
||||
Recent,
|
||||
Admins,
|
||||
};
|
||||
using MembersAlreadyIn = OrderedSet<UserData*>;
|
||||
|
||||
// Not used for now.
|
||||
//
|
||||
//class MembersAddButton : public Ui::RippleButton {
|
||||
//public:
|
||||
// MembersAddButton(QWidget *parent, const style::TwoIconButton &st);
|
||||
//
|
||||
//protected:
|
||||
// void paintEvent(QPaintEvent *e) override;
|
||||
//
|
||||
// QImage prepareRippleMask() const override;
|
||||
// QPoint prepareRippleStartPosition() const override;
|
||||
//
|
||||
//private:
|
||||
// const style::TwoIconButton &_st;
|
||||
//
|
||||
//};
|
||||
|
||||
namespace Dialogs {
|
||||
class Row;
|
||||
@@ -80,6 +102,7 @@ protected:
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> createMultiSelect();
|
||||
@@ -103,8 +126,8 @@ private:
|
||||
void saveAdminsDone(const MTPUpdates &result);
|
||||
void saveSelectedAdmins();
|
||||
void getAdminsDone(const MTPmessages_ChatFull &result);
|
||||
void setAdminDone(UserData *user, const MTPBool &result);
|
||||
void removeAdminDone(UserData *user, const MTPBool &result);
|
||||
void setAdminDone(gsl::not_null<UserData*> user, const MTPBool &result);
|
||||
void removeAdminDone(gsl::not_null<UserData*> user, const MTPBool &result);
|
||||
bool saveAdminsFail(const RPCError &error);
|
||||
bool editAdminFail(const RPCError &error);
|
||||
|
||||
@@ -161,7 +184,7 @@ public:
|
||||
void selectSkip(int32 dir);
|
||||
void selectSkipPage(int32 h, int32 dir);
|
||||
|
||||
QVector<UserData*> selected();
|
||||
std::vector<gsl::not_null<UserData*>> selected();
|
||||
QVector<MTPInputUser> selectedInputs();
|
||||
bool allAdmins() const;
|
||||
void setAllAdminsChangedCallback(base::lambda<void()> allAdminsChangedCallback) {
|
||||
@@ -249,8 +272,6 @@ private:
|
||||
void updateSelectedRow();
|
||||
int getRowTopWithPeer(PeerData *peer) const;
|
||||
void updateRowWithPeer(PeerData *peer);
|
||||
void addAdminDone(const MTPUpdates &result, mtpRequestId req);
|
||||
bool addAdminFail(const RPCError &error, mtpRequestId req);
|
||||
|
||||
void paintDialog(Painter &p, TimeMs ms, PeerData *peer, ContactData *data, bool sel);
|
||||
void paintDisabledCheckUserpic(Painter &p, PeerData *peer, int x, int y, int outerWidth) const;
|
||||
@@ -266,9 +287,13 @@ private:
|
||||
template <typename FilterCallback>
|
||||
void addDialogsToList(FilterCallback callback);
|
||||
|
||||
PeerData *selectedPeer() const;
|
||||
bool usingMultiSelect() const {
|
||||
return (_chat != nullptr) || (_creating != CreatingGroupNone && (!_channel || _membersFilter != MembersFilter::Admins));
|
||||
}
|
||||
void changeMultiSelectCheckState();
|
||||
void shareBotGameToSelected();
|
||||
void addBotToSelectedGroup();
|
||||
|
||||
base::lambda<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
|
||||
|
||||
@@ -291,9 +316,6 @@ private:
|
||||
base::lambda<void()> _allAdminsChangedCallback;
|
||||
|
||||
PeerData *_addToPeer = nullptr;
|
||||
UserData *_addAdmin = nullptr;
|
||||
mtpRequestId _addAdminRequestId = 0;
|
||||
QPointer<ConfirmBox> _addAdminBox;
|
||||
|
||||
int32 _time;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/download_path_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
@@ -39,10 +39,10 @@ DownloadPathBox::DownloadPathBox(QWidget *parent)
|
||||
}
|
||||
|
||||
void DownloadPathBox::prepare() {
|
||||
addButton(lang(lng_connection_save), [this] { save(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_connection_save), [this] { save(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setTitle(lang(lng_download_path_header));
|
||||
setTitle(langFactory(lng_download_path_header));
|
||||
|
||||
_group->setChangedCallback([this](Directory value) { radioChanged(value); });
|
||||
|
||||
@@ -57,11 +57,11 @@ void DownloadPathBox::updateControlsVisibility() {
|
||||
auto custom = (_group->value() == Directory::Custom);
|
||||
_pathLink->setVisible(custom);
|
||||
|
||||
auto newHeight = st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
|
||||
auto newHeight = st::boxOptionListPadding.top() + _default->getMargins().top() + _default->heightNoMargins() + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
|
||||
if (custom) {
|
||||
newHeight += st::downloadPathSkip + _pathLink->height();
|
||||
}
|
||||
newHeight += st::boxOptionListPadding.bottom();
|
||||
newHeight += st::boxOptionListPadding.bottom() + _dir->getMargins().bottom();
|
||||
|
||||
setDimensions(st::boxWideWidth, newHeight);
|
||||
}
|
||||
@@ -69,10 +69,10 @@ void DownloadPathBox::updateControlsVisibility() {
|
||||
void DownloadPathBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
|
||||
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top() + _default->getMargins().top());
|
||||
_temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListSkip);
|
||||
_dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListSkip);
|
||||
auto inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x();
|
||||
auto inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x();
|
||||
auto inputy = _dir->bottomNoMargins() + st::downloadPathSkip;
|
||||
|
||||
_pathLink->moveToLeft(inputx, inputy);
|
||||
@@ -132,6 +132,6 @@ void DownloadPathBox::save() {
|
||||
}
|
||||
|
||||
void DownloadPathBox::setPathText(const QString &text) {
|
||||
auto availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right();
|
||||
auto availw = st::boxWideWidth - st::boxPadding.left() - st::defaultCheck.diameter - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right();
|
||||
_pathLink->setText(st::boxTextFont->elided(text, availw));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/edit_color_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "styles/style_mediaview.h"
|
||||
@@ -643,7 +643,7 @@ EditColorBox::EditColorBox(QWidget*, const QString &title, QColor current) : Box
|
||||
}
|
||||
|
||||
void EditColorBox::prepare() {
|
||||
setTitle(_title);
|
||||
setTitle([this] { return _title; });
|
||||
|
||||
connect(_hueField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
connect(_saturationField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
@@ -661,8 +661,8 @@ void EditColorBox::prepare() {
|
||||
connect(_blueField, SIGNAL(submitted(bool)), this, SLOT(onFieldSubmitted()));
|
||||
connect(_result, SIGNAL(submitted(bool)), this, SLOT(onFieldSubmitted()));
|
||||
|
||||
addButton(lang(lng_settings_save), [this] { saveColor(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { saveColor(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
auto height = st::colorEditSkip + st::colorPickerSize + st::colorEditSkip + st::colorSliderWidth + st::colorEditSkip;
|
||||
setDimensions(st::colorEditWidth, height);
|
||||
|
||||
510
Telegram/SourceFiles/boxes/edit_participant_box.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/edit_participant_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "boxes/calendar_box.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kMaxRestrictDelayDays = 366;
|
||||
constexpr auto kSecondsInDay = 24 * 60 * 60;
|
||||
constexpr auto kSecondsInWeek = 7 * kSecondsInDay;
|
||||
|
||||
template <typename CheckboxesMap, typename DependenciesMap>
|
||||
void ApplyDependencies(CheckboxesMap &checkboxes, DependenciesMap &dependencies, QPointer<Ui::Checkbox> changed) {
|
||||
auto checkAndApply = [&checkboxes](auto &¤t, auto dependency, bool isChecked) {
|
||||
for (auto &&checkbox : checkboxes) {
|
||||
if ((checkbox.first & dependency) && (checkbox.second->checked() == isChecked)) {
|
||||
current->setChecked(isChecked);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
auto applySomeDependency = [&checkboxes, &dependencies, &changed, checkAndApply] {
|
||||
auto result = false;
|
||||
for (auto &&entry : checkboxes) {
|
||||
if (entry.second == changed) {
|
||||
continue;
|
||||
}
|
||||
auto isChecked = entry.second->checked();
|
||||
for (auto &&dependency : dependencies) {
|
||||
if (entry.first & (isChecked ? dependency.first : dependency.second)) {
|
||||
if (checkAndApply(entry.second, (isChecked ? dependency.second : dependency.first), !isChecked)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
while (true) {
|
||||
if (!applySomeDependency()) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class EditParticipantBox::Divider : public TWidget {
|
||||
public:
|
||||
Divider(QWidget *parent) : TWidget(parent) {
|
||||
}
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
};
|
||||
|
||||
int EditParticipantBox::Divider::resizeGetHeight(int newWidth) {
|
||||
return st::rightsDividerHeight;
|
||||
}
|
||||
|
||||
void EditParticipantBox::Divider::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
p.fillRect(e->rect(), st::contactsAboutBg);
|
||||
auto dividerFillTop = myrtlrect(0, 0, width(), st::profileDividerTop.height());
|
||||
st::profileDividerTop.fill(p, dividerFillTop);
|
||||
auto dividerFillBottom = myrtlrect(0, height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height());
|
||||
st::profileDividerBottom.fill(p, dividerFillBottom);
|
||||
}
|
||||
|
||||
class EditParticipantBox::Inner : public TWidget {
|
||||
public:
|
||||
Inner(QWidget *parent, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, bool hasAdminRights);
|
||||
|
||||
template <typename Widget>
|
||||
QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin) {
|
||||
doAddControl(std::move(widget), margin);
|
||||
return static_cast<Widget*>(_rows.back().widget.data());
|
||||
}
|
||||
|
||||
void removeControl(QPointer<TWidget> widget);
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
void doAddControl(object_ptr<TWidget> widget, QMargins margin);
|
||||
|
||||
gsl::not_null<ChannelData*> _channel;
|
||||
gsl::not_null<UserData*> _user;
|
||||
object_ptr<Ui::PeerAvatarButton> _userPhoto;
|
||||
Text _userName;
|
||||
bool _hasAdminRights = false;
|
||||
struct Control {
|
||||
object_ptr<TWidget> widget;
|
||||
QMargins margin;
|
||||
};
|
||||
std::vector<Control> _rows;
|
||||
|
||||
};
|
||||
|
||||
EditParticipantBox::Inner::Inner(QWidget *parent, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, bool hasAdminRights) : TWidget(parent)
|
||||
, _channel(channel)
|
||||
, _user(user)
|
||||
, _userPhoto(this, _user, st::rightsPhotoButton)
|
||||
, _hasAdminRights(hasAdminRights) {
|
||||
_userName.setText(st::rightsNameStyle, App::peerName(_user), _textNameOptions);
|
||||
_userPhoto->setClickedCallback([this] { Ui::showPeerProfile(_user); });
|
||||
}
|
||||
|
||||
void EditParticipantBox::Inner::removeControl(QPointer<TWidget> widget) {
|
||||
auto row = std::find_if(_rows.begin(), _rows.end(), [widget](auto &&row) {
|
||||
return (row.widget == widget);
|
||||
});
|
||||
t_assert(row != _rows.end());
|
||||
row->widget.destroy();
|
||||
_rows.erase(row);
|
||||
}
|
||||
|
||||
void EditParticipantBox::Inner::doAddControl(object_ptr<TWidget> widget, QMargins margin) {
|
||||
widget->setParent(this);
|
||||
_rows.push_back({ std::move(widget), margin });
|
||||
_rows.back().widget->show();
|
||||
}
|
||||
|
||||
int EditParticipantBox::Inner::resizeGetHeight(int newWidth) {
|
||||
_userPhoto->moveToLeft(st::rightsPhotoMargin.left(), st::rightsPhotoMargin.top());
|
||||
auto newHeight = st::rightsPhotoMargin.top() + st::rightsPhotoButton.size + st::rightsPhotoMargin.bottom();
|
||||
for (auto &&row : _rows) {
|
||||
auto rowWidth = newWidth - row.margin.left() - row.margin.right();
|
||||
newHeight += row.margin.top();
|
||||
row.widget->resizeToNaturalWidth(rowWidth);
|
||||
row.widget->moveToLeft(row.margin.left(), newHeight);
|
||||
newHeight += row.widget->heightNoMargins() + row.margin.bottom();
|
||||
}
|
||||
return newHeight;
|
||||
}
|
||||
|
||||
void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
p.fillRect(e->rect(), st::boxBg);
|
||||
|
||||
p.setPen(st::contactsNameFg);
|
||||
auto namex = st::rightsPhotoMargin.left() + st::rightsPhotoButton.size + st::rightsPhotoMargin.right();
|
||||
auto namew = width() - namex - st::rightsPhotoMargin.right();
|
||||
_userName.drawLeftElided(p, namex, st::rightsPhotoMargin.top() + st::rightsNameTop, namew, width());
|
||||
auto statusText = [this] {
|
||||
if (_user->botInfo) {
|
||||
auto seesAllMessages = (_user->botInfo->readsAllHistory || _hasAdminRights);
|
||||
return lang(seesAllMessages ? lng_status_bot_reads_all : lng_status_bot_not_reads_all);
|
||||
}
|
||||
return App::onlineText(_user->onlineTill, unixtime());
|
||||
};
|
||||
p.setFont(st::contactsStatusFont);
|
||||
p.setPen(st::contactsStatusFg);
|
||||
p.drawTextLeft(namex, st::rightsPhotoMargin.top() + st::rightsStatusTop, width(), statusText());
|
||||
}
|
||||
|
||||
EditParticipantBox::EditParticipantBox(QWidget*, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, bool hasAdminRights) : BoxContent()
|
||||
, _channel(channel)
|
||||
, _user(user)
|
||||
, _hasAdminRights(hasAdminRights) {
|
||||
}
|
||||
|
||||
void EditParticipantBox::prepare() {
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, _channel, _user, hasAdminRights()));
|
||||
}
|
||||
|
||||
template <typename Widget>
|
||||
QPointer<Widget> EditParticipantBox::addControl(object_ptr<Widget> widget, QMargins margin) {
|
||||
Expects(_inner != nullptr);
|
||||
return _inner->addControl(std::move(widget), margin);
|
||||
}
|
||||
|
||||
void EditParticipantBox::removeControl(QPointer<TWidget> widget) {
|
||||
Expects(_inner != nullptr);
|
||||
return _inner->removeControl(widget);
|
||||
}
|
||||
|
||||
void EditParticipantBox::resizeToContent() {
|
||||
_inner->resizeToWidth(st::boxWideWidth);
|
||||
setDimensions(_inner->width(), qMin(_inner->height(), st::boxMaxListHeight));
|
||||
}
|
||||
|
||||
EditAdminBox::EditAdminBox(QWidget*, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, const MTPChannelAdminRights &rights) : EditParticipantBox(nullptr, channel, user, (rights.c_channelAdminRights().vflags.v != 0))
|
||||
, _oldRights(rights) {
|
||||
auto dependency = [this](Flag dependent, Flag dependency) {
|
||||
_dependencies.push_back(std::make_pair(dependent, dependency));
|
||||
};
|
||||
dependency(Flag::f_invite_link, Flag::f_invite_users); // invite_link <-> invite_users
|
||||
dependency(Flag::f_invite_users, Flag::f_invite_link);
|
||||
}
|
||||
|
||||
MTPChannelAdminRights EditAdminBox::DefaultRights(gsl::not_null<ChannelData*> channel) {
|
||||
auto defaultRights = channel->isMegagroup()
|
||||
? (Flag::f_change_info | Flag::f_delete_messages | Flag::f_ban_users | Flag::f_invite_users | Flag::f_invite_link | Flag::f_pin_messages)
|
||||
: (Flag::f_change_info | Flag::f_post_messages | Flag::f_edit_messages | Flag::f_delete_messages | Flag::f_invite_users | Flag::f_invite_link);
|
||||
return MTP_channelAdminRights(MTP_flags(defaultRights));
|
||||
}
|
||||
|
||||
void EditAdminBox::prepare() {
|
||||
EditParticipantBox::prepare();
|
||||
|
||||
auto hadRights = _oldRights.c_channelAdminRights().vflags.v;
|
||||
setTitle(langFactory(hadRights ? lng_rights_edit_admin : lng_channel_add_admin));
|
||||
|
||||
addControl(object_ptr<Divider>(this), QMargins());
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_edit_admin_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
|
||||
auto prepareRights = (hadRights ? _oldRights : DefaultRights(channel()));
|
||||
auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) {
|
||||
auto checked = (prepareRights.c_channelAdminRights().vflags.v & flags) != 0;
|
||||
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin);
|
||||
subscribe(control->checkedChanged, [this, control](bool checked) {
|
||||
InvokeQueued(this, [this, control] { applyDependencies(control); });
|
||||
});
|
||||
if (!channel()->amCreator()) {
|
||||
if (!(channel()->adminRights().vflags.v & flags)) {
|
||||
control->setDisabled(true); // Grey out options that we don't have ourselves.
|
||||
}
|
||||
}
|
||||
if (!canSave()) {
|
||||
control->setDisabled(true);
|
||||
}
|
||||
_checkboxes.emplace(flags, control);
|
||||
};
|
||||
if (channel()->isMegagroup()) {
|
||||
addCheckbox(Flag::f_change_info, lang(lng_rights_group_info));
|
||||
addCheckbox(Flag::f_delete_messages, lang(lng_rights_group_delete));
|
||||
addCheckbox(Flag::f_ban_users, lang(lng_rights_group_ban));
|
||||
addCheckbox(Flag::f_invite_users | Flag::f_invite_link, lang(channel()->anyoneCanAddMembers() ? lng_rights_group_invite_link : lng_rights_group_invite));
|
||||
addCheckbox(Flag::f_pin_messages, lang(lng_rights_group_pin));
|
||||
addCheckbox(Flag::f_add_admins, lang(lng_rights_add_admins));
|
||||
} else {
|
||||
addCheckbox(Flag::f_change_info, lang(lng_rights_channel_info));
|
||||
addCheckbox(Flag::f_post_messages, lang(lng_rights_channel_post));
|
||||
addCheckbox(Flag::f_edit_messages, lang(lng_rights_channel_edit));
|
||||
addCheckbox(Flag::f_delete_messages, lang(lng_rights_channel_delete));
|
||||
addCheckbox(Flag::f_invite_users | Flag::f_invite_link, lang(lng_rights_group_invite));
|
||||
addCheckbox(Flag::f_add_admins, lang(lng_rights_add_admins));
|
||||
}
|
||||
|
||||
auto addAdmins = _checkboxes.find(Flag::f_add_admins);
|
||||
if (addAdmins != _checkboxes.end()) {
|
||||
_aboutAddAdmins = addControl(object_ptr<Ui::FlatLabel>(this, st::boxLabel), st::rightsAboutMargin);
|
||||
t_assert(addAdmins != _checkboxes.end());
|
||||
subscribe(addAdmins->second->checkedChanged, [this](bool checked) {
|
||||
refreshAboutAddAdminsText();
|
||||
});
|
||||
refreshAboutAddAdminsText();
|
||||
}
|
||||
|
||||
if (canSave()) {
|
||||
addButton(langFactory(lng_settings_save), [this] {
|
||||
if (!_saveCallback) {
|
||||
return;
|
||||
}
|
||||
auto newFlags = MTPDchannelAdminRights::Flags(0);
|
||||
for (auto &&checkbox : _checkboxes) {
|
||||
if (checkbox.second->checked()) {
|
||||
newFlags |= checkbox.first;
|
||||
} else {
|
||||
newFlags &= ~checkbox.first;
|
||||
}
|
||||
}
|
||||
if (!channel()->amCreator()) {
|
||||
// Leave only rights that we have so we could save them.
|
||||
newFlags &= channel()->adminRights().vflags.v;
|
||||
}
|
||||
_saveCallback(_oldRights, MTP_channelAdminRights(MTP_flags(newFlags)));
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
} else {
|
||||
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
|
||||
}
|
||||
|
||||
applyDependencies(nullptr);
|
||||
for (auto &&checkbox : _checkboxes) {
|
||||
checkbox.second->finishAnimations();
|
||||
}
|
||||
|
||||
resizeToContent();
|
||||
}
|
||||
|
||||
void EditAdminBox::applyDependencies(QPointer<Ui::Checkbox> changed) {
|
||||
ApplyDependencies(_checkboxes, _dependencies, changed);
|
||||
}
|
||||
|
||||
void EditAdminBox::refreshAboutAddAdminsText() {
|
||||
auto addAdmins = _checkboxes.find(Flag::f_add_admins);
|
||||
t_assert(addAdmins != _checkboxes.end());
|
||||
auto text = [this, addAdmins] {
|
||||
if (!canSave()) {
|
||||
return lang(lng_rights_about_admin_cant_edit);
|
||||
} else if (addAdmins->second->checked()) {
|
||||
return lang(lng_rights_about_add_admins_yes);
|
||||
}
|
||||
return lang(lng_rights_about_add_admins_no);
|
||||
};
|
||||
_aboutAddAdmins->setText(text());
|
||||
resizeToContent();
|
||||
}
|
||||
|
||||
EditRestrictedBox::EditRestrictedBox(QWidget*, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, bool hasAdminRights, const MTPChannelBannedRights &rights) : EditParticipantBox(nullptr, channel, user, hasAdminRights)
|
||||
, _oldRights(rights) {
|
||||
auto dependency = [this](Flag dependent, Flag dependency) {
|
||||
_dependencies.push_back(std::make_pair(dependent, dependency));
|
||||
};
|
||||
dependency(Flag::f_send_gifs, Flag::f_send_stickers); // stickers <-> gifs
|
||||
dependency(Flag::f_send_stickers, Flag::f_send_gifs);
|
||||
dependency(Flag::f_send_games, Flag::f_send_stickers); // stickers <-> games
|
||||
dependency(Flag::f_send_stickers, Flag::f_send_games);
|
||||
dependency(Flag::f_send_inline, Flag::f_send_stickers); // stickers <-> inline
|
||||
dependency(Flag::f_send_stickers, Flag::f_send_inline);
|
||||
dependency(Flag::f_send_stickers, Flag::f_send_media); // stickers -> send_media
|
||||
dependency(Flag::f_embed_links, Flag::f_send_media); // embed_links -> send_media
|
||||
dependency(Flag::f_send_media, Flag::f_send_messages); // send_media- > send_messages
|
||||
dependency(Flag::f_send_messages, Flag::f_view_messages); // send_messages -> view_messages
|
||||
}
|
||||
|
||||
void EditRestrictedBox::prepare() {
|
||||
EditParticipantBox::prepare();
|
||||
|
||||
setTitle(langFactory(lng_rights_user_restrictions));
|
||||
|
||||
addControl(object_ptr<Divider>(this), QMargins());
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_user_restrictions_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
|
||||
auto prepareRights = (_oldRights.c_channelBannedRights().vflags.v ? _oldRights : DefaultRights(channel()));
|
||||
_until = prepareRights.c_channelBannedRights().vuntil_date.v;
|
||||
|
||||
auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) {
|
||||
auto checked = (prepareRights.c_channelBannedRights().vflags.v & flags) == 0;
|
||||
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin);
|
||||
subscribe(control->checkedChanged, [this, control](bool checked) {
|
||||
InvokeQueued(this, [this, control] { applyDependencies(control); });
|
||||
});
|
||||
if (!canSave()) {
|
||||
control->setDisabled(true);
|
||||
}
|
||||
_checkboxes.emplace(flags, control);
|
||||
};
|
||||
addCheckbox(Flag::f_view_messages, lang(lng_rights_chat_read));
|
||||
addCheckbox(Flag::f_send_messages, lang(lng_rights_chat_send_text));
|
||||
addCheckbox(Flag::f_send_media, lang(lng_rights_chat_send_media));
|
||||
addCheckbox(Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline, lang(lng_rights_chat_send_stickers));
|
||||
addCheckbox(Flag::f_embed_links, lang(lng_rights_chat_send_links));
|
||||
|
||||
addControl(object_ptr<Divider>(this), st::rightsUntilMargin);
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_chat_banned_until_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
setRestrictUntil(_until);
|
||||
|
||||
//addControl(object_ptr<Ui::LinkButton>(this, lang(lng_rights_chat_banned_block), st::boxLinkButton));
|
||||
|
||||
if (canSave()) {
|
||||
addButton(langFactory(lng_settings_save), [this] {
|
||||
if (!_saveCallback) {
|
||||
return;
|
||||
}
|
||||
auto newFlags = MTPDchannelBannedRights::Flags(0);
|
||||
for (auto &&checkbox : _checkboxes) {
|
||||
if (checkbox.second->checked()) {
|
||||
newFlags &= ~checkbox.first;
|
||||
} else {
|
||||
newFlags |= checkbox.first;
|
||||
}
|
||||
}
|
||||
_saveCallback(_oldRights, MTP_channelBannedRights(MTP_flags(newFlags), MTP_int(getRealUntilValue())));
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
} else {
|
||||
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
|
||||
}
|
||||
|
||||
applyDependencies(nullptr);
|
||||
for (auto &&checkbox : _checkboxes) {
|
||||
checkbox.second->finishAnimations();
|
||||
}
|
||||
|
||||
resizeToContent();
|
||||
}
|
||||
|
||||
void EditRestrictedBox::applyDependencies(QPointer<Ui::Checkbox> changed) {
|
||||
ApplyDependencies(_checkboxes, _dependencies, changed);
|
||||
}
|
||||
|
||||
MTPChannelBannedRights EditRestrictedBox::DefaultRights(gsl::not_null<ChannelData*> channel) {
|
||||
auto defaultRights = Flag::f_send_messages | Flag::f_send_media | Flag::f_embed_links | Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline;
|
||||
return MTP_channelBannedRights(MTP_flags(defaultRights), MTP_int(0));
|
||||
}
|
||||
|
||||
void EditRestrictedBox::showRestrictUntil() {
|
||||
auto tomorrow = QDate::currentDate().addDays(1);
|
||||
auto highlighted = isUntilForever() ? tomorrow : date(getRealUntilValue()).date();
|
||||
auto month = highlighted;
|
||||
_restrictUntilBox = Ui::show(Box<CalendarBox>(month, highlighted, [this](const QDate &date) { setRestrictUntil(static_cast<int>(QDateTime(date).toTime_t())); }), KeepOtherLayers);
|
||||
_restrictUntilBox->setMaxDate(QDate::currentDate().addDays(kMaxRestrictDelayDays));
|
||||
_restrictUntilBox->setMinDate(tomorrow);
|
||||
_restrictUntilBox->addLeftButton(langFactory(lng_rights_chat_banned_forever), [this] { setRestrictUntil(0); });
|
||||
}
|
||||
|
||||
void EditRestrictedBox::setRestrictUntil(TimeId until) {
|
||||
_until = until;
|
||||
if (_restrictUntilBox) {
|
||||
_restrictUntilBox->closeBox();
|
||||
}
|
||||
clearVariants();
|
||||
createUntilGroup();
|
||||
createUntilVariants();
|
||||
resizeToContent();
|
||||
}
|
||||
|
||||
void EditRestrictedBox::clearVariants() {
|
||||
for (auto &&widget : base::take(_untilVariants)) {
|
||||
removeControl(widget.data());
|
||||
}
|
||||
}
|
||||
|
||||
void EditRestrictedBox::createUntilGroup() {
|
||||
_untilGroup = std::make_shared<Ui::RadiobuttonGroup>(isUntilForever() ? 0 : _until);
|
||||
_untilGroup->setChangedCallback([this](int value) {
|
||||
if (value == kUntilCustom) {
|
||||
_untilGroup->setValue(_until);
|
||||
showRestrictUntil();
|
||||
} else if (_until != value) {
|
||||
_until = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EditRestrictedBox::createUntilVariants() {
|
||||
auto addVariant = [this](int value, const QString &text) {
|
||||
if (!canSave() && _untilGroup->value() != value) {
|
||||
return;
|
||||
}
|
||||
_untilVariants.push_back(addControl(object_ptr<Ui::Radiobutton>(this, _untilGroup, value, text, st::defaultBoxCheckbox), st::rightsToggleMargin));
|
||||
if (!canSave()) {
|
||||
_untilVariants.back()->setDisabled(true);
|
||||
}
|
||||
};
|
||||
auto addCustomVariant = [this, addVariant](TimeId until, TimeId from, TimeId to) {
|
||||
if (!ChannelData::IsRestrictedForever(until) && until > from && until <= to) {
|
||||
addVariant(until, lng_rights_chat_banned_custom_date(lt_date, langDayOfMonthFull(date(until).date())));
|
||||
}
|
||||
};
|
||||
auto addCurrentVariant = [this, addCustomVariant](TimeId from, TimeId to) {
|
||||
auto oldUntil = _oldRights.c_channelBannedRights().vuntil_date.v;
|
||||
if (oldUntil < _until) {
|
||||
addCustomVariant(oldUntil, from, to);
|
||||
}
|
||||
addCustomVariant(_until, from, to);
|
||||
if (oldUntil > _until) {
|
||||
addCustomVariant(oldUntil, from, to);
|
||||
}
|
||||
};
|
||||
addVariant(0, lang(lng_rights_chat_banned_forever));
|
||||
|
||||
auto now = unixtime();
|
||||
auto nextDay = now + kSecondsInDay;
|
||||
auto nextWeek = now + kSecondsInWeek;
|
||||
addCurrentVariant(0, nextDay);
|
||||
addVariant(kUntilOneDay, lng_rights_chat_banned_day(lt_count, 1));
|
||||
addCurrentVariant(nextDay, nextWeek);
|
||||
addVariant(kUntilOneWeek, lng_rights_chat_banned_week(lt_count, 1));
|
||||
addCurrentVariant(nextWeek, INT_MAX);
|
||||
addVariant(kUntilCustom, lang(lng_rights_chat_banned_custom));
|
||||
}
|
||||
|
||||
TimeId EditRestrictedBox::getRealUntilValue() const {
|
||||
Expects(_until != kUntilCustom);
|
||||
if (_until == kUntilOneDay) {
|
||||
return unixtime() + kSecondsInDay;
|
||||
} else if (_until == kUntilOneWeek) {
|
||||
return unixtime() + kSecondsInWeek;
|
||||
}
|
||||
t_assert(_until >= 0);
|
||||
return _until;
|
||||
}
|
||||
153
Telegram/SourceFiles/boxes/edit_participant_box.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
|
||||
namespace Ui {
|
||||
class FlatLabel;
|
||||
class LinkButton;
|
||||
class Checkbox;
|
||||
class Radiobutton;
|
||||
class RadiobuttonGroup;
|
||||
} // namespace Ui
|
||||
|
||||
class CalendarBox;
|
||||
|
||||
class EditParticipantBox : public BoxContent {
|
||||
public:
|
||||
EditParticipantBox(QWidget*, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, bool hasAdminRights);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void resizeToContent();
|
||||
|
||||
gsl::not_null<UserData*> user() const {
|
||||
return _user;
|
||||
}
|
||||
gsl::not_null<ChannelData*> channel() const {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
template <typename Widget>
|
||||
QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin);
|
||||
|
||||
void removeControl(QPointer<TWidget> widget);
|
||||
|
||||
bool hasAdminRights() const {
|
||||
return _hasAdminRights;
|
||||
}
|
||||
|
||||
class Divider;
|
||||
|
||||
private:
|
||||
gsl::not_null<ChannelData*> _channel;
|
||||
gsl::not_null<UserData*> _user;
|
||||
bool _hasAdminRights = false;
|
||||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
||||
class EditAdminBox : public EditParticipantBox {
|
||||
public:
|
||||
EditAdminBox(QWidget*, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, const MTPChannelAdminRights &rights);
|
||||
|
||||
void setSaveCallback(base::lambda<void(MTPChannelAdminRights, MTPChannelAdminRights)> callback) {
|
||||
_saveCallback = std::move(callback);
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
using Flag = MTPDchannelAdminRights::Flag;
|
||||
using Flags = MTPDchannelAdminRights::Flags;
|
||||
|
||||
static MTPChannelAdminRights DefaultRights(gsl::not_null<ChannelData*> channel);
|
||||
|
||||
bool canSave() const {
|
||||
return !!_saveCallback;
|
||||
}
|
||||
void applyDependencies(QPointer<Ui::Checkbox> changed);
|
||||
void refreshAboutAddAdminsText();
|
||||
|
||||
const MTPChannelAdminRights _oldRights;
|
||||
std::vector<std::pair<Flag, Flag>> _dependencies;
|
||||
base::lambda<void(MTPChannelAdminRights, MTPChannelAdminRights)> _saveCallback;
|
||||
|
||||
std::map<Flags, QPointer<Ui::Checkbox>> _checkboxes;
|
||||
QPointer<Ui::FlatLabel> _aboutAddAdmins;
|
||||
|
||||
};
|
||||
|
||||
// Restricted box works with flags in the opposite way.
|
||||
// If some flag is set in the rights then the checkbox is unchecked.
|
||||
|
||||
class EditRestrictedBox : public EditParticipantBox {
|
||||
public:
|
||||
EditRestrictedBox(QWidget*, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, bool hasAdminRights, const MTPChannelBannedRights &rights);
|
||||
|
||||
void setSaveCallback(base::lambda<void(MTPChannelBannedRights, MTPChannelBannedRights)> callback) {
|
||||
_saveCallback = std::move(callback);
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
using Flag = MTPDchannelBannedRights::Flag;
|
||||
using Flags = MTPDchannelBannedRights::Flags;
|
||||
|
||||
static MTPChannelBannedRights DefaultRights(gsl::not_null<ChannelData*> channel);
|
||||
|
||||
bool canSave() const {
|
||||
return !!_saveCallback;
|
||||
}
|
||||
void applyDependencies(QPointer<Ui::Checkbox> changed);
|
||||
void showRestrictUntil();
|
||||
void setRestrictUntil(TimeId until);
|
||||
bool isUntilForever() {
|
||||
return ChannelData::IsRestrictedForever(_until);
|
||||
}
|
||||
void clearVariants();
|
||||
void createUntilGroup();
|
||||
void createUntilVariants();
|
||||
TimeId getRealUntilValue() const;
|
||||
|
||||
const MTPChannelBannedRights _oldRights;
|
||||
TimeId _until = 0;
|
||||
std::vector<std::pair<Flag, Flag>> _dependencies;
|
||||
base::lambda<void(MTPChannelBannedRights, MTPChannelBannedRights)> _saveCallback;
|
||||
|
||||
std::map<Flags, QPointer<Ui::Checkbox>> _checkboxes;
|
||||
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> _untilGroup;
|
||||
QVector<QPointer<Ui::Radiobutton>> _untilVariants;
|
||||
QPointer<CalendarBox> _restrictUntilBox;
|
||||
|
||||
static constexpr auto kUntilOneDay = -1;
|
||||
static constexpr auto kUntilOneWeek = -2;
|
||||
static constexpr auto kUntilCustom = -3;
|
||||
|
||||
};
|
||||
@@ -27,57 +27,56 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/effects/widget_slide_wrap.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "apiwrap.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class PrivacyExceptionsBoxController : public ChatsListBoxController {
|
||||
public:
|
||||
PrivacyExceptionsBoxController(const QString &title, const QVector<UserData*> &selected, base::lambda_once<void(QVector<UserData*> &&result)> saveCallback);
|
||||
void rowClicked(PeerListBox::Row *row) override;
|
||||
PrivacyExceptionsBoxController(base::lambda<QString()> titleFactory, const std::vector<gsl::not_null<UserData*>> &selected);
|
||||
void rowClicked(gsl::not_null<PeerListRow*> row) override;
|
||||
|
||||
std::vector<gsl::not_null<UserData*>> getResult() const;
|
||||
|
||||
protected:
|
||||
void prepareViewHook() override;
|
||||
std::unique_ptr<Row> createRow(History *history) override;
|
||||
std::unique_ptr<Row> createRow(gsl::not_null<History*> history) override;
|
||||
|
||||
private:
|
||||
QString _title;
|
||||
QVector<UserData*> _selected;
|
||||
base::lambda_once<void(QVector<UserData*> &&result)> _saveCallback;
|
||||
base::lambda<QString()> _titleFactory;
|
||||
std::vector<gsl::not_null<UserData*>> _selected;
|
||||
|
||||
};
|
||||
|
||||
PrivacyExceptionsBoxController::PrivacyExceptionsBoxController(const QString &title, const QVector<UserData*> &selected, base::lambda_once<void(QVector<UserData*> &&result)> saveCallback)
|
||||
: _title(title)
|
||||
, _selected(selected)
|
||||
, _saveCallback(std::move(saveCallback)) {
|
||||
PrivacyExceptionsBoxController::PrivacyExceptionsBoxController(base::lambda<QString()> titleFactory, const std::vector<gsl::not_null<UserData*>> &selected)
|
||||
: _titleFactory(std::move(titleFactory))
|
||||
, _selected(selected) {
|
||||
}
|
||||
|
||||
void PrivacyExceptionsBoxController::prepareViewHook() {
|
||||
view()->setTitle(_title);
|
||||
view()->addButton(lang(lng_settings_save), [this] {
|
||||
auto peers = view()->collectSelectedRows();
|
||||
auto users = QVector<UserData*>();
|
||||
if (!peers.empty()) {
|
||||
users.reserve(peers.size());
|
||||
for_const (auto peer, peers) {
|
||||
auto user = peer->asUser();
|
||||
t_assert(user != nullptr);
|
||||
users.push_back(user);
|
||||
}
|
||||
delegate()->peerListSetTitle(_titleFactory);
|
||||
delegate()->peerListAddSelectedRows(_selected);
|
||||
}
|
||||
|
||||
std::vector<gsl::not_null<UserData*>> PrivacyExceptionsBoxController::getResult() const {
|
||||
auto peers = delegate()->peerListCollectSelectedRows();
|
||||
auto users = std::vector<gsl::not_null<UserData*>>();
|
||||
if (!peers.empty()) {
|
||||
users.reserve(peers.size());
|
||||
for_const (auto peer, peers) {
|
||||
auto user = peer->asUser();
|
||||
t_assert(user != nullptr);
|
||||
users.push_back(user);
|
||||
}
|
||||
_saveCallback(std::move(users));
|
||||
view()->closeBox();
|
||||
});
|
||||
view()->addButton(lang(lng_cancel), [this] { view()->closeBox(); });
|
||||
view()->addSelectedRows(_selected);
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
void PrivacyExceptionsBoxController::rowClicked(PeerListBox::Row *row) {
|
||||
view()->setRowChecked(row, !row->checked());
|
||||
void PrivacyExceptionsBoxController::rowClicked(gsl::not_null<PeerListRow*> row) {
|
||||
delegate()->peerListSetRowChecked(row, !row->checked());
|
||||
}
|
||||
|
||||
std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxController::createRow(History *history) {
|
||||
std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxController::createRow(gsl::not_null<History*> history) {
|
||||
if (auto user = history->peer->asUser()) {
|
||||
if (!user->isSelf()) {
|
||||
return std::make_unique<Row>(history);
|
||||
@@ -96,8 +95,8 @@ EditPrivacyBox::EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller)
|
||||
void EditPrivacyBox::prepare() {
|
||||
_controller->setView(this);
|
||||
|
||||
setTitle(_controller->title());
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
setTitle([this] { return _controller->title(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
loadData();
|
||||
|
||||
@@ -146,7 +145,7 @@ int EditPrivacyBox::countDefaultHeight(int newWidth) {
|
||||
if (!_controller->hasOption(option)) {
|
||||
return 0;
|
||||
}
|
||||
return st::editPrivacyOptionMargin.top() + st::defaultBoxCheckbox.height + st::editPrivacyOptionMargin.bottom();
|
||||
return st::editPrivacyOptionMargin.top() + st::defaultCheck.diameter + st::editPrivacyOptionMargin.bottom();
|
||||
};
|
||||
auto labelHeight = [this, newWidth](const QString &text, const style::FlatLabel &st, style::margins padding) {
|
||||
if (text.isEmpty()) {
|
||||
@@ -174,29 +173,37 @@ int EditPrivacyBox::countDefaultHeight(int newWidth) {
|
||||
}
|
||||
|
||||
void EditPrivacyBox::editExceptionUsers(Exception exception) {
|
||||
auto controller = std::make_unique<PrivacyExceptionsBoxController>(_controller->exceptionBoxTitle(exception), exceptionUsers(exception), base::lambda_guarded(this, [this, exception](QVector<UserData*> &&users) {
|
||||
exceptionUsers(exception) = std::move(users);
|
||||
exceptionLink(exception)->entity()->setText(exceptionLinkText(exception));
|
||||
auto removeFrom = ([exception] {
|
||||
switch (exception) {
|
||||
case Exception::Always: return Exception::Never;
|
||||
case Exception::Never: return Exception::Always;
|
||||
auto controller = std::make_unique<PrivacyExceptionsBoxController>(base::lambda_guarded(this, [this, exception] {
|
||||
return _controller->exceptionBoxTitle(exception);
|
||||
}), exceptionUsers(exception));
|
||||
auto initBox = [this, exception, controller = controller.get()](PeerListBox *box) {
|
||||
box->addButton(langFactory(lng_settings_save), base::lambda_guarded(this, [this, box, exception, controller] {
|
||||
exceptionUsers(exception) = controller->getResult();
|
||||
exceptionLink(exception)->entity()->setText(exceptionLinkText(exception));
|
||||
auto removeFrom = ([exception] {
|
||||
switch (exception) {
|
||||
case Exception::Always: return Exception::Never;
|
||||
case Exception::Never: return Exception::Always;
|
||||
}
|
||||
Unexpected("Invalid exception value.");
|
||||
})();
|
||||
auto &removeFromUsers = exceptionUsers(removeFrom);
|
||||
auto removedSome = false;
|
||||
for (auto user : exceptionUsers(exception)) {
|
||||
auto removedStart = std::remove(removeFromUsers.begin(), removeFromUsers.end(), user);
|
||||
if (removedStart != removeFromUsers.end()) {
|
||||
removeFromUsers.erase(removedStart, removeFromUsers.end());
|
||||
removedSome = true;
|
||||
}
|
||||
}
|
||||
Unexpected("Invalid exception value.");
|
||||
})();
|
||||
auto &removeFromUsers = exceptionUsers(removeFrom);
|
||||
auto removedSome = false;
|
||||
for (auto user : exceptionUsers(exception)) {
|
||||
if (removeFromUsers.contains(user)) {
|
||||
removeFromUsers.erase(std::remove(removeFromUsers.begin(), removeFromUsers.end(), user), removeFromUsers.end());
|
||||
removedSome = true;
|
||||
if (removedSome) {
|
||||
exceptionLink(removeFrom)->entity()->setText(exceptionLinkText(removeFrom));
|
||||
}
|
||||
}
|
||||
if (removedSome) {
|
||||
exceptionLink(removeFrom)->entity()->setText(exceptionLinkText(removeFrom));
|
||||
}
|
||||
}));
|
||||
Ui::show(Box<PeerListBox>(std::move(controller)), KeepOtherLayers);
|
||||
box->closeBox();
|
||||
}));
|
||||
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
|
||||
};
|
||||
Ui::show(Box<PeerListBox>(std::move(controller), std::move(initBox)), KeepOtherLayers);
|
||||
}
|
||||
|
||||
QString EditPrivacyBox::exceptionLinkText(Exception exception) {
|
||||
@@ -235,7 +242,7 @@ style::margins EditPrivacyBox::exceptionLinkMargins() const {
|
||||
return st::editPrivacyLinkMargin;
|
||||
}
|
||||
|
||||
QVector<UserData*> &EditPrivacyBox::exceptionUsers(Exception exception) {
|
||||
std::vector<gsl::not_null<UserData*>> &EditPrivacyBox::exceptionUsers(Exception exception) {
|
||||
switch (exception) {
|
||||
case Exception::Always: return _alwaysUsers;
|
||||
case Exception::Never: return _neverUsers;
|
||||
@@ -292,14 +299,14 @@ void EditPrivacyBox::createWidgets() {
|
||||
createLabel(_exceptionsDescription, _controller->exceptionsDescription(), st::editPrivacyLabel);
|
||||
|
||||
clearButtons();
|
||||
addButton(lang(lng_settings_save), [this] {
|
||||
addButton(langFactory(lng_settings_save), [this] {
|
||||
auto someAreDisallowed = (_option != Option::Everyone) || !_neverUsers.empty();
|
||||
_controller->confirmSave(someAreDisallowed, base::lambda_guarded(this, [this] {
|
||||
App::api()->savePrivacy(_controller->key(), collectResult());
|
||||
closeBox();
|
||||
}));
|
||||
});
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
_optionGroup->setChangedCallback([this](Option value) {
|
||||
_option = value;
|
||||
@@ -337,7 +344,7 @@ void EditPrivacyBox::loadData() {
|
||||
_alwaysUsers.reserve(_alwaysUsers.size() + users.size());
|
||||
for (auto &userId : users) {
|
||||
auto user = App::user(UserId(userId.v));
|
||||
if (!_neverUsers.contains(user) && !_alwaysUsers.contains(user)) {
|
||||
if (!base::contains(_neverUsers, user) && !base::contains(_alwaysUsers, user)) {
|
||||
_alwaysUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
@@ -349,7 +356,7 @@ void EditPrivacyBox::loadData() {
|
||||
_neverUsers.reserve(_neverUsers.size() + users.size());
|
||||
for (auto &userId : users) {
|
||||
auto user = App::user(UserId(userId.v));
|
||||
if (!_alwaysUsers.contains(user) && !_neverUsers.contains(user)) {
|
||||
if (!base::contains(_alwaysUsers, user) && !base::contains(_neverUsers, user)) {
|
||||
_neverUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ private:
|
||||
|
||||
void editExceptionUsers(Exception exception);
|
||||
QString exceptionLinkText(Exception exception);
|
||||
QVector<UserData*> &exceptionUsers(Exception exception);
|
||||
std::vector<gsl::not_null<UserData*>> &exceptionUsers(Exception exception);
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> &exceptionLink(Exception exception);
|
||||
|
||||
std::unique_ptr<Controller> _controller;
|
||||
@@ -120,7 +120,7 @@ private:
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _neverLink = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
|
||||
|
||||
QVector<UserData*> _alwaysUsers;
|
||||
QVector<UserData*> _neverUsers;
|
||||
std::vector<gsl::not_null<UserData*>> _alwaysUsers;
|
||||
std::vector<gsl::not_null<UserData*>> _neverUsers;
|
||||
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/emoji_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
@@ -79,10 +79,10 @@ EmojiBox::EmojiBox(QWidget*) : _esize(Ui::Emoji::Size(Ui::Emoji::Index() + 1)) {
|
||||
}
|
||||
|
||||
void EmojiBox::prepare() {
|
||||
setTitle(lang(lng_settings_emoji_list));
|
||||
setTitle(langFactory(lng_settings_emoji_list));
|
||||
fillBlocks();
|
||||
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
||||
_blockHeight = st::emojiReplaceInnerHeight;
|
||||
|
||||
|
||||
@@ -20,90 +20,146 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/language_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "langloaderplain.h"
|
||||
#include "lang/lang_instance.h"
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
class LanguageBox::Inner : public TWidget, private base::Subscriber {
|
||||
public:
|
||||
Inner(QWidget *parent, gsl::not_null<Languages*> languages);
|
||||
|
||||
void setSelected(int index);
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
void activateCurrent();
|
||||
void languageChanged(int languageIndex);
|
||||
|
||||
gsl::not_null<Languages*> _languages;
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> _group;
|
||||
std::vector<object_ptr<Ui::Radiobutton>> _buttons;
|
||||
|
||||
};
|
||||
|
||||
LanguageBox::Inner::Inner(QWidget *parent, gsl::not_null<Languages*> languages) : TWidget(parent)
|
||||
, _languages(languages) {
|
||||
_group = std::make_shared<Ui::RadiobuttonGroup>(0);
|
||||
_group->setChangedCallback([this](int value) { languageChanged(value); });
|
||||
subscribe(Lang::Current().updated(), [this] {
|
||||
activateCurrent();
|
||||
refresh();
|
||||
});
|
||||
}
|
||||
|
||||
void LanguageBox::Inner::setSelected(int index) {
|
||||
_group->setValue(index);
|
||||
}
|
||||
|
||||
void LanguageBox::Inner::refresh() {
|
||||
for (auto &button : _buttons) {
|
||||
button.destroy();
|
||||
}
|
||||
_buttons.clear();
|
||||
|
||||
auto y = st::boxOptionListPadding.top() + st::langsButton.margin.top();
|
||||
_buttons.reserve(_languages->size());
|
||||
auto index = 0;
|
||||
for_const (auto &language, *_languages) {
|
||||
_buttons.emplace_back(this, _group, index++, language.nativeName, st::langsButton);
|
||||
auto button = _buttons.back().data();
|
||||
button->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
|
||||
button->show();
|
||||
y += button->heightNoMargins() + st::boxOptionListSkip;
|
||||
}
|
||||
auto newHeight = y - st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::langsButton.margin.bottom();
|
||||
resize(st::langsWidth, newHeight);
|
||||
}
|
||||
|
||||
void LanguageBox::Inner::languageChanged(int languageIndex) {
|
||||
Expects(languageIndex >= 0 && languageIndex < _languages->size());
|
||||
|
||||
activateCurrent();
|
||||
auto languageId = (*_languages)[languageIndex].id;
|
||||
if (Lang::Current().id() != languageId) {
|
||||
// "custom" is applied each time it is passed to switchToLanguage().
|
||||
// So we check that the language really has changed.
|
||||
Lang::CurrentCloudManager().switchToLanguage(languageId);
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageBox::Inner::activateCurrent() {
|
||||
auto currentId = Lang::Current().id();
|
||||
for (auto i = 0, count = _languages->size(); i != count; ++i) {
|
||||
auto languageId = (*_languages)[i].id;
|
||||
auto isCurrent = (languageId == currentId) || (languageId == Lang::DefaultLanguageId() && currentId.isEmpty());
|
||||
if (isCurrent) {
|
||||
_group->setValue(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageBox::prepare() {
|
||||
addButton(lang(lng_box_ok), [this] { closeBox(); });
|
||||
refreshLang();
|
||||
subscribe(Lang::Current().updated(), [this] {
|
||||
refreshLang();
|
||||
});
|
||||
|
||||
setTitle(lang(lng_languages));
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, &_languages), st::boxLayerScroll);
|
||||
|
||||
auto haveTestLang = (cLang() == languageTest);
|
||||
|
||||
_langGroup = std::make_shared<Ui::RadiobuttonGroup>(cLang());
|
||||
auto y = st::boxOptionListPadding.top();
|
||||
_langs.reserve(languageCount + (haveTestLang ? 1 : 0));
|
||||
if (haveTestLang) {
|
||||
_langs.emplace_back(this, _langGroup, languageTest, qsl("Custom Lang"), st::langsButton);
|
||||
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
|
||||
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
|
||||
}
|
||||
for (auto i = 0; i != languageCount; ++i) {
|
||||
LangLoaderResult result;
|
||||
if (i) {
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lng_language_name));
|
||||
result = loader.found();
|
||||
} else {
|
||||
result.insert(lng_language_name, langOriginal(lng_language_name));
|
||||
}
|
||||
_langs.emplace_back(this, _langGroup, i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), st::langsButton);
|
||||
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
|
||||
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
|
||||
}
|
||||
_langGroup->setChangedCallback([this](int value) { languageChanged(value); });
|
||||
|
||||
auto optionsCount = languageCount + (haveTestLang ? 1 : 0);
|
||||
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + optionsCount * st::langsButton.height + (optionsCount - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
|
||||
refresh();
|
||||
subscribe(Lang::CurrentCloudManager().languageListChanged(), [this] {
|
||||
refresh();
|
||||
});
|
||||
}
|
||||
|
||||
void LanguageBox::mousePressEvent(QMouseEvent *e) {
|
||||
if ((e->modifiers() & Qt::CTRL) && (e->modifiers() & Qt::ALT) && (e->modifiers() & Qt::SHIFT)) {
|
||||
for (int32 i = 1; i < languageCount; ++i) {
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lngkeys_cnt));
|
||||
if (!loader.errors().isEmpty()) {
|
||||
Ui::show(Box<InformBox>(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors()));
|
||||
return;
|
||||
} else if (!loader.warnings().isEmpty()) {
|
||||
QString warn = loader.warnings();
|
||||
if (warn.size() > 256) warn = warn.mid(0, 253) + qsl("...");
|
||||
Ui::show(Box<InformBox>(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn));
|
||||
return;
|
||||
void LanguageBox::refreshLang() {
|
||||
clearButtons();
|
||||
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
|
||||
|
||||
setTitle(langFactory(lng_languages));
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void LanguageBox::refresh() {
|
||||
refreshLanguages();
|
||||
|
||||
_inner->refresh();
|
||||
setDimensions(st::langsWidth, qMin(_inner->height(), st::boxMaxListHeight));
|
||||
}
|
||||
|
||||
void LanguageBox::refreshLanguages() {
|
||||
_languages = Languages();
|
||||
auto list = Lang::CurrentCloudManager().languageList();
|
||||
_languages.reserve(list.size() + 1);
|
||||
auto currentId = Lang::Current().id();
|
||||
auto currentIndex = -1;
|
||||
_languages.push_back({ qsl("en"), qsl("English"), qsl("English") });
|
||||
for (auto &language : list) {
|
||||
auto isCurrent = (language.id == currentId) || (language.id == Lang::DefaultLanguageId() && currentId.isEmpty());
|
||||
if (language.id != qstr("en")) {
|
||||
if (isCurrent) {
|
||||
currentIndex = _languages.size();
|
||||
}
|
||||
_languages.push_back(language);
|
||||
} else if (isCurrent) {
|
||||
currentIndex = 0;
|
||||
}
|
||||
Ui::show(Box<InformBox>(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageBox::languageChanged(int languageId) {
|
||||
Expects(languageId == languageTest || (languageId >= 0 && languageId < base::array_size(LanguageCodes)));
|
||||
|
||||
if (languageId == cLang()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LangLoaderResult result;
|
||||
if (languageId > 0) {
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[languageId].c_str() + qsl(".strings"), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
|
||||
result = loader.found();
|
||||
} else if (languageId == languageTest) {
|
||||
LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
|
||||
result = loader.found();
|
||||
}
|
||||
auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
|
||||
save = result.value(lng_box_ok, langOriginal(lng_box_ok)),
|
||||
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
|
||||
Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this, languageId] {
|
||||
cSetLang(languageId);
|
||||
Local::writeSettings();
|
||||
App::restart();
|
||||
}), base::lambda_guarded(this, [this] {
|
||||
_langGroup->setValue(cLang());
|
||||
})), KeepOtherLayers);
|
||||
if (currentId == qstr("custom")) {
|
||||
_languages.insert(_languages.begin(), { currentId, qsl("Custom LangPack"), qsl("Custom LangPack") });
|
||||
currentIndex = 0;
|
||||
} else if (currentIndex < 0) {
|
||||
currentIndex = _languages.size();
|
||||
_languages.push_back({ currentId, lang(lng_language_name), lang(lng_language_name) });
|
||||
}
|
||||
_inner->setSelected(currentIndex);
|
||||
}
|
||||
|
||||
@@ -20,16 +20,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
namespace Ui {
|
||||
class RadiobuttonGroup;
|
||||
class Radiobutton;
|
||||
} // namespace Ui
|
||||
|
||||
class LanguageBox : public BoxContent {
|
||||
Q_OBJECT
|
||||
|
||||
class LanguageBox : public BoxContent, private MTP::Sender {
|
||||
public:
|
||||
LanguageBox(QWidget*) {
|
||||
}
|
||||
@@ -37,12 +37,16 @@ public:
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
void languageChanged(int languageId);
|
||||
using Languages = Lang::CloudManager::Languages;
|
||||
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> _langGroup;
|
||||
std::vector<object_ptr<Ui::Radiobutton>> _langs;
|
||||
void refresh();
|
||||
void refreshLanguages();
|
||||
void refreshLang();
|
||||
|
||||
Languages _languages;
|
||||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "auth_session.h"
|
||||
|
||||
@@ -32,9 +32,9 @@ LocalStorageBox::LocalStorageBox(QWidget *parent)
|
||||
}
|
||||
|
||||
void LocalStorageBox::prepare() {
|
||||
setTitle(lang(lng_local_storage_title));
|
||||
setTitle(langFactory(lng_local_storage_title));
|
||||
|
||||
addButton(lang(lng_box_ok), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
|
||||
|
||||
_clear->setClickedCallback([this] { clearStorage(); });
|
||||
|
||||
|
||||
@@ -1,656 +0,0 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/members_box.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "lang.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "boxes/contacts_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "observer_peer.h"
|
||||
#include "auth_session.h"
|
||||
#include "storage/file_download.h"
|
||||
|
||||
// Not used for now.
|
||||
//
|
||||
//MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||
//, _st(st) {
|
||||
// resize(_st.width, _st.height);
|
||||
// setCursor(style::cur_pointer);
|
||||
//}
|
||||
//
|
||||
//void MembersAddButton::paintEvent(QPaintEvent *e) {
|
||||
// Painter p(this);
|
||||
//
|
||||
// auto ms = getms();
|
||||
// auto over = isOver();
|
||||
// auto down = isDown();
|
||||
//
|
||||
// ((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||
// paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
// ((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||
//}
|
||||
//
|
||||
//QImage MembersAddButton::prepareRippleMask() const {
|
||||
// return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||
//}
|
||||
//
|
||||
//QPoint MembersAddButton::prepareRippleStartPosition() const {
|
||||
// return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||
//}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kReloadChannelAdminsTimeout = 1000; // 1 second wait before reload admins in channel after adding
|
||||
|
||||
} // namespace
|
||||
|
||||
MembersBox::MembersBox(QWidget*, ChannelData *channel, MembersFilter filter)
|
||||
: _channel(channel)
|
||||
, _filter(filter) {
|
||||
}
|
||||
|
||||
void MembersBox::prepare() {
|
||||
setTitle(lang(_filter == MembersFilter::Recent ? lng_channel_members : lng_channel_admins));
|
||||
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, _channel, _filter), st::boxLayerScroll);
|
||||
|
||||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
if (_channel->amCreator() && (_channel->membersCount() < (_channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!_channel->isMegagroup() && !_channel->isPublic()) || _filter == MembersFilter::Admins)) {
|
||||
addLeftButton(lang((_filter == MembersFilter::Admins) ? lng_channel_add_admin : lng_channel_add_members), [this] { onAdd(); });
|
||||
}
|
||||
|
||||
connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int)));
|
||||
|
||||
_loadTimer.create(this);
|
||||
connect(_loadTimer, SIGNAL(timeout()), _inner, SLOT(load()));
|
||||
}
|
||||
|
||||
void MembersBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Down) {
|
||||
_inner->selectSkip(1);
|
||||
} else if (e->key() == Qt::Key_Up) {
|
||||
_inner->selectSkip(-1);
|
||||
} else if (e->key() == Qt::Key_PageDown) {
|
||||
_inner->selectSkipPage(height(), 1);
|
||||
} else if (e->key() == Qt::Key_PageUp) {
|
||||
_inner->selectSkipPage(height(), -1);
|
||||
} else {
|
||||
BoxContent::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_inner->resize(width(), _inner->height());
|
||||
}
|
||||
|
||||
void MembersBox::onAdd() {
|
||||
if (_inner->filter() == MembersFilter::Recent && _inner->channel()->membersCount() >= (_inner->channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
|
||||
Ui::show(Box<MaxInviteBox>(_inner->channel()->inviteLink()), KeepOtherLayers);
|
||||
return;
|
||||
}
|
||||
auto box = Box<ContactsBox>(_inner->channel(), _inner->filter(), _inner->already());
|
||||
if (_inner->filter() == MembersFilter::Recent) {
|
||||
Ui::show(std::move(box));
|
||||
} else {
|
||||
_addBox = Ui::show(std::move(box), KeepOtherLayers);
|
||||
if (_addBox) {
|
||||
connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::onAdminAdded() {
|
||||
if (!_addBox) return;
|
||||
_addBox->closeBox();
|
||||
_addBox = nullptr;
|
||||
_loadTimer->start(kReloadChannelAdminsTimeout);
|
||||
}
|
||||
|
||||
MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter filter) : TWidget(parent)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _channel(channel)
|
||||
, _filter(filter)
|
||||
, _kickText(lang(lng_profile_kick))
|
||||
, _kickWidth(st::normalFont->width(_kickText))
|
||||
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
|
||||
, _about(_aboutWidth) {
|
||||
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
|
||||
refresh();
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
void MembersBox::Inner::load() {
|
||||
if (!_loadingRequestId) {
|
||||
_loadingRequestId = MTP::send(MTPchannels_GetParticipants(_channel->inputChannel, (_filter == MembersFilter::Recent) ? MTP_channelParticipantsRecent() : MTP_channelParticipantsAdmins(), MTP_int(0), MTP_int(Global::ChatSizeMax())), rpcDone(&Inner::membersReceived), rpcFail(&Inner::membersFailed));
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::paintEvent(QPaintEvent *e) {
|
||||
QRect r(e->rect());
|
||||
Painter p(this);
|
||||
|
||||
_time = unixtime();
|
||||
p.fillRect(r, st::contactsBg);
|
||||
|
||||
auto ms = getms();
|
||||
auto yFrom = r.y() - st::membersMarginTop;
|
||||
auto yTo = r.y() + r.height() - st::membersMarginTop;
|
||||
p.translate(0, st::membersMarginTop);
|
||||
if (_rows.isEmpty()) {
|
||||
p.setFont(st::noContactsFont);
|
||||
p.setPen(st::noContactsColor);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
|
||||
} else {
|
||||
int32 from = floorclamp(yFrom, _rowHeight, 0, _rows.size());
|
||||
int32 to = ceilclamp(yTo, _rowHeight, 0, _rows.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (; from < to; ++from) {
|
||||
auto selected = (_pressed >= 0) ? (from == _pressed) : (from == _selected);
|
||||
auto kickSelected = (_pressed >= 0) ? (from == _kickPressed && from == _kickSelected) : (from == _kickSelected);
|
||||
paintDialog(p, ms, _rows[from], data(from), selected, kickSelected);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
if (to == _rows.size() && _filter == MembersFilter::Recent && (_rows.size() < _channel->membersCount() || _rows.size() >= Global::ChatSizeMax())) {
|
||||
p.setPen(st::membersAboutLimitFg);
|
||||
_about.draw(p, st::contactsPadding.left(), st::membersAboutLimitPadding.top(), _aboutWidth, style::al_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::enterEventHook(QEvent *e) {
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
void MembersBox::Inner::leaveEventHook(QEvent *e) {
|
||||
_mouseSelection = false;
|
||||
setMouseTracking(false);
|
||||
if (_selected >= 0) {
|
||||
clearSel();
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
_mouseSelection = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
void MembersBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||
_mouseSelection = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSelection();
|
||||
setPressed(_selected);
|
||||
_kickPressed = _kickSelected;
|
||||
if (_selected >= 0 && _selected < _datas.size() && _kickSelected < 0) {
|
||||
addRipple(_datas[_selected]);
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
auto pressed = _pressed;
|
||||
auto kickPressed = _kickPressed;
|
||||
setPressed(-1);
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
if (pressed == _selected && kickPressed == _kickSelected) {
|
||||
if (kickPressed >= 0) {
|
||||
if (!_kickRequestId) {
|
||||
_kickConfirm = _rows.at(_kickSelected);
|
||||
if (_kickBox) _kickBox->deleteLater();
|
||||
auto text = (_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName);
|
||||
_kickBox = Ui::show(Box<ConfirmBox>(text, base::lambda_guarded(this, [this] {
|
||||
if (_filter == MembersFilter::Recent) {
|
||||
_kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail));
|
||||
} else {
|
||||
_kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail));
|
||||
}
|
||||
})), KeepOtherLayers);
|
||||
}
|
||||
} else if (pressed >= 0) {
|
||||
chooseParticipant();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::addRipple(MemberData *data) {
|
||||
auto rowTop = getSelectedRowTop();
|
||||
if (!data->ripple) {
|
||||
auto mask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight));
|
||||
data->ripple = std::make_unique<Ui::RippleAnimation>(st::contactsRipple, std::move(mask), [this, data] {
|
||||
updateRowWithTop(data->rippleRowTop);
|
||||
});
|
||||
}
|
||||
data->rippleRowTop = rowTop;
|
||||
data->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(0, rowTop));
|
||||
}
|
||||
|
||||
void MembersBox::Inner::stopLastRipple(MemberData *data) {
|
||||
if (data->ripple) {
|
||||
data->ripple->lastStop();
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::setPressed(int pressed) {
|
||||
if (_pressed >= 0 && _pressed < _datas.size()) {
|
||||
stopLastRipple(_datas[_pressed]);
|
||||
}
|
||||
_pressed = pressed;
|
||||
}
|
||||
|
||||
void MembersBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, MemberData *data, bool selected, bool kickSelected) {
|
||||
UserData *user = peer->asUser();
|
||||
|
||||
p.fillRect(0, 0, width(), _rowHeight, selected ? st::contactsBgOver : st::contactsBg);
|
||||
if (data->ripple) {
|
||||
data->ripple->paint(p, 0, 0, width(), ms);
|
||||
if (data->ripple->empty()) {
|
||||
data->ripple.reset();
|
||||
}
|
||||
}
|
||||
peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize);
|
||||
|
||||
p.setPen(st::contactsNameFg);
|
||||
|
||||
int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
int32 namew = width() - namex - st::contactsPadding.right() - (data->canKick ? (_kickWidth + st::contactsCheckPosition.x() * 2) : 0);
|
||||
if (peer->isVerified()) {
|
||||
auto icon = &st::dialogsVerifiedIcon;
|
||||
namew -= icon->width();
|
||||
icon->paint(p, namex + qMin(data->name.maxWidth(), namew), st::contactsPadding.top() + st::contactsNameTop, width());
|
||||
}
|
||||
data->name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width());
|
||||
|
||||
if (data->canKick) {
|
||||
p.setFont(kickSelected ? st::linkOverFont : st::linkFont);
|
||||
p.setPen(kickSelected ? st::defaultLinkButton.overColor : st::defaultLinkButton.color);
|
||||
p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), _kickText, _kickWidth);
|
||||
}
|
||||
|
||||
p.setFont(st::contactsStatusFont->f);
|
||||
p.setPen(data->onlineColor ? st::contactsStatusFgOnline : (selected ? st::contactsStatusFgOver : st::contactsStatusFg));
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), data->online);
|
||||
}
|
||||
|
||||
void MembersBox::Inner::selectSkip(int32 dir) {
|
||||
_time = unixtime();
|
||||
_mouseSelection = false;
|
||||
|
||||
int cur = -1;
|
||||
if (_selected >= 0) {
|
||||
cur = _selected;
|
||||
}
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_selected = _rows.isEmpty() ? -1 : 0;
|
||||
} else if (cur >= _rows.size()) {
|
||||
_selected = -1;
|
||||
} else {
|
||||
_selected = cur;
|
||||
}
|
||||
if (dir > 0) {
|
||||
if (_selected < 0 || _selected >= _rows.size()) {
|
||||
_selected = -1;
|
||||
}
|
||||
} else {
|
||||
if (!_rows.isEmpty()) {
|
||||
if (_selected < 0) _selected = _rows.size() - 1;
|
||||
}
|
||||
}
|
||||
if (_selected >= 0) {
|
||||
emit mustScrollTo(st::membersMarginTop + _selected * _rowHeight, st::membersMarginTop + (_selected + 1) * _rowHeight);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void MembersBox::Inner::selectSkipPage(int32 h, int32 dir) {
|
||||
int32 points = h / _rowHeight;
|
||||
if (!points) return;
|
||||
selectSkip(points * dir);
|
||||
}
|
||||
|
||||
MembersBox::Inner::MemberData::MemberData() = default;
|
||||
|
||||
MembersBox::Inner::MemberData::~MemberData() = default;
|
||||
|
||||
void MembersBox::Inner::loadProfilePhotos() {
|
||||
if (_visibleTop >= _visibleBottom) return;
|
||||
|
||||
auto yFrom = _visibleTop;
|
||||
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
|
||||
AuthSession::Current().downloader().clearPriorities();
|
||||
|
||||
if (yTo < 0) return;
|
||||
if (yFrom < 0) yFrom = 0;
|
||||
|
||||
if (!_rows.isEmpty()) {
|
||||
int32 from = yFrom / _rowHeight;
|
||||
if (from < 0) from = 0;
|
||||
if (from < _rows.size()) {
|
||||
int32 to = (yTo / _rowHeight) + 1;
|
||||
if (to > _rows.size()) to = _rows.size();
|
||||
|
||||
for (; from < to; ++from) {
|
||||
_rows[from]->loadUserpic();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::chooseParticipant() {
|
||||
if (_selected < 0 || _selected >= _rows.size()) return;
|
||||
if (auto peer = _rows[_selected]) {
|
||||
Ui::hideLayer();
|
||||
Ui::showPeerProfile(peer);
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::refresh() {
|
||||
if (_rows.isEmpty()) {
|
||||
resize(width(), st::membersMarginTop + st::noContactsHeight + st::membersMarginBottom);
|
||||
_aboutHeight = 0;
|
||||
} else {
|
||||
_about.setText(st::boxLabelStyle, lng_channel_only_last_shown(lt_count, _rows.size()));
|
||||
_aboutHeight = st::membersAboutLimitPadding.top() + _about.countHeight(_aboutWidth) + st::membersAboutLimitPadding.bottom();
|
||||
if (_filter != MembersFilter::Recent || (_rows.size() >= _channel->membersCount() && _rows.size() < Global::ChatSizeMax())) {
|
||||
_aboutHeight = 0;
|
||||
}
|
||||
resize(width(), st::membersMarginTop + _aboutHeight + _rows.size() * _rowHeight + st::membersMarginBottom);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
ChannelData *MembersBox::Inner::channel() const {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
MembersFilter MembersBox::Inner::filter() const {
|
||||
return _filter;
|
||||
}
|
||||
|
||||
MembersAlreadyIn MembersBox::Inner::already() const {
|
||||
MembersAlreadyIn result;
|
||||
for_const (auto peer, _rows) {
|
||||
if (peer->isUser()) {
|
||||
result.insert(peer->asUser());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MembersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||
_visibleTop = visibleTop;
|
||||
_visibleBottom = visibleBottom;
|
||||
loadProfilePhotos();
|
||||
}
|
||||
|
||||
void MembersBox::Inner::clearSel() {
|
||||
updateSelectedRow();
|
||||
_selected = _kickSelected = -1;
|
||||
_lastMousePos = QCursor::pos();
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
MembersBox::Inner::MemberData *MembersBox::Inner::data(int32 index) {
|
||||
if (MemberData *result = _datas.at(index)) {
|
||||
return result;
|
||||
}
|
||||
MemberData *result = _datas[index] = new MemberData();
|
||||
result->name.setText(st::contactsNameStyle, _rows[index]->name, _textNameOptions);
|
||||
int32 t = unixtime();
|
||||
result->online = App::onlineText(_rows[index], t);// lng_mediaview_date_time(lt_date, _dates[index].date().toString(qsl("dd.MM.yy")), lt_time, _dates[index].time().toString(cTimeFormat()));
|
||||
result->onlineColor = App::onlineColorUse(_rows[index], t);
|
||||
if (_filter == MembersFilter::Recent) {
|
||||
result->canKick = (_channel->amCreator() || _channel->amEditor() || _channel->amModerator()) ? (_roles[index] == MemberRole::None) : false;
|
||||
} else if (_filter == MembersFilter::Admins) {
|
||||
result->canKick = _channel->amCreator() ? (_roles[index] == MemberRole::Editor || _roles[index] == MemberRole::Moderator) : false;
|
||||
} else {
|
||||
result->canKick = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MembersBox::Inner::clear() {
|
||||
for (int32 i = 0, l = _datas.size(); i < l; ++i) {
|
||||
delete _datas.at(i);
|
||||
}
|
||||
_datas.clear();
|
||||
_rows.clear();
|
||||
_dates.clear();
|
||||
_roles.clear();
|
||||
if (_kickBox) _kickBox->deleteLater();
|
||||
clearSel();
|
||||
}
|
||||
|
||||
MembersBox::Inner::~Inner() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void MembersBox::Inner::updateSelection() {
|
||||
if (!_mouseSelection) return;
|
||||
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
p.setY(p.y() - st::membersMarginTop);
|
||||
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
|
||||
auto selected = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
|
||||
auto kickSelected = selected;
|
||||
if (selected >= 0 && (!data(selected)->canKick || !QRect(width() - _kickWidth - st::contactsPadding.right() - st::contactsCheckPosition.x(), selected * _rowHeight + st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, _kickWidth, st::normalFont->height).contains(p))) {
|
||||
kickSelected = -1;
|
||||
}
|
||||
if (_selected != selected || _kickSelected != kickSelected) {
|
||||
updateSelectedRow();
|
||||
_selected = selected;
|
||||
_kickSelected = kickSelected;
|
||||
updateSelectedRow();
|
||||
setCursor(_kickSelected >= 0 ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::peerUpdated(PeerData *peer) {
|
||||
update();
|
||||
}
|
||||
|
||||
int MembersBox::Inner::getSelectedRowTop() const {
|
||||
if (_selected >= 0) {
|
||||
return st::membersMarginTop + _selected * _rowHeight;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MembersBox::Inner::updateRowWithTop(int rowTop) {
|
||||
update(0, rowTop, width(), _rowHeight);
|
||||
}
|
||||
|
||||
void MembersBox::Inner::updateSelectedRow() {
|
||||
auto rowTop = getSelectedRowTop();
|
||||
if (rowTop >= 0) {
|
||||
updateRowWithTop(rowTop);
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||
for (int32 i = 0, l = _rows.size(); i < l; ++i) {
|
||||
if (_rows.at(i) == peer) {
|
||||
if (_datas.at(i)) {
|
||||
_datas.at(i)->name.setText(st::contactsNameStyle, peer->name, _textNameOptions);
|
||||
update(0, st::membersMarginTop + i * _rowHeight, width(), _rowHeight);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MembersBox::Inner::membersReceived(const MTPchannels_ChannelParticipants &result, mtpRequestId req) {
|
||||
Expects(result.type() == mtpc_channels_channelParticipants);
|
||||
|
||||
clear();
|
||||
_loadingRequestId = 0;
|
||||
|
||||
auto &d = result.c_channels_channelParticipants();
|
||||
auto &v = d.vparticipants.v;
|
||||
_rows.reserve(v.size());
|
||||
_datas.reserve(v.size());
|
||||
_dates.reserve(v.size());
|
||||
_roles.reserve(v.size());
|
||||
|
||||
if (_filter == MembersFilter::Recent && _channel->membersCount() < d.vcount.v) {
|
||||
_channel->setMembersCount(d.vcount.v);
|
||||
if (App::main()) emit App::main()->peerUpdated(_channel);
|
||||
} else if (_filter == MembersFilter::Admins && _channel->adminsCount() < d.vcount.v) {
|
||||
_channel->setAdminsCount(d.vcount.v);
|
||||
if (App::main()) emit App::main()->peerUpdated(_channel);
|
||||
}
|
||||
App::feedUsers(d.vusers);
|
||||
|
||||
for (QVector<MTPChannelParticipant>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
|
||||
int32 userId = 0, addedTime = 0;
|
||||
MemberRole role = MemberRole::None;
|
||||
switch (i->type()) {
|
||||
case mtpc_channelParticipant:
|
||||
userId = i->c_channelParticipant().vuser_id.v;
|
||||
addedTime = i->c_channelParticipant().vdate.v;
|
||||
break;
|
||||
case mtpc_channelParticipantSelf:
|
||||
role = MemberRole::Self;
|
||||
userId = i->c_channelParticipantSelf().vuser_id.v;
|
||||
addedTime = i->c_channelParticipantSelf().vdate.v;
|
||||
break;
|
||||
case mtpc_channelParticipantModerator:
|
||||
role = MemberRole::Moderator;
|
||||
userId = i->c_channelParticipantModerator().vuser_id.v;
|
||||
addedTime = i->c_channelParticipantModerator().vdate.v;
|
||||
break;
|
||||
case mtpc_channelParticipantEditor:
|
||||
role = MemberRole::Editor;
|
||||
userId = i->c_channelParticipantEditor().vuser_id.v;
|
||||
addedTime = i->c_channelParticipantEditor().vdate.v;
|
||||
break;
|
||||
case mtpc_channelParticipantKicked:
|
||||
userId = i->c_channelParticipantKicked().vuser_id.v;
|
||||
addedTime = i->c_channelParticipantKicked().vdate.v;
|
||||
role = MemberRole::Kicked;
|
||||
break;
|
||||
case mtpc_channelParticipantCreator:
|
||||
userId = i->c_channelParticipantCreator().vuser_id.v;
|
||||
addedTime = _channel->date;
|
||||
role = MemberRole::Creator;
|
||||
break;
|
||||
}
|
||||
if (UserData *user = App::userLoaded(userId)) {
|
||||
_rows.push_back(user);
|
||||
_dates.push_back(date(addedTime));
|
||||
_roles.push_back(role);
|
||||
_datas.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
// update admins if we got all of them
|
||||
if (_filter == MembersFilter::Admins && _channel->isMegagroup() && _rows.size() < Global::ChatSizeMax()) {
|
||||
_channel->mgInfo->lastAdmins.clear();
|
||||
for (int32 i = 0, l = _rows.size(); i != l; ++i) {
|
||||
if (_roles.at(i) == MemberRole::Creator || _roles.at(i) == MemberRole::Editor) {
|
||||
_channel->mgInfo->lastAdmins.insert(_rows.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
Notify::peerUpdatedDelayed(_channel, Notify::PeerUpdate::Flag::AdminsChanged);
|
||||
}
|
||||
|
||||
if (_rows.isEmpty()) {
|
||||
_rows.push_back(App::self());
|
||||
_dates.push_back(date(MTP_int(_channel->date)));
|
||||
_roles.push_back(MemberRole::Self);
|
||||
_datas.push_back(0);
|
||||
}
|
||||
|
||||
clearSel();
|
||||
_loading = false;
|
||||
refresh();
|
||||
|
||||
emit loaded();
|
||||
}
|
||||
|
||||
bool MembersBox::Inner::membersFailed(const RPCError &error, mtpRequestId req) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MembersBox::Inner::kickDone(const MTPUpdates &result, mtpRequestId req) {
|
||||
App::main()->sentUpdatesReceived(result);
|
||||
|
||||
if (_kickRequestId != req) return;
|
||||
removeKicked();
|
||||
if (_kickBox) _kickBox->closeBox();
|
||||
}
|
||||
|
||||
void MembersBox::Inner::kickAdminDone(const MTPUpdates &result, mtpRequestId req) {
|
||||
if (_kickRequestId != req) return;
|
||||
if (App::main()) App::main()->sentUpdatesReceived(result);
|
||||
removeKicked();
|
||||
if (_kickBox) _kickBox->closeBox();
|
||||
}
|
||||
|
||||
bool MembersBox::Inner::kickFail(const RPCError &error, mtpRequestId req) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
if (_kickBox) _kickBox->closeBox();
|
||||
load();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MembersBox::Inner::removeKicked() {
|
||||
_kickRequestId = 0;
|
||||
int32 index = _rows.indexOf(_kickConfirm);
|
||||
if (index >= 0) {
|
||||
_rows.removeAt(index);
|
||||
delete _datas.at(index);
|
||||
_datas.removeAt(index);
|
||||
_dates.removeAt(index);
|
||||
_roles.removeAt(index);
|
||||
clearSel();
|
||||
if (_filter == MembersFilter::Recent && _channel->membersCount() > 1) {
|
||||
_channel->setMembersCount(_channel->membersCount() - 1);
|
||||
if (App::main()) emit App::main()->peerUpdated(_channel);
|
||||
} else if (_filter == MembersFilter::Admins && _channel->adminsCount() > 1) {
|
||||
_channel->setAdminsCount(_channel->adminsCount() - 1);
|
||||
if (App::main()) emit App::main()->peerUpdated(_channel);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
_kickConfirm = 0;
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "core/single_timer.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
||||
class ContactsBox;
|
||||
class ConfirmBox;
|
||||
|
||||
enum class MembersFilter {
|
||||
Recent,
|
||||
Admins,
|
||||
};
|
||||
using MembersAlreadyIn = OrderedSet<UserData*>;
|
||||
|
||||
// Not used for now.
|
||||
//
|
||||
//class MembersAddButton : public Ui::RippleButton {
|
||||
//public:
|
||||
// MembersAddButton(QWidget *parent, const style::TwoIconButton &st);
|
||||
//
|
||||
//protected:
|
||||
// void paintEvent(QPaintEvent *e) override;
|
||||
//
|
||||
// QImage prepareRippleMask() const override;
|
||||
// QPoint prepareRippleStartPosition() const override;
|
||||
//
|
||||
//private:
|
||||
// const style::TwoIconButton &_st;
|
||||
//
|
||||
//};
|
||||
|
||||
class MembersBox : public BoxContent {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MembersBox(QWidget*, ChannelData *channel, MembersFilter filter);
|
||||
|
||||
public slots:
|
||||
void onAdminAdded();
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
void onAdd();
|
||||
|
||||
ChannelData *_channel = nullptr;
|
||||
MembersFilter _filter = MembersFilter::Recent;
|
||||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
QPointer<ContactsBox> _addBox;
|
||||
|
||||
object_ptr<SingleTimer> _loadTimer = { nullptr };
|
||||
|
||||
};
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
class MembersBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Inner(QWidget *parent, ChannelData *channel, MembersFilter filter);
|
||||
|
||||
void selectSkip(int32 dir);
|
||||
void selectSkipPage(int32 h, int32 dir);
|
||||
|
||||
void chooseParticipant();
|
||||
|
||||
void refresh();
|
||||
|
||||
ChannelData *channel() const;
|
||||
MembersFilter filter() const;
|
||||
|
||||
bool isLoaded() const {
|
||||
return !_loading;
|
||||
}
|
||||
void clearSel();
|
||||
|
||||
MembersAlreadyIn already() const;
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
|
||||
~Inner();
|
||||
|
||||
signals:
|
||||
void mustScrollTo(int ymin, int ymax);
|
||||
void loaded();
|
||||
|
||||
public slots:
|
||||
void load();
|
||||
|
||||
void peerUpdated(PeerData *peer);
|
||||
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void enterEventHook(QEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
struct MemberData {
|
||||
MemberData();
|
||||
~MemberData();
|
||||
|
||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
int rippleRowTop = 0;
|
||||
Text name;
|
||||
QString online;
|
||||
bool onlineColor;
|
||||
bool canKick;
|
||||
};
|
||||
void addRipple(MemberData *data);
|
||||
void stopLastRipple(MemberData *data);
|
||||
void setPressed(int pressed);
|
||||
|
||||
void updateSelection();
|
||||
void loadProfilePhotos();
|
||||
|
||||
void updateRowWithTop(int rowTop);
|
||||
int getSelectedRowTop() const;
|
||||
void updateSelectedRow();
|
||||
MemberData *data(int32 index);
|
||||
|
||||
void paintDialog(Painter &p, TimeMs ms, PeerData *peer, MemberData *data, bool selected, bool kickSelected);
|
||||
|
||||
void membersReceived(const MTPchannels_ChannelParticipants &result, mtpRequestId req);
|
||||
bool membersFailed(const RPCError &error, mtpRequestId req);
|
||||
|
||||
void kickDone(const MTPUpdates &result, mtpRequestId req);
|
||||
void kickAdminDone(const MTPUpdates &result, mtpRequestId req);
|
||||
bool kickFail(const RPCError &error, mtpRequestId req);
|
||||
void removeKicked();
|
||||
|
||||
void clear();
|
||||
|
||||
int _rowHeight = 0;
|
||||
int _visibleTop = 0;
|
||||
int _visibleBottom = 0;
|
||||
|
||||
ChannelData *_channel = nullptr;
|
||||
MembersFilter _filter;
|
||||
|
||||
QString _kickText;
|
||||
TimeId _time = 0;
|
||||
int _kickWidth = 0;
|
||||
|
||||
int _selected = -1;
|
||||
int _pressed = -1;
|
||||
int _kickSelected = -1;
|
||||
int _kickPressed = -1;
|
||||
bool _mouseSelection = false;
|
||||
|
||||
UserData *_kickConfirm = nullptr;
|
||||
mtpRequestId _kickRequestId = 0;
|
||||
|
||||
QPointer<ConfirmBox> _kickBox;
|
||||
|
||||
enum class MemberRole {
|
||||
None,
|
||||
Self,
|
||||
Creator,
|
||||
Editor,
|
||||
Moderator,
|
||||
Kicked
|
||||
};
|
||||
|
||||
bool _loading = true;
|
||||
mtpRequestId _loadingRequestId = 0;
|
||||
typedef QVector<UserData*> MemberRows;
|
||||
typedef QVector<QDateTime> MemberDates;
|
||||
typedef QVector<MemberRole> MemberRoles;
|
||||
typedef QVector<MemberData*> MemberDatas;
|
||||
MemberRows _rows;
|
||||
MemberDates _dates;
|
||||
MemberRoles _roles;
|
||||
MemberDatas _datas;
|
||||
|
||||
int _aboutWidth = 0;
|
||||
Text _about;
|
||||
int _aboutHeight = 0;
|
||||
|
||||
QPoint _lastMousePos;
|
||||
|
||||
};
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/notifications_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "styles/style_boxes.h"
|
||||
@@ -119,7 +119,7 @@ NotificationsBox::NotificationsBox(QWidget *parent)
|
||||
}
|
||||
|
||||
void NotificationsBox::prepare() {
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
||||
_sampleOpacities.reserve(kMaxNotificationsCount);
|
||||
for (int i = 0; i != kMaxNotificationsCount; ++i) {
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/passcode_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
@@ -31,11 +31,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
PasscodeBox::PasscodeBox(QWidget*, bool turningOff)
|
||||
: _turningOff(turningOff)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField, lang(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
|
||||
, _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_passcode_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField, langFactory(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
|
||||
, _reenterPasscode(this, st::defaultInputField, langFactory(lng_passcode_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField, langFactory(lng_cloud_password_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, langFactory(lng_cloud_password_email))
|
||||
, _recover(this, lang(lng_signin_recover)) {
|
||||
}
|
||||
|
||||
@@ -46,34 +46,34 @@ PasscodeBox::PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &
|
||||
, _curSalt(curSalt)
|
||||
, _hasRecovery(hasRecovery)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, lang(lng_cloud_password_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
|
||||
, _reenterPasscode(this, st::defaultInputField, lang(lng_cloud_password_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_hint : lng_cloud_password_change_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField, langFactory(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
|
||||
, _reenterPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField, langFactory(curSalt.isEmpty() ? lng_cloud_password_hint : lng_cloud_password_change_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, langFactory(lng_cloud_password_email))
|
||||
, _recover(this, lang(lng_signin_recover)) {
|
||||
if (!hint.isEmpty()) _hintText.setText(st::passcodeTextStyle, lng_signin_hint(lt_password_hint, hint));
|
||||
}
|
||||
|
||||
void PasscodeBox::prepare() {
|
||||
addButton(lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(_turningOff ? lng_passcode_remove_button : lng_settings_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
_about.setRichText(st::passcodeTextStyle, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about));
|
||||
_aboutHeight = _about.countHeight(st::boxWidth - st::boxPadding.left() * 1.5);
|
||||
if (_turningOff) {
|
||||
_oldPasscode->show();
|
||||
setTitle(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove));
|
||||
setTitle(langFactory(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove));
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom());
|
||||
} else {
|
||||
auto has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
|
||||
if (has) {
|
||||
_oldPasscode->show();
|
||||
setTitle(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change));
|
||||
setTitle(langFactory(_cloudPwd ? lng_cloud_password_change : lng_passcode_change));
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom());
|
||||
} else {
|
||||
_oldPasscode->hide();
|
||||
setTitle(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create));
|
||||
setTitle(langFactory(_cloudPwd ? lng_cloud_password_create : lng_passcode_create));
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + st::passcodeAboutSkip + _aboutHeight + (_cloudPwd ? (st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip) : st::passcodePadding.bottom()));
|
||||
}
|
||||
}
|
||||
@@ -421,14 +421,14 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) {
|
||||
|
||||
RecoverBox::RecoverBox(QWidget*, const QString &pattern)
|
||||
: _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
|
||||
, _recoverCode(this, st::defaultInputField, lang(lng_signin_code)) {
|
||||
, _recoverCode(this, st::defaultInputField, langFactory(lng_signin_code)) {
|
||||
}
|
||||
|
||||
void RecoverBox::prepare() {
|
||||
setTitle(lang(lng_signin_recover_title));
|
||||
setTitle(langFactory(lng_signin_recover_title));
|
||||
|
||||
addButton(lang(lng_passcode_submit), [this] { onSubmit(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_passcode_submit), [this] { onSubmit(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace Ui {
|
||||
class RippleAnimation;
|
||||
@@ -32,216 +33,305 @@ class WidgetSlideWrap;
|
||||
class FlatLabel;
|
||||
} // namespace Ui
|
||||
|
||||
class PeerListBox : public BoxContent {
|
||||
class Inner;
|
||||
|
||||
using PeerListRowId = uint64;
|
||||
class PeerListRow {
|
||||
public:
|
||||
using RowId = uint64;
|
||||
PeerListRow(gsl::not_null<PeerData*> peer);
|
||||
PeerListRow(gsl::not_null<PeerData*> peer, PeerListRowId id);
|
||||
|
||||
class Row {
|
||||
public:
|
||||
Row(PeerData *peer);
|
||||
Row(PeerData *peer, RowId id);
|
||||
void setDisabled(bool disabled) {
|
||||
_disabled = disabled;
|
||||
}
|
||||
|
||||
void setDisabled(bool disabled) {
|
||||
_disabled = disabled;
|
||||
}
|
||||
// Checked state is controlled by the box with multiselect,
|
||||
// not by the row itself, so there is no setChecked() method.
|
||||
// We can query the checked state from row, but before it is
|
||||
// added to the box it is always false.
|
||||
bool checked() const;
|
||||
|
||||
// Checked state is controlled by the box with multiselect,
|
||||
// not by the row itself, so there is no setChecked() method.
|
||||
// We can query the checked state from row, but before it is
|
||||
// added to the box it is always false.
|
||||
bool checked() const;
|
||||
gsl::not_null<PeerData*> peer() const {
|
||||
return _peer;
|
||||
}
|
||||
PeerListRowId id() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
PeerData *peer() const {
|
||||
return _peer;
|
||||
}
|
||||
RowId id() const {
|
||||
return _id;
|
||||
}
|
||||
void setCustomStatus(const QString &status);
|
||||
void clearCustomStatus();
|
||||
|
||||
void setCustomStatus(const QString &status);
|
||||
void clearCustomStatus();
|
||||
virtual ~PeerListRow();
|
||||
|
||||
virtual ~Row();
|
||||
// Box interface.
|
||||
virtual bool needsVerifiedIcon() const {
|
||||
return _peer->isVerified();
|
||||
}
|
||||
virtual QSize actionSize() const {
|
||||
return QSize();
|
||||
}
|
||||
virtual QMargins actionMargins() const {
|
||||
return QMargins();
|
||||
}
|
||||
virtual void addActionRipple(QPoint point, base::lambda<void()> updateCallback) {
|
||||
}
|
||||
virtual void stopLastActionRipple() {
|
||||
}
|
||||
virtual void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void paintStatusText(Painter &p, int x, int y, int outerWidth, bool selected);
|
||||
|
||||
bool isInitialized() const {
|
||||
return _initialized;
|
||||
}
|
||||
virtual void lazyInitialize();
|
||||
|
||||
private:
|
||||
// Inner interface.
|
||||
friend class PeerListBox;
|
||||
friend class Inner;
|
||||
|
||||
virtual bool needsVerifiedIcon() const {
|
||||
return _peer->isVerified();
|
||||
}
|
||||
virtual QSize actionSize() const {
|
||||
return QSize();
|
||||
}
|
||||
virtual QMargins actionMargins() const {
|
||||
return QMargins();
|
||||
}
|
||||
virtual void addActionRipple(QPoint point, base::lambda<void()> updateCallback) {
|
||||
}
|
||||
virtual void stopLastActionRipple() {
|
||||
}
|
||||
virtual void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
|
||||
}
|
||||
|
||||
void refreshName();
|
||||
const Text &name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
enum class StatusType {
|
||||
Online,
|
||||
LastSeen,
|
||||
Custom,
|
||||
};
|
||||
void refreshStatus();
|
||||
|
||||
void setAbsoluteIndex(int index) {
|
||||
_absoluteIndex = index;
|
||||
}
|
||||
int absoluteIndex() const {
|
||||
return _absoluteIndex;
|
||||
}
|
||||
bool disabled() const {
|
||||
return _disabled;
|
||||
}
|
||||
bool isGlobalSearchResult() const {
|
||||
return _isGlobalSearchResult;
|
||||
}
|
||||
void setIsGlobalSearchResult(bool isGlobalSearchResult) {
|
||||
_isGlobalSearchResult = isGlobalSearchResult;
|
||||
}
|
||||
|
||||
enum class SetStyle {
|
||||
Animated,
|
||||
Fast,
|
||||
};
|
||||
template <typename UpdateCallback>
|
||||
void setChecked(bool checked, SetStyle style, UpdateCallback callback) {
|
||||
if (checked && !_checkbox) {
|
||||
createCheckbox(std::move(callback));
|
||||
}
|
||||
setCheckedInternal(checked, style);
|
||||
}
|
||||
void invalidatePixmapsCache();
|
||||
|
||||
template <typename UpdateCallback>
|
||||
void addRipple(QSize size, QPoint point, UpdateCallback updateCallback);
|
||||
void stopLastRipple();
|
||||
void paintRipple(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
void paintUserpic(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
float64 checkedRatio();
|
||||
|
||||
void setNameFirstChars(const OrderedSet<QChar> &nameFirstChars) {
|
||||
_nameFirstChars = nameFirstChars;
|
||||
}
|
||||
const OrderedSet<QChar> &nameFirstChars() const {
|
||||
return _nameFirstChars;
|
||||
}
|
||||
|
||||
private:
|
||||
void createCheckbox(base::lambda<void()> updateCallback);
|
||||
void setCheckedInternal(bool checked, SetStyle style);
|
||||
void paintDisabledCheckUserpic(Painter &p, int x, int y, int outerWidth) const;
|
||||
|
||||
RowId _id = 0;
|
||||
PeerData *_peer = nullptr;
|
||||
bool _initialized = false;
|
||||
std::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||
std::unique_ptr<Ui::RoundImageCheckbox> _checkbox;
|
||||
Text _name;
|
||||
QString _status;
|
||||
StatusType _statusType = StatusType::Online;
|
||||
bool _disabled = false;
|
||||
int _absoluteIndex = -1;
|
||||
OrderedSet<QChar> _nameFirstChars;
|
||||
bool _isGlobalSearchResult = false;
|
||||
void refreshName();
|
||||
const Text &name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
enum class StatusType {
|
||||
Online,
|
||||
LastSeen,
|
||||
Custom,
|
||||
};
|
||||
void refreshStatus();
|
||||
|
||||
class Controller {
|
||||
public:
|
||||
virtual void prepare() = 0;
|
||||
virtual void rowClicked(Row *row) = 0;
|
||||
virtual void rowActionClicked(Row *row) {
|
||||
}
|
||||
virtual void preloadRows() {
|
||||
}
|
||||
virtual std::unique_ptr<Row> createGlobalRow(PeerData *peer) {
|
||||
return std::unique_ptr<Row>();
|
||||
}
|
||||
|
||||
virtual ~Controller() = default;
|
||||
|
||||
protected:
|
||||
PeerListBox *view() const {
|
||||
return _view;
|
||||
}
|
||||
|
||||
private:
|
||||
void setView(PeerListBox *box) {
|
||||
_view = box;
|
||||
prepare();
|
||||
}
|
||||
|
||||
PeerListBox *_view = nullptr;
|
||||
|
||||
friend class PeerListBox;
|
||||
friend class Inner;
|
||||
void setAbsoluteIndex(int index) {
|
||||
_absoluteIndex = index;
|
||||
}
|
||||
int absoluteIndex() const {
|
||||
return _absoluteIndex;
|
||||
}
|
||||
bool disabled() const {
|
||||
return _disabled;
|
||||
}
|
||||
bool isSearchResult() const {
|
||||
return _isSearchResult;
|
||||
}
|
||||
void setIsSearchResult(bool isSearchResult) {
|
||||
_isSearchResult = isSearchResult;
|
||||
}
|
||||
|
||||
enum class SetStyle {
|
||||
Animated,
|
||||
Fast,
|
||||
};
|
||||
PeerListBox(QWidget*, std::unique_ptr<Controller> controller);
|
||||
template <typename UpdateCallback>
|
||||
void setChecked(bool checked, SetStyle style, UpdateCallback callback) {
|
||||
if (checked && !_checkbox) {
|
||||
createCheckbox(std::move(callback));
|
||||
}
|
||||
setCheckedInternal(checked, style);
|
||||
}
|
||||
void invalidatePixmapsCache();
|
||||
|
||||
// Interface for the controller.
|
||||
void appendRow(std::unique_ptr<Row> row);
|
||||
void prependRow(std::unique_ptr<Row> row);
|
||||
Row *findRow(RowId id);
|
||||
void updateRow(Row *row);
|
||||
void removeRow(Row *row);
|
||||
void setRowChecked(Row *row, bool checked);
|
||||
int fullRowsCount() const;
|
||||
Row *rowAt(int index) const;
|
||||
void setAboutText(const QString &aboutText);
|
||||
void setAbout(object_ptr<Ui::FlatLabel> about);
|
||||
void refreshRows();
|
||||
template <typename UpdateCallback>
|
||||
void addRipple(QSize size, QPoint point, UpdateCallback updateCallback);
|
||||
void stopLastRipple();
|
||||
void paintRipple(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
void paintUserpic(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
float64 checkedRatio();
|
||||
|
||||
// Search works only with RowId == peer->id.
|
||||
enum class SearchMode {
|
||||
None,
|
||||
Local,
|
||||
Global,
|
||||
};
|
||||
void setSearchMode(SearchMode mode);
|
||||
void setSearchNoResultsText(const QString &noResultsText);
|
||||
void setSearchNoResults(object_ptr<Ui::FlatLabel> searchNoResults);
|
||||
void setSearchLoadingText(const QString &searchLoadingText);
|
||||
void setSearchLoading(object_ptr<Ui::FlatLabel> searchLoading);
|
||||
void setNameFirstChars(const OrderedSet<QChar> &nameFirstChars) {
|
||||
_nameFirstChars = nameFirstChars;
|
||||
}
|
||||
const OrderedSet<QChar> &nameFirstChars() const {
|
||||
return _nameFirstChars;
|
||||
}
|
||||
|
||||
virtual void lazyInitialize();
|
||||
virtual void paintStatusText(Painter &p, int x, int y, int availableWidth, int outerWidth, bool selected);
|
||||
|
||||
protected:
|
||||
bool isInitialized() const {
|
||||
return _initialized;
|
||||
}
|
||||
|
||||
private:
|
||||
void createCheckbox(base::lambda<void()> updateCallback);
|
||||
void setCheckedInternal(bool checked, SetStyle style);
|
||||
void paintDisabledCheckUserpic(Painter &p, int x, int y, int outerWidth) const;
|
||||
void setStatusText(const QString &text);
|
||||
|
||||
PeerListRowId _id = 0;
|
||||
gsl::not_null<PeerData*> _peer;
|
||||
std::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||
std::unique_ptr<Ui::RoundImageCheckbox> _checkbox;
|
||||
Text _name;
|
||||
Text _status;
|
||||
StatusType _statusType = StatusType::Online;
|
||||
OrderedSet<QChar> _nameFirstChars;
|
||||
int _absoluteIndex = -1;
|
||||
bool _initialized : 1;
|
||||
bool _disabled : 1;
|
||||
bool _isSearchResult : 1;
|
||||
|
||||
};
|
||||
|
||||
enum class PeerListSearchMode {
|
||||
Disabled,
|
||||
Enabled,
|
||||
};
|
||||
|
||||
class PeerListDelegate {
|
||||
public:
|
||||
virtual void peerListSetTitle(base::lambda<QString()> title) = 0;
|
||||
virtual void peerListSetDescription(object_ptr<Ui::FlatLabel> description) = 0;
|
||||
virtual void peerListSetSearchLoading(object_ptr<Ui::FlatLabel> loading) = 0;
|
||||
virtual void peerListSetSearchNoResults(object_ptr<Ui::FlatLabel> noResults) = 0;
|
||||
virtual void peerListSetSearchMode(PeerListSearchMode mode) = 0;
|
||||
virtual void peerListAppendRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
virtual void peerListAppendSearchRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
virtual void peerListAppendFoundRow(gsl::not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListPrependRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
virtual void peerListPrependRowFromSearchResult(gsl::not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListUpdateRow(gsl::not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListRemoveRow(gsl::not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListConvertRowToSearchResult(gsl::not_null<PeerListRow*> row) = 0;
|
||||
virtual bool peerListIsRowSelected(gsl::not_null<PeerData*> peer) = 0;
|
||||
virtual void peerListSetRowChecked(gsl::not_null<PeerListRow*> row, bool checked) = 0;
|
||||
virtual gsl::not_null<PeerListRow*> peerListRowAt(int index) = 0;
|
||||
virtual void peerListRefreshRows() = 0;
|
||||
virtual void peerListScrollToTop() = 0;
|
||||
virtual int peerListFullRowsCount() = 0;
|
||||
virtual PeerListRow *peerListFindRow(PeerListRowId id) = 0;
|
||||
virtual void peerListSortRows(base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) = 0;
|
||||
virtual void peerListPartitionRows(base::lambda<bool(PeerListRow &a)> border) = 0;
|
||||
|
||||
template <typename PeerDataRange>
|
||||
void addSelectedRows(PeerDataRange &&range) {
|
||||
Expects(_select != nullptr);
|
||||
void peerListAddSelectedRows(PeerDataRange &&range) {
|
||||
for (auto peer : range) {
|
||||
addSelectItem(peer, Row::SetStyle::Fast);
|
||||
peerListAddSelectedRowInBunch(peer);
|
||||
}
|
||||
finishSelectItemsBunch();
|
||||
peerListFinishSelectedRowsBunch();
|
||||
}
|
||||
QVector<PeerData*> collectSelectedRows() const;
|
||||
|
||||
// callback takes two iterators, like [](auto &begin, auto &end).
|
||||
template <typename ReorderCallback>
|
||||
void reorderRows(ReorderCallback &&callback);
|
||||
virtual std::vector<gsl::not_null<PeerData*>> peerListCollectSelectedRows() = 0;
|
||||
virtual ~PeerListDelegate() = default;
|
||||
|
||||
bool isRowSelected(PeerData *peer) const;
|
||||
private:
|
||||
virtual void peerListAddSelectedRowInBunch(gsl::not_null<PeerData*> peer) = 0;
|
||||
virtual void peerListFinishSelectedRowsBunch() = 0;
|
||||
|
||||
};
|
||||
|
||||
class PeerListSearchDelegate {
|
||||
public:
|
||||
virtual void peerListSearchAddRow(gsl::not_null<PeerData*> peer) = 0;
|
||||
virtual void peerListSearchRefreshRows() = 0;
|
||||
virtual ~PeerListSearchDelegate() = default;
|
||||
|
||||
};
|
||||
|
||||
class PeerListSearchController {
|
||||
public:
|
||||
virtual void searchQuery(const QString &query) = 0;
|
||||
virtual bool isLoading() = 0;
|
||||
virtual bool loadMoreRows() = 0;
|
||||
virtual ~PeerListSearchController() = default;
|
||||
|
||||
void setDelegate(gsl::not_null<PeerListSearchDelegate*> delegate) {
|
||||
_delegate = delegate;
|
||||
}
|
||||
|
||||
protected:
|
||||
gsl::not_null<PeerListSearchDelegate*> delegate() const {
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
private:
|
||||
PeerListSearchDelegate *_delegate = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class PeerListController : public PeerListSearchDelegate {
|
||||
public:
|
||||
// Search works only with RowId == peer->id.
|
||||
PeerListController(std::unique_ptr<PeerListSearchController> searchController = nullptr);
|
||||
|
||||
void setDelegate(gsl::not_null<PeerListDelegate*> delegate) {
|
||||
_delegate = delegate;
|
||||
prepare();
|
||||
}
|
||||
|
||||
virtual void prepare() = 0;
|
||||
virtual void rowClicked(gsl::not_null<PeerListRow*> row) = 0;
|
||||
virtual void rowActionClicked(gsl::not_null<PeerListRow*> row) {
|
||||
}
|
||||
virtual void loadMoreRows() {
|
||||
}
|
||||
bool isSearchLoading() const {
|
||||
return _searchController ? _searchController->isLoading() : false;
|
||||
}
|
||||
virtual std::unique_ptr<PeerListRow> createSearchRow(gsl::not_null<PeerData*> peer) {
|
||||
return std::unique_ptr<PeerListRow>();
|
||||
}
|
||||
|
||||
bool isRowSelected(gsl::not_null<PeerData*> peer) {
|
||||
return delegate()->peerListIsRowSelected(peer);
|
||||
}
|
||||
|
||||
virtual bool searchInLocal() {
|
||||
return true;
|
||||
}
|
||||
bool hasComplexSearch() const;
|
||||
void search(const QString &query);
|
||||
|
||||
void peerListSearchAddRow(gsl::not_null<PeerData*> peer) override;
|
||||
void peerListSearchRefreshRows() override;
|
||||
|
||||
virtual ~PeerListController() = default;
|
||||
|
||||
protected:
|
||||
gsl::not_null<PeerListDelegate*> delegate() const {
|
||||
return _delegate;
|
||||
}
|
||||
PeerListSearchController *searchController() const {
|
||||
return _searchController.get();
|
||||
}
|
||||
|
||||
void setDescriptionText(const QString &text);
|
||||
void setSearchLoadingText(const QString &text);
|
||||
void setSearchNoResultsText(const QString &text);
|
||||
void setDescription(object_ptr<Ui::FlatLabel> description) {
|
||||
delegate()->peerListSetDescription(std::move(description));
|
||||
}
|
||||
void setSearchLoading(object_ptr<Ui::FlatLabel> loading) {
|
||||
delegate()->peerListSetSearchLoading(std::move(loading));
|
||||
}
|
||||
void setSearchNoResults(object_ptr<Ui::FlatLabel> noResults) {
|
||||
delegate()->peerListSetSearchNoResults(std::move(noResults));
|
||||
}
|
||||
|
||||
private:
|
||||
PeerListDelegate *_delegate = nullptr;
|
||||
std::unique_ptr<PeerListSearchController> _searchController = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class PeerListBox : public BoxContent, public PeerListDelegate {
|
||||
public:
|
||||
PeerListBox(QWidget*, std::unique_ptr<PeerListController> controller, base::lambda<void(PeerListBox*)> init);
|
||||
|
||||
void peerListSetTitle(base::lambda<QString()> title) override {
|
||||
setTitle(std::move(title));
|
||||
}
|
||||
void peerListSetDescription(object_ptr<Ui::FlatLabel> description) override;
|
||||
void peerListSetSearchLoading(object_ptr<Ui::FlatLabel> loading) override;
|
||||
void peerListSetSearchNoResults(object_ptr<Ui::FlatLabel> noResults) override;
|
||||
void peerListSetSearchMode(PeerListSearchMode mode) override;
|
||||
void peerListAppendRow(std::unique_ptr<PeerListRow> row) override;
|
||||
void peerListAppendSearchRow(std::unique_ptr<PeerListRow> row) override;
|
||||
void peerListAppendFoundRow(gsl::not_null<PeerListRow*> row) override;
|
||||
void peerListPrependRow(std::unique_ptr<PeerListRow> row) override;
|
||||
void peerListPrependRowFromSearchResult(gsl::not_null<PeerListRow*> row) override;
|
||||
void peerListUpdateRow(gsl::not_null<PeerListRow*> row) override;
|
||||
void peerListRemoveRow(gsl::not_null<PeerListRow*> row) override;
|
||||
void peerListConvertRowToSearchResult(gsl::not_null<PeerListRow*> row) override;
|
||||
void peerListSetRowChecked(gsl::not_null<PeerListRow*> row, bool checked) override;
|
||||
gsl::not_null<PeerListRow*> peerListRowAt(int index) override;
|
||||
bool peerListIsRowSelected(gsl::not_null<PeerData*> peer) override;
|
||||
std::vector<gsl::not_null<PeerData*>> peerListCollectSelectedRows() override;
|
||||
void peerListRefreshRows() override;
|
||||
void peerListScrollToTop() override;
|
||||
int peerListFullRowsCount() override;
|
||||
PeerListRow *peerListFindRow(PeerListRowId id) override;
|
||||
void peerListSortRows(base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) override;
|
||||
void peerListPartitionRows(base::lambda<bool(PeerListRow &a)> border) override;
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
@@ -249,10 +339,15 @@ protected:
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
void addSelectItem(PeerData *peer, Row::SetStyle style);
|
||||
void finishSelectItemsBunch();
|
||||
void peerListAddSelectedRowInBunch(gsl::not_null<PeerData*> peer) override {
|
||||
addSelectItem(peer, PeerListRow::SetStyle::Fast);
|
||||
}
|
||||
void peerListFinishSelectedRowsBunch() override;
|
||||
|
||||
void addSelectItem(gsl::not_null<PeerData*> peer, PeerListRow::SetStyle style);
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> createMultiSelect();
|
||||
int getTopScrollSkip() const;
|
||||
void updateScrollSkips();
|
||||
@@ -260,18 +355,20 @@ private:
|
||||
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select = { nullptr };
|
||||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
std::unique_ptr<Controller> _controller;
|
||||
std::unique_ptr<PeerListController> _controller;
|
||||
base::lambda<void(PeerListBox*)> _init;
|
||||
|
||||
};
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
class PeerListBox::Inner : public TWidget, private MTP::Sender, private base::Subscriber {
|
||||
class PeerListBox::Inner : public TWidget, private base::Subscriber {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Inner(QWidget *parent, Controller *controller);
|
||||
Inner(QWidget *parent, gsl::not_null<PeerListController*> controller);
|
||||
|
||||
void selectSkip(int direction);
|
||||
void selectSkipPage(int height, int direction);
|
||||
@@ -284,22 +381,26 @@ public:
|
||||
void submitted();
|
||||
|
||||
// Interface for the controller.
|
||||
void appendRow(std::unique_ptr<Row> row);
|
||||
void prependRow(std::unique_ptr<Row> row);
|
||||
Row *findRow(RowId id);
|
||||
void updateRow(Row *row) {
|
||||
void appendRow(std::unique_ptr<PeerListRow> row);
|
||||
void appendSearchRow(std::unique_ptr<PeerListRow> row);
|
||||
void appendFoundRow(gsl::not_null<PeerListRow*> row);
|
||||
void prependRow(std::unique_ptr<PeerListRow> row);
|
||||
void prependRowFromSearchResult(gsl::not_null<PeerListRow*> row);
|
||||
PeerListRow *findRow(PeerListRowId id);
|
||||
void updateRow(gsl::not_null<PeerListRow*> row) {
|
||||
updateRow(row, RowIndex());
|
||||
}
|
||||
void removeRow(Row *row);
|
||||
void removeRow(gsl::not_null<PeerListRow*> row);
|
||||
void convertRowToSearchResult(gsl::not_null<PeerListRow*> row);
|
||||
int fullRowsCount() const;
|
||||
Row *rowAt(int index) const;
|
||||
void setAbout(object_ptr<Ui::FlatLabel> about);
|
||||
gsl::not_null<PeerListRow*> rowAt(int index) const;
|
||||
void setDescription(object_ptr<Ui::FlatLabel> description);
|
||||
void setSearchLoading(object_ptr<Ui::FlatLabel> loading);
|
||||
void setSearchNoResults(object_ptr<Ui::FlatLabel> noResults);
|
||||
void refreshRows();
|
||||
void setSearchMode(SearchMode mode);
|
||||
void setSearchNoResults(object_ptr<Ui::FlatLabel> searchNoResults);
|
||||
void setSearchLoading(object_ptr<Ui::FlatLabel> searchLoading);
|
||||
|
||||
void changeCheckState(Row *row, bool checked, Row::SetStyle style);
|
||||
void setSearchMode(PeerListSearchMode mode);
|
||||
void changeCheckState(gsl::not_null<PeerListRow*> row, bool checked, PeerListRow::SetStyle style);
|
||||
|
||||
template <typename ReorderCallback>
|
||||
void reorderRows(ReorderCallback &&callback) {
|
||||
@@ -327,7 +428,7 @@ protected:
|
||||
|
||||
private:
|
||||
void refreshIndices();
|
||||
void appendGlobalSearchRow(std::unique_ptr<Row> row);
|
||||
void removeRowAtIndex(std::vector<std::unique_ptr<PeerListRow>> &from, int index);
|
||||
|
||||
void invalidatePixmapsCache();
|
||||
|
||||
@@ -370,19 +471,20 @@ private:
|
||||
void loadProfilePhotos();
|
||||
void checkScrollForPreload();
|
||||
|
||||
void updateRow(Row *row, RowIndex hint);
|
||||
void updateRow(gsl::not_null<PeerListRow*> row, RowIndex hint);
|
||||
void updateRow(RowIndex row);
|
||||
int getRowTop(RowIndex row) const;
|
||||
Row *getRow(RowIndex element);
|
||||
RowIndex findRowIndex(Row *row, RowIndex hint = RowIndex());
|
||||
QRect getActionRect(Row *row, RowIndex index) const;
|
||||
PeerListRow *getRow(RowIndex element);
|
||||
RowIndex findRowIndex(gsl::not_null<PeerListRow*> row, RowIndex hint = RowIndex());
|
||||
QRect getActionRect(gsl::not_null<PeerListRow*> row, RowIndex index) const;
|
||||
|
||||
void paintRow(Painter &p, TimeMs ms, RowIndex index);
|
||||
|
||||
void addRowEntry(Row *row);
|
||||
void addToSearchIndex(Row *row);
|
||||
void addRowEntry(gsl::not_null<PeerListRow*> row);
|
||||
void addToSearchIndex(gsl::not_null<PeerListRow*> row);
|
||||
bool addingToSearchIndex() const;
|
||||
void removeFromSearchIndex(Row *row);
|
||||
void removeFromSearchIndex(gsl::not_null<PeerListRow*> row);
|
||||
void setSearchQuery(const QString &query, const QString &normalizedQuery);
|
||||
bool showingSearch() const {
|
||||
return !_searchQuery.isEmpty();
|
||||
}
|
||||
@@ -396,14 +498,11 @@ private:
|
||||
|
||||
int labelHeight() const;
|
||||
|
||||
void needGlobalSearch();
|
||||
bool globalSearchInCache();
|
||||
void globalSearchOnServer();
|
||||
void globalSearchDone(const MTPcontacts_Found &result, mtpRequestId requestId);
|
||||
bool globalSearchLoading() const;
|
||||
void clearGlobalSearchRows();
|
||||
void clearSearchRows();
|
||||
|
||||
gsl::not_null<PeerListController*> _controller;
|
||||
PeerListSearchMode _searchMode = PeerListSearchMode::Disabled;
|
||||
|
||||
Controller *_controller = nullptr;
|
||||
int _rowHeight = 0;
|
||||
int _visibleTop = 0;
|
||||
int _visibleBottom = 0;
|
||||
@@ -412,43 +511,32 @@ private:
|
||||
Selected _pressed;
|
||||
bool _mouseSelection = false;
|
||||
|
||||
std::vector<std::unique_ptr<Row>> _rows;
|
||||
std::map<RowId, Row*> _rowsById;
|
||||
std::map<PeerData*, std::vector<Row*>> _rowsByPeer;
|
||||
std::vector<std::unique_ptr<PeerListRow>> _rows;
|
||||
std::map<PeerListRowId, gsl::not_null<PeerListRow*>> _rowsById;
|
||||
std::map<PeerData*, std::vector<gsl::not_null<PeerListRow*>>> _rowsByPeer;
|
||||
|
||||
SearchMode _searchMode = SearchMode::None;
|
||||
std::map<QChar, std::vector<Row*>> _searchIndex;
|
||||
std::map<QChar, std::vector<gsl::not_null<PeerListRow*>>> _searchIndex;
|
||||
QString _searchQuery;
|
||||
std::vector<Row*> _filterResults;
|
||||
QString _normalizedSearchQuery;
|
||||
QString _mentionHighlight;
|
||||
std::vector<gsl::not_null<PeerListRow*>> _filterResults;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _about = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _description = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _searchNoResults = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _searchLoading = { nullptr };
|
||||
|
||||
QPoint _lastMousePosition;
|
||||
|
||||
std::vector<std::unique_ptr<Row>> _globalSearchRows;
|
||||
object_ptr<SingleTimer> _globalSearchTimer = { nullptr };
|
||||
QString _globalSearchQuery;
|
||||
QString _globalSearchHighlight;
|
||||
mtpRequestId _globalSearchRequestId = 0;
|
||||
std::map<QString, MTPcontacts_Found> _globalSearchCache;
|
||||
std::map<mtpRequestId, QString> _globalSearchQueries;
|
||||
std::vector<std::unique_ptr<PeerListRow>> _searchRows;
|
||||
|
||||
};
|
||||
|
||||
template <typename ReorderCallback>
|
||||
inline void PeerListBox::reorderRows(ReorderCallback &&callback) {
|
||||
_inner->reorderRows(std::forward<ReorderCallback>(callback));
|
||||
}
|
||||
|
||||
class PeerListRowWithLink : public PeerListBox::Row {
|
||||
class PeerListRowWithLink : public PeerListRow {
|
||||
public:
|
||||
using Row::Row;
|
||||
using PeerListRow::PeerListRow;
|
||||
|
||||
void setActionLink(const QString &action);
|
||||
|
||||
protected:
|
||||
void lazyInitialize() override;
|
||||
|
||||
private:
|
||||
@@ -462,25 +550,50 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class ChatsListBoxController : public PeerListBox::Controller, protected base::Subscriber {
|
||||
class PeerListGlobalSearchController : public PeerListSearchController, private MTP::Sender {
|
||||
public:
|
||||
PeerListGlobalSearchController();
|
||||
|
||||
void searchQuery(const QString &query) override;
|
||||
bool isLoading() override;
|
||||
bool loadMoreRows() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool searchInCache();
|
||||
void searchOnServer();
|
||||
void searchDone(const MTPcontacts_Found &result, mtpRequestId requestId);
|
||||
|
||||
base::Timer _timer;
|
||||
QString _query;
|
||||
mtpRequestId _requestId = 0;
|
||||
std::map<QString, MTPcontacts_Found> _cache;
|
||||
std::map<mtpRequestId, QString> _queries;
|
||||
|
||||
};
|
||||
|
||||
class ChatsListBoxController : public PeerListController, protected base::Subscriber {
|
||||
public:
|
||||
ChatsListBoxController(std::unique_ptr<PeerListSearchController> searchController = std::make_unique<PeerListGlobalSearchController>());
|
||||
|
||||
void prepare() override final;
|
||||
std::unique_ptr<PeerListBox::Row> createGlobalRow(PeerData *peer) override final;
|
||||
std::unique_ptr<PeerListRow> createSearchRow(gsl::not_null<PeerData*> peer) override final;
|
||||
|
||||
protected:
|
||||
class Row : public PeerListBox::Row {
|
||||
class Row : public PeerListRow {
|
||||
public:
|
||||
Row(History *history) : PeerListBox::Row(history->peer), _history(history) {
|
||||
Row(gsl::not_null<History*> history) : PeerListRow(history->peer), _history(history) {
|
||||
}
|
||||
History *history() const {
|
||||
gsl::not_null<History*> history() const {
|
||||
return _history;
|
||||
}
|
||||
|
||||
private:
|
||||
History *_history = nullptr;
|
||||
gsl::not_null<History*> _history;
|
||||
|
||||
};
|
||||
virtual std::unique_ptr<Row> createRow(History *history) = 0;
|
||||
virtual std::unique_ptr<Row> createRow(gsl::not_null<History*> history) = 0;
|
||||
virtual void prepareViewHook() = 0;
|
||||
virtual void updateRowHook(Row *row) {
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/photo_crop_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "messenger.h"
|
||||
#include "mainwidget.h"
|
||||
#include "storage/file_upload.h"
|
||||
@@ -50,8 +50,8 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) {
|
||||
}
|
||||
|
||||
void PhotoCropBox::prepare() {
|
||||
addButton(lang(lng_settings_save), [this] { sendPhoto(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { sendPhoto(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
if (peerToBareInt(_peerId)) {
|
||||
connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&)));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/rate_call_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
@@ -42,10 +42,8 @@ RateCallBox::RateCallBox(QWidget*, uint64 callId, uint64 callAccessHash)
|
||||
}
|
||||
|
||||
void RateCallBox::prepare() {
|
||||
auto titleWidth = st::boxWideWidth - 2 * st::boxTitlePosition.x();
|
||||
auto titleText = st::boxTitleFont->elided(lang(lng_call_rate_label), titleWidth);
|
||||
setTitle(titleText);
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
setTitle(langFactory(lng_call_rate_label));
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
for (auto i = 0; i < kMaxRating; ++i) {
|
||||
_stars.push_back(object_ptr<Ui::IconButton>(this, st::callRatingStar));
|
||||
@@ -75,8 +73,8 @@ void RateCallBox::ratingChanged(int value) {
|
||||
Expects(value > 0 && value <= kMaxRating);
|
||||
if (!_rating) {
|
||||
clearButtons();
|
||||
addButton(lang(lng_send_button), [this] { onSend(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_send_button), [this] { onSend(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}
|
||||
_rating = value;
|
||||
|
||||
@@ -86,7 +84,7 @@ void RateCallBox::ratingChanged(int value) {
|
||||
}
|
||||
if (value < kMaxRating) {
|
||||
if (!_comment) {
|
||||
_comment.create(this, st::callRatingComment, lang(lng_call_rate_comment));
|
||||
_comment.create(this, st::callRatingComment, langFactory(lng_call_rate_comment));
|
||||
_comment->show();
|
||||
_comment->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
|
||||
_comment->setMaxLength(MaxPhotoCaption);
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/report_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
@@ -38,10 +38,10 @@ ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer)
|
||||
}
|
||||
|
||||
void ReportBox::prepare() {
|
||||
setTitle(lang(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
|
||||
setTitle(langFactory(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
|
||||
|
||||
addButton(lang(lng_report_button), [this] { onReport(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_report_button), [this] { onReport(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
_reasonGroup->setChangedCallback([this](Reason value) { reasonChanged(value); });
|
||||
|
||||
@@ -51,7 +51,7 @@ void ReportBox::prepare() {
|
||||
void ReportBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
|
||||
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top() + _reasonSpam->getMargins().top());
|
||||
_reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListSkip);
|
||||
_reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListSkip);
|
||||
_reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListSkip);
|
||||
@@ -64,7 +64,7 @@ void ReportBox::resizeEvent(QResizeEvent *e) {
|
||||
void ReportBox::reasonChanged(Reason reason) {
|
||||
if (reason == Reason::Other) {
|
||||
if (!_reasonOtherText) {
|
||||
_reasonOtherText.create(this, st::profileReportReasonOther, lang(lng_report_reason_description));
|
||||
_reasonOtherText.create(this, st::profileReportReasonOther, langFactory(lng_report_reason_description));
|
||||
_reasonOtherText->show();
|
||||
_reasonOtherText->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
|
||||
_reasonOtherText->setMaxLength(MaxPhotoCaption);
|
||||
@@ -131,7 +131,7 @@ bool ReportBox::reportFail(const RPCError &error) {
|
||||
}
|
||||
|
||||
void ReportBox::updateMaxHeight() {
|
||||
auto newHeight = st::boxOptionListPadding.top() + 4 * _reasonSpam->heightNoMargins() + 3 * st::boxOptionListSkip + st::boxOptionListPadding.bottom();
|
||||
auto newHeight = st::boxOptionListPadding.top() + _reasonSpam->getMargins().top() + 4 * _reasonSpam->heightNoMargins() + 3 * st::boxOptionListSkip + _reasonSpam->getMargins().bottom() + st::boxOptionListPadding.bottom();
|
||||
if (_reasonOtherText) {
|
||||
newHeight += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom();
|
||||
}
|
||||
|
||||
@@ -20,20 +20,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/self_destruction_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
void SelfDestructionBox::prepare() {
|
||||
setTitle(lang(lng_self_destruct_title));
|
||||
setTitle(langFactory(lng_self_destruct_title));
|
||||
|
||||
_ttlValues = { 30, 90, 180, 365 };
|
||||
|
||||
auto fake = object_ptr<Ui::FlatLabel>(this, lang(lng_self_destruct_description), Ui::FlatLabel::InitType::Simple, st::boxLabel);
|
||||
auto boxHeight = st::boxOptionListPadding.top()
|
||||
+ fake->height() + st::boxMediumSkip
|
||||
+ _ttlValues.size() * (st::langsButton.height + st::boxOptionListSkip) - st::boxOptionListSkip
|
||||
+ _ttlValues.size() * (st::defaultRadio.diameter + st::boxOptionListSkip) - st::boxOptionListSkip
|
||||
+ st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
|
||||
fake.destroy();
|
||||
|
||||
@@ -42,7 +42,7 @@ void SelfDestructionBox::prepare() {
|
||||
auto loading = object_ptr<Ui::FlatLabel>(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout);
|
||||
loading->moveToLeft((st::boxWidth - loading->width()) / 2, boxHeight / 3);
|
||||
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
request(MTPaccount_GetAccountTTL()).done([this, loading = std::move(loading)](const MTPAccountDaysTTL &result) mutable {
|
||||
Expects(result.type() == mtpc_accountDaysTTL);
|
||||
@@ -72,10 +72,10 @@ void SelfDestructionBox::prepare() {
|
||||
showChildren();
|
||||
|
||||
clearButtons();
|
||||
addButton(lang(lng_settings_save), [this, group] {
|
||||
addButton(langFactory(lng_settings_save), [this, group] {
|
||||
MTP::send(MTPaccount_SetAccountTTL(MTP_accountDaysTTL(MTP_int(group->value()))));
|
||||
closeBox();
|
||||
});
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}).send();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/send_files_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "history/history_media_types.h"
|
||||
@@ -46,7 +46,7 @@ bool ValidatePhotoDimensions(int width, int height) {
|
||||
SendFilesBox::SendFilesBox(QWidget*, QImage image, CompressConfirm compressed)
|
||||
: _image(image)
|
||||
, _compressConfirm(compressed)
|
||||
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption)) {
|
||||
, _caption(this, st::confirmCaptionArea, langFactory(lng_photo_caption)) {
|
||||
_files.push_back(QString());
|
||||
prepareSingleFileLayout();
|
||||
}
|
||||
@@ -54,7 +54,7 @@ SendFilesBox::SendFilesBox(QWidget*, QImage image, CompressConfirm compressed)
|
||||
SendFilesBox::SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed)
|
||||
: _files(files)
|
||||
, _compressConfirm(compressed)
|
||||
, _caption(this, st::confirmCaptionArea, lang(_files.size() > 1 ? lng_photos_comment : lng_photo_caption)) {
|
||||
, _caption(this, st::confirmCaptionArea, langFactory(_files.size() > 1 ? lng_photos_comment : lng_photo_caption)) {
|
||||
if (_files.size() == 1) {
|
||||
prepareSingleFileLayout();
|
||||
}
|
||||
@@ -237,14 +237,14 @@ void SendFilesBox::prepare() {
|
||||
updateTitleText();
|
||||
}
|
||||
|
||||
_send = addButton(lang(lng_send_button), [this] { onSend(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
_send = addButton(langFactory(lng_send_button), [this] { onSend(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
if (_compressConfirm != CompressConfirm::None) {
|
||||
auto compressed = (_compressConfirm == CompressConfirm::Auto) ? cCompressPastedImage() : (_compressConfirm == CompressConfirm::Yes);
|
||||
auto text = lng_send_images_compress(lt_count, _files.size());
|
||||
_compressed.create(this, text, compressed, st::defaultBoxCheckbox);
|
||||
connect(_compressed, SIGNAL(changed()), this, SLOT(onCompressedChange()));
|
||||
subscribe(_compressed->checkedChanged, [this](bool checked) { onCompressedChange(); });
|
||||
}
|
||||
if (_caption) {
|
||||
_caption->setMaxLength(MaxPhotoCaption);
|
||||
@@ -258,13 +258,13 @@ void SendFilesBox::prepare() {
|
||||
updateBoxSize();
|
||||
}
|
||||
|
||||
QString SendFilesBox::getSendButtonText() const {
|
||||
base::lambda<QString()> SendFilesBox::getSendButtonText() const {
|
||||
if (!_contactPhone.isEmpty()) {
|
||||
return lang(lng_send_button);
|
||||
return langFactory(lng_send_button);
|
||||
} else if (_compressed && _compressed->checked()) {
|
||||
return lng_send_photos(lt_count, _files.size());
|
||||
return [count = _files.size()] { return lng_send_photos(lt_count, count); };
|
||||
}
|
||||
return lng_send_files(lt_count, _files.size());
|
||||
return [count = _files.size()] { return lng_send_files(lt_count, count); };
|
||||
}
|
||||
|
||||
void SendFilesBox::onCompressedChange() {
|
||||
@@ -438,7 +438,7 @@ void SendFilesBox::onSend(bool ctrlShiftEnter) {
|
||||
_confirmed = true;
|
||||
if (_confirmedCallback) {
|
||||
auto compressed = _compressed ? _compressed->checked() : false;
|
||||
auto caption = _caption ? prepareText(_caption->getLastText(), true) : QString();
|
||||
auto caption = _caption ? TextUtilities::PrepareForSending(_caption->getLastText(), TextUtilities::PrepareTextOption::CheckLinks) : QString();
|
||||
_confirmedCallback(_files, _animated ? QImage() : _image, std::move(_information), compressed, caption, ctrlShiftEnter);
|
||||
}
|
||||
closeBox();
|
||||
@@ -564,7 +564,7 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
||||
}
|
||||
t_assert(_animated || _photo || _doc);
|
||||
|
||||
_field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
|
||||
_field.create(this, st::confirmCaptionArea, langFactory(lng_photo_caption), caption);
|
||||
_field->setMaxLength(MaxPhotoCaption);
|
||||
_field->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
|
||||
}
|
||||
@@ -607,8 +607,8 @@ void EditCaptionBox::clipCallback(Media::Clip::Notification notification) {
|
||||
}
|
||||
|
||||
void EditCaptionBox::prepare() {
|
||||
addButton(lang(lng_settings_save), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
updateBoxSize();
|
||||
connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool)));
|
||||
@@ -766,7 +766,7 @@ void EditCaptionBox::onSave(bool ctrlShiftEnter) {
|
||||
if (!sentEntities.v.isEmpty()) {
|
||||
flags |= MTPmessages_EditMessage::Flag::f_entities;
|
||||
}
|
||||
auto text = prepareText(_field->getLastText(), true);
|
||||
auto text = TextUtilities::PrepareForSending(_field->getLastText(), TextUtilities::PrepareTextOption::CheckLinks);
|
||||
_saveRequestId = MTP::send(MTPmessages_EditMessage(MTP_flags(flags), item->history()->peer->input, MTP_int(item->id), MTP_string(text), MTPnullMarkup, sentEntities), rpcDone(&EditCaptionBox::saveDone), rpcFail(&EditCaptionBox::saveFail));
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ private:
|
||||
void updateTitleText();
|
||||
void updateBoxSize();
|
||||
void updateControlsGeometry();
|
||||
QString getSendButtonText() const;
|
||||
base::lambda<QString()> getSendButtonText() const;
|
||||
|
||||
QString _titleText;
|
||||
QStringList _files;
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/sessions_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
@@ -35,9 +35,9 @@ SessionsBox::SessionsBox(QWidget*)
|
||||
}
|
||||
|
||||
void SessionsBox::prepare() {
|
||||
setTitle(lang(lng_sessions_other_header));
|
||||
setTitle(langFactory(lng_sessions_other_header));
|
||||
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWideWidth, st::sessionsHeight);
|
||||
|
||||
@@ -117,8 +117,8 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
||||
if (appVer == QString::number(appVer.toInt())) {
|
||||
int32 ver = appVer.toInt();
|
||||
appVer = QString("%1.%2").arg(ver / 1000000).arg((ver % 1000000) / 1000) + ((ver % 1000) ? ('.' + QString::number(ver % 1000)) : QString());
|
||||
} else {
|
||||
appVer = QString();
|
||||
//} else {
|
||||
// appVer = QString();
|
||||
}
|
||||
} else {
|
||||
appName = qs(d.vapp_name);// +qsl(" for ") + qs(d.vplatform);
|
||||
|
||||
@@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "observer_peer.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "base/qthelp_url.h"
|
||||
@@ -34,6 +34,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "history/history_media_types.h"
|
||||
#include "history/history_message.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
@@ -45,7 +46,7 @@ ShareBox::ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submi
|
||||
: _copyCallback(std::move(copyCallback))
|
||||
, _submitCallback(std::move(submitCallback))
|
||||
, _filterCallback(std::move(filterCallback))
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _select(this, st::contactsMultiSelect, langFactory(lng_participant_filter))
|
||||
, _searchTimer(this) {
|
||||
}
|
||||
|
||||
@@ -53,7 +54,7 @@ void ShareBox::prepare() {
|
||||
_select->resizeToWidth(st::boxWideWidth);
|
||||
myEnsureResized(_select);
|
||||
|
||||
setTitle(lang(lng_share_title));
|
||||
setTitle(langFactory(lng_share_title));
|
||||
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, std::move(_filterCallback)), getTopScrollSkip());
|
||||
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
|
||||
@@ -207,11 +208,11 @@ void ShareBox::updateButtons() {
|
||||
void ShareBox::createButtons() {
|
||||
clearButtons();
|
||||
if (_hasSelected) {
|
||||
addButton(lang(lng_share_confirm), [this] { onSubmit(); });
|
||||
} else {
|
||||
addButton(lang(lng_share_copy_link), [this] { onCopyLink(); });
|
||||
addButton(langFactory(lng_share_confirm), [this] { onSubmit(); });
|
||||
} else if (_copyCallback) {
|
||||
addButton(langFactory(lng_share_copy_link), [this] { onCopyLink(); });
|
||||
}
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}
|
||||
|
||||
void ShareBox::onFilterUpdate(const QString &query) {
|
||||
@@ -674,21 +675,9 @@ bool ShareBox::Inner::hasSelected() const {
|
||||
|
||||
void ShareBox::Inner::updateFilter(QString filter) {
|
||||
_lastQuery = filter.toLower().trimmed();
|
||||
filter = textSearchKey(filter);
|
||||
|
||||
QStringList f;
|
||||
if (!filter.isEmpty()) {
|
||||
QStringList filterList = filter.split(cWordSplit(), QString::SkipEmptyParts);
|
||||
int l = filterList.size();
|
||||
|
||||
f.reserve(l);
|
||||
for (int i = 0; i < l; ++i) {
|
||||
QString filterName = filterList[i].trimmed();
|
||||
if (filterName.isEmpty()) continue;
|
||||
f.push_back(filterName);
|
||||
}
|
||||
filter = f.join(' ');
|
||||
}
|
||||
auto words = TextUtilities::PrepareSearchWords(_lastQuery);
|
||||
filter = words.isEmpty() ? QString() : words.join(' ');
|
||||
if (_filter != filter) {
|
||||
_filter = filter;
|
||||
|
||||
@@ -701,10 +690,10 @@ void ShareBox::Inner::updateFilter(QString filter) {
|
||||
if (_filter.isEmpty()) {
|
||||
refresh();
|
||||
} else {
|
||||
QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi;
|
||||
QStringList::const_iterator fb = words.cbegin(), fe = words.cend(), fi;
|
||||
|
||||
_filtered.clear();
|
||||
if (!f.isEmpty()) {
|
||||
if (!words.isEmpty()) {
|
||||
const Dialogs::List *toFilter = nullptr;
|
||||
if (!_chatsIndexed->isEmpty()) {
|
||||
for (fi = fb; fi != fe; ++fi) {
|
||||
@@ -809,7 +798,7 @@ QVector<PeerData*> ShareBox::Inner::selected() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
||||
QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
||||
auto shareHashData = QByteArray(0x10, Qt::Uninitialized);
|
||||
auto shareHashDataInts = reinterpret_cast<int32*>(shareHashData.data());
|
||||
auto channel = fullId.channel ? App::channelLoaded(fullId.channel) : static_cast<ChannelData*>(nullptr);
|
||||
@@ -852,79 +841,7 @@ QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
||||
return url + shareComponent;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void shareGameScoreFromItem(HistoryItem *item) {
|
||||
struct ShareGameScoreData {
|
||||
ShareGameScoreData(const FullMsgId &msgId) : msgId(msgId) {
|
||||
}
|
||||
FullMsgId msgId;
|
||||
OrderedSet<mtpRequestId> requests;
|
||||
};
|
||||
auto data = MakeShared<ShareGameScoreData>(item->fullId());
|
||||
|
||||
auto copyCallback = [data]() {
|
||||
if (auto main = App::main()) {
|
||||
if (auto item = App::histItemById(data->msgId)) {
|
||||
if (auto bot = item->getMessageBot()) {
|
||||
if (auto media = item->getMedia()) {
|
||||
if (media->type() == MediaTypeGame) {
|
||||
auto shortName = static_cast<HistoryGame*>(media)->game()->shortName;
|
||||
|
||||
QApplication::clipboard()->setText(Messenger::Instance().createInternalLinkFull(bot->username + qsl("?game=") + shortName));
|
||||
|
||||
Ui::Toast::Show(lang(lng_share_game_link_copied));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
auto submitCallback = [data](const QVector<PeerData*> &result) {
|
||||
if (!data->requests.empty()) {
|
||||
return; // Share clicked already.
|
||||
}
|
||||
|
||||
auto doneCallback = [data](const MTPUpdates &updates, mtpRequestId requestId) {
|
||||
if (auto main = App::main()) {
|
||||
main->sentUpdatesReceived(updates);
|
||||
}
|
||||
data->requests.remove(requestId);
|
||||
if (data->requests.empty()) {
|
||||
Ui::Toast::Show(lang(lng_share_done));
|
||||
Ui::hideLayer();
|
||||
}
|
||||
};
|
||||
|
||||
auto sendFlags = MTPmessages_ForwardMessages::Flag::f_with_my_score;
|
||||
MTPVector<MTPint> msgIds = MTP_vector<MTPint>(1, MTP_int(data->msgId.msg));
|
||||
if (auto main = App::main()) {
|
||||
if (auto item = App::histItemById(data->msgId)) {
|
||||
for_const (auto peer, result) {
|
||||
MTPVector<MTPlong> random = MTP_vector<MTPlong>(1, rand_value<MTPlong>());
|
||||
auto request = MTPmessages_ForwardMessages(MTP_flags(sendFlags), item->history()->peer->input, msgIds, random, peer->input);
|
||||
auto callback = doneCallback;
|
||||
auto requestId = MTP::send(request, rpcDone(std::move(callback)));
|
||||
data->requests.insert(requestId);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
auto filterCallback = [](PeerData *peer) {
|
||||
if (peer->canWrite()) {
|
||||
if (auto channel = peer->asChannel()) {
|
||||
return !channel->isBroadcast();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Ui::show(Box<ShareBox>(std::move(copyCallback), std::move(submitCallback), std::move(filterCallback)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void shareGameScoreByHash(const QString &hash) {
|
||||
void ShareGameScoreByHash(const QString &hash) {
|
||||
auto key128Size = 0x10;
|
||||
|
||||
auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
@@ -975,12 +892,12 @@ void shareGameScoreByHash(const QString &hash) {
|
||||
}
|
||||
|
||||
if (auto item = App::histItemById(channelId, msgId)) {
|
||||
shareGameScoreFromItem(item);
|
||||
FastShareMessage(item);
|
||||
} else if (App::api()) {
|
||||
auto resolveMessageAndShareScore = [msgId](ChannelData *channel) {
|
||||
App::api()->requestMessageData(channel, msgId, [](ChannelData *channel, MsgId msgId) {
|
||||
if (auto item = App::histItemById(channel, msgId)) {
|
||||
shareGameScoreFromItem(item);
|
||||
FastShareMessage(item);
|
||||
} else {
|
||||
Ui::show(Box<InformBox>(lang(lng_edit_deleted)));
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace Ui {
|
||||
class MultiSelect;
|
||||
} // namespace Ui
|
||||
|
||||
QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
|
||||
void shareGameScoreByHash(const QString &hash);
|
||||
QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
|
||||
void ShareGameScoreByHash(const QString &hash);
|
||||
|
||||
class ShareBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/sticker_set_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
@@ -46,7 +46,7 @@ StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
|
||||
}
|
||||
|
||||
void StickerSetBox::prepare() {
|
||||
setTitle(lang(lng_contacts_loading));
|
||||
setTitle(langFactory(lng_contacts_loading));
|
||||
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, _set), st::stickersScroll);
|
||||
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
|
||||
@@ -89,16 +89,16 @@ void StickerSetBox::updateButtons() {
|
||||
clearButtons();
|
||||
if (_inner->loaded()) {
|
||||
if (_inner->notInstalled()) {
|
||||
addButton(lang(lng_stickers_add_pack), [this] { onAddStickers(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_stickers_add_pack), [this] { onAddStickers(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
} else if (_inner->official()) {
|
||||
addButton(lang(lng_about_done), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_about_done), [this] { closeBox(); });
|
||||
} else {
|
||||
addButton(lang(lng_stickers_share_pack), [this] { onShareStickers(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_stickers_share_pack), [this] { onShareStickers(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}
|
||||
} else {
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}
|
||||
update();
|
||||
}
|
||||
@@ -427,19 +427,18 @@ bool StickerSetBox::Inner::official() const {
|
||||
return _loaded && _setShortName.isEmpty();
|
||||
}
|
||||
|
||||
TextWithEntities StickerSetBox::Inner::title() const {
|
||||
auto text = _setTitle;
|
||||
auto entities = EntitiesInText();
|
||||
base::lambda<TextWithEntities()> StickerSetBox::Inner::title() const {
|
||||
auto text = TextWithEntities { _setTitle };
|
||||
if (_loaded) {
|
||||
if (_pack.isEmpty()) {
|
||||
text = lang(lng_attach_failed);
|
||||
return [] { return TextWithEntities { lang(lng_attach_failed), EntitiesInText() }; };
|
||||
} else {
|
||||
textParseEntities(text, TextParseMentions, &entities);
|
||||
TextUtilities::ParseEntities(text, TextParseMentions);
|
||||
}
|
||||
} else {
|
||||
text = lang(lng_contacts_loading);
|
||||
return [] { return TextWithEntities { lang(lng_contacts_loading), EntitiesInText() }; };
|
||||
}
|
||||
return { text, entities };
|
||||
return [text] { return text; };
|
||||
}
|
||||
|
||||
QString StickerSetBox::Inner::shortName() const {
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
bool loaded() const;
|
||||
int32 notInstalled() const;
|
||||
bool official() const;
|
||||
TextWithEntities title() const;
|
||||
base::lambda<TextWithEntities()> title() const;
|
||||
QString shortName() const;
|
||||
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stickers_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
@@ -230,7 +230,7 @@ void StickersBox::prepare() {
|
||||
} else if (_section == Section::Archived) {
|
||||
requestArchivedSets();
|
||||
} else if (_section == Section::ArchivedPart) {
|
||||
setTitle(lang(lng_stickers_archived));
|
||||
setTitle(langFactory(lng_stickers_archived));
|
||||
}
|
||||
if (Global::ArchivedStickerSetsOrder().isEmpty()) {
|
||||
preloadArchivedSets();
|
||||
@@ -252,7 +252,7 @@ void StickersBox::prepare() {
|
||||
_archived.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
|
||||
_archived.widget()->setLoadMoreCallback([this] { loadMoreArchived(); });
|
||||
|
||||
addButton(lang(lng_about_done), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_about_done), [this] { closeBox(); });
|
||||
|
||||
if (_section == Section::Installed) {
|
||||
_tab = &_installed;
|
||||
@@ -713,9 +713,11 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
||||
}
|
||||
}
|
||||
|
||||
auto statusText = (s->count > 0) ? lng_stickers_count(lt_count, s->count) : lang(lng_contacts_loading);
|
||||
|
||||
p.setFont(st::contactsStatusFont);
|
||||
p.setPen(st::contactsStatusFg);
|
||||
p.drawTextLeft(statusx, statusy, width(), lng_stickers_count(lt_count, s->count));
|
||||
p.drawTextLeft(statusx, statusy, width(), statusText);
|
||||
|
||||
p.setOpacity(1);
|
||||
if (xadd || yadd) p.translate(-xadd, -yadd);
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/username_box.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "application.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
@@ -31,7 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "messenger.h"
|
||||
|
||||
UsernameBox::UsernameBox(QWidget*)
|
||||
: _username(this, st::defaultInputField, qsl("@username"), App::self()->username, false)
|
||||
: _username(this, st::defaultInputField, [] { return qsl("@username"); }, App::self()->username, false)
|
||||
, _link(this, QString(), st::boxLinkButton)
|
||||
, _about(st::boxWidth - st::usernamePadding.left())
|
||||
, _checkTimer(this) {
|
||||
@@ -40,10 +40,10 @@ UsernameBox::UsernameBox(QWidget*)
|
||||
void UsernameBox::prepare() {
|
||||
_goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available);
|
||||
|
||||
setTitle(lang(lng_username_title));
|
||||
setTitle(langFactory(lng_username_title));
|
||||
|
||||
addButton(lang(lng_settings_save), [this] { onSave(); });
|
||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
connect(_username, SIGNAL(changed()), this, SLOT(onChanged()));
|
||||
connect(_username, SIGNAL(submitted(bool)), this, SLOT(onSave()));
|
||||
@@ -175,7 +175,7 @@ bool UsernameBox::onUpdateFail(const RPCError &error) {
|
||||
_saveRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == App::self()->username) {
|
||||
App::self()->setName(textOneLine(App::self()->firstName), textOneLine(App::self()->lastName), textOneLine(App::self()->nameOrPhone), textOneLine(_sentUsername));
|
||||
App::self()->setName(TextUtilities::SingleLine(App::self()->firstName), TextUtilities::SingleLine(App::self()->lastName), TextUtilities::SingleLine(App::self()->nameOrPhone), TextUtilities::SingleLine(_sentUsername));
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == qstr("USERNAME_INVALID")) {
|
||||
|
||||
@@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "observer_peer.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "calls/calls_instance.h"
|
||||
@@ -36,7 +36,7 @@ constexpr auto kPerPageCount = 100;
|
||||
|
||||
} // namespace
|
||||
|
||||
class BoxController::Row : public PeerListBox::Row {
|
||||
class BoxController::Row : public PeerListRow {
|
||||
public:
|
||||
Row(HistoryItem *item);
|
||||
|
||||
@@ -77,12 +77,10 @@ public:
|
||||
return _items.front()->id;
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintStatusText(Painter &p, int x, int y, int outerWidth, bool selected) override;
|
||||
void paintStatusText(Painter &p, int x, int y, int availableWidth, int outerWidth, bool selected) override;
|
||||
void addActionRipple(QPoint point, base::lambda<void()> updateCallback) override;
|
||||
void stopLastActionRipple() override;
|
||||
|
||||
private:
|
||||
bool needsVerifiedIcon() const override {
|
||||
return false;
|
||||
}
|
||||
@@ -94,6 +92,7 @@ private:
|
||||
}
|
||||
void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) override;
|
||||
|
||||
private:
|
||||
void refreshStatus();
|
||||
static Type ComputeType(HistoryItem *item);
|
||||
|
||||
@@ -105,14 +104,14 @@ private:
|
||||
|
||||
};
|
||||
|
||||
BoxController::Row::Row(HistoryItem *item) : PeerListBox::Row(item->history()->peer, item->id)
|
||||
BoxController::Row::Row(HistoryItem *item) : PeerListRow(item->history()->peer, item->id)
|
||||
, _items(1, item)
|
||||
, _date(item->date.date())
|
||||
, _type(ComputeType(item)) {
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
void BoxController::Row::paintStatusText(Painter &p, int x, int y, int outerWidth, bool selected) {
|
||||
void BoxController::Row::paintStatusText(Painter &p, int x, int y, int availableWidth, int outerWidth, bool selected) {
|
||||
auto icon = ([this] {
|
||||
switch (_type) {
|
||||
case Type::In: return &st::callArrowIn;
|
||||
@@ -122,9 +121,11 @@ void BoxController::Row::paintStatusText(Painter &p, int x, int y, int outerWidt
|
||||
Unexpected("_type in Calls::BoxController::Row::paintStatusText().");
|
||||
})();
|
||||
icon->paint(p, x + st::callArrowPosition.x(), y + st::callArrowPosition.y(), outerWidth);
|
||||
x += + st::callArrowPosition.x() + icon->width() + st::callArrowSkip;
|
||||
auto shift = st::callArrowPosition.x() + icon->width() + st::callArrowSkip;
|
||||
x += shift;
|
||||
availableWidth -= shift;
|
||||
|
||||
PeerListBox::Row::paintStatusText(p, x, y, outerWidth, selected);
|
||||
PeerListRow::paintStatusText(p, x, y, availableWidth, outerWidth, selected);
|
||||
}
|
||||
|
||||
void BoxController::Row::paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
|
||||
@@ -188,12 +189,12 @@ void BoxController::prepare() {
|
||||
if (auto row = rowForItem(item)) {
|
||||
row->itemRemoved(item);
|
||||
if (!row->hasItems()) {
|
||||
view()->removeRow(row);
|
||||
if (!view()->fullRowsCount()) {
|
||||
delegate()->peerListRemoveRow(row);
|
||||
if (!delegate()->peerListFullRowsCount()) {
|
||||
refreshAbout();
|
||||
}
|
||||
}
|
||||
view()->refreshRows();
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
});
|
||||
subscribe(Current().newServiceMessage(), [this](const FullMsgId &msgId) {
|
||||
@@ -202,20 +203,19 @@ void BoxController::prepare() {
|
||||
}
|
||||
});
|
||||
|
||||
view()->setTitle(lang(lng_call_box_title));
|
||||
view()->addButton(lang(lng_close), [this] { view()->closeBox(); });
|
||||
view()->setAboutText(lang(lng_contacts_loading));
|
||||
view()->refreshRows();
|
||||
delegate()->peerListSetTitle(langFactory(lng_call_box_title));
|
||||
setDescriptionText(lang(lng_contacts_loading));
|
||||
delegate()->peerListRefreshRows();
|
||||
|
||||
preloadRows();
|
||||
loadMoreRows();
|
||||
}
|
||||
|
||||
void BoxController::preloadRows() {
|
||||
void BoxController::loadMoreRows() {
|
||||
if (_loadRequestId || _allLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
_loadRequestId = request(MTPmessages_Search(MTP_flags(0), MTP_inputPeerEmpty(), MTP_string(QString()), MTP_inputMessagesFilterPhoneCalls(MTP_flags(0)), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_offsetId), MTP_int(_offsetId ? kFirstPageCount : kPerPageCount))).done([this](const MTPmessages_Messages &result) {
|
||||
_loadRequestId = request(MTPmessages_Search(MTP_flags(0), MTP_inputPeerEmpty(), MTP_string(QString()), MTP_inputUserEmpty(), MTP_inputMessagesFilterPhoneCalls(MTP_flags(0)), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_offsetId), MTP_int(_offsetId ? kFirstPageCount : kPerPageCount))).done([this](const MTPmessages_Messages &result) {
|
||||
_loadRequestId = 0;
|
||||
|
||||
auto handleResult = [this](auto &data) {
|
||||
@@ -240,16 +240,16 @@ void BoxController::preloadRows() {
|
||||
}
|
||||
|
||||
void BoxController::refreshAbout() {
|
||||
view()->setAboutText(view()->fullRowsCount() ? QString() : lang(lng_call_box_about));
|
||||
setDescriptionText(delegate()->peerListFullRowsCount() ? QString() : lang(lng_call_box_about));
|
||||
}
|
||||
|
||||
void BoxController::rowClicked(PeerListBox::Row *row) {
|
||||
auto itemsRow = static_cast<Row*>(row);
|
||||
void BoxController::rowClicked(gsl::not_null<PeerListRow*> row) {
|
||||
auto itemsRow = static_cast<Row*>(row.get());
|
||||
auto itemId = itemsRow->maxItemId();
|
||||
Ui::showPeerHistoryAsync(row->peer()->id, itemId);
|
||||
}
|
||||
|
||||
void BoxController::rowActionClicked(PeerListBox::Row *row) {
|
||||
void BoxController::rowActionClicked(gsl::not_null<PeerListRow*> row) {
|
||||
auto user = row->peer()->asUser();
|
||||
t_assert(user != nullptr);
|
||||
|
||||
@@ -274,7 +274,7 @@ void BoxController::receivedCalls(const QVector<MTPMessage> &result) {
|
||||
}
|
||||
|
||||
refreshAbout();
|
||||
view()->refreshRows();
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
||||
bool BoxController::insertRow(HistoryItem *item, InsertWay way) {
|
||||
@@ -284,24 +284,22 @@ bool BoxController::insertRow(HistoryItem *item, InsertWay way) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
(way == InsertWay::Append) ? view()->appendRow(createRow(item)) : view()->prependRow(createRow(item));
|
||||
view()->reorderRows([](auto &&begin, auto &&end) {
|
||||
std::sort(begin, end, [](auto &a, auto &b) {
|
||||
return static_cast<Row&>(*a).maxItemId() > static_cast<Row&>(*a).maxItemId();
|
||||
});
|
||||
(way == InsertWay::Append) ? delegate()->peerListAppendRow(createRow(item)) : delegate()->peerListPrependRow(createRow(item));
|
||||
delegate()->peerListSortRows([](PeerListRow &a, PeerListRow &b) {
|
||||
return static_cast<Row&>(a).maxItemId() > static_cast<Row&>(b).maxItemId();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
|
||||
auto v = view();
|
||||
if (auto fullRowsCount = v->fullRowsCount()) {
|
||||
auto v = delegate();
|
||||
if (auto fullRowsCount = v->peerListFullRowsCount()) {
|
||||
auto itemId = item->id;
|
||||
auto lastRow = static_cast<Row*>(v->rowAt(fullRowsCount - 1));
|
||||
auto lastRow = static_cast<Row*>(v->peerListRowAt(fullRowsCount - 1).get());
|
||||
if (itemId < lastRow->minItemId()) {
|
||||
return lastRow;
|
||||
}
|
||||
auto firstRow = static_cast<Row*>(v->rowAt(0));
|
||||
auto firstRow = static_cast<Row*>(v->peerListRowAt(0).get());
|
||||
if (itemId > firstRow->maxItemId()) {
|
||||
return firstRow;
|
||||
}
|
||||
@@ -313,18 +311,18 @@ BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
|
||||
auto right = fullRowsCount;
|
||||
while (left + 1 < right) {
|
||||
auto middle = (right + left) / 2;
|
||||
auto middleRow = static_cast<Row*>(v->rowAt(middle));
|
||||
auto middleRow = static_cast<Row*>(v->peerListRowAt(middle).get());
|
||||
if (middleRow->maxItemId() >= itemId) {
|
||||
left = middle;
|
||||
} else {
|
||||
right = middle;
|
||||
}
|
||||
}
|
||||
auto result = static_cast<Row*>(v->rowAt(left));
|
||||
auto result = static_cast<Row*>(v->peerListRowAt(left).get());
|
||||
// Check for rowAt(left)->minItemId > itemId > rowAt(left + 1)->maxItemId.
|
||||
// In that case we sometimes need to return rowAt(left + 1), not rowAt(left).
|
||||
if (result->minItemId() > itemId && left + 1 < fullRowsCount) {
|
||||
auto possibleResult = static_cast<Row*>(v->rowAt(left + 1));
|
||||
auto possibleResult = static_cast<Row*>(v->peerListRowAt(left + 1).get());
|
||||
t_assert(possibleResult->maxItemId() < itemId);
|
||||
if (possibleResult->canAddItem(item)) {
|
||||
return possibleResult;
|
||||
@@ -335,7 +333,7 @@ BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListBox::Row> BoxController::createRow(HistoryItem *item) const {
|
||||
std::unique_ptr<PeerListRow> BoxController::createRow(HistoryItem *item) const {
|
||||
auto row = std::make_unique<Row>(item);
|
||||
return std::move(row);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
namespace Calls {
|
||||
|
||||
class BoxController : public PeerListBox::Controller, private base::Subscriber, private MTP::Sender {
|
||||
class BoxController : public PeerListController, private base::Subscriber, private MTP::Sender {
|
||||
public:
|
||||
void prepare() override;
|
||||
void rowClicked(PeerListBox::Row *row) override;
|
||||
void rowActionClicked(PeerListBox::Row *row) override;
|
||||
void preloadRows() override;
|
||||
void rowClicked(gsl::not_null<PeerListRow*> row) override;
|
||||
void rowActionClicked(gsl::not_null<PeerListRow*> row) override;
|
||||
void loadMoreRows() override;
|
||||
|
||||
private:
|
||||
void receivedCalls(const QVector<MTPMessage> &result);
|
||||
@@ -43,7 +43,7 @@ private:
|
||||
Prepend,
|
||||
};
|
||||
bool insertRow(HistoryItem *item, InsertWay way);
|
||||
std::unique_ptr<PeerListBox::Row> createRow(HistoryItem *item) const;
|
||||
std::unique_ptr<PeerListRow> createRow(HistoryItem *item) const;
|
||||
|
||||
MsgId _offsetId = 0;
|
||||
mtpRequestId _loadRequestId = 0;
|
||||
|
||||
@@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "auth_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/rate_call_box.h"
|
||||
#include "calls/calls_instance.h"
|
||||
@@ -231,7 +231,7 @@ void Call::hangup() {
|
||||
_delegate->callFinished(this);
|
||||
} else {
|
||||
auto missed = (_state == State::Ringing || (_state == State::Waiting && _type == Type::Outgoing));
|
||||
auto declined = (_state == State::WaitingIncoming);
|
||||
auto declined = isIncomingWaiting();
|
||||
auto reason = missed ? MTP_phoneCallDiscardReasonMissed() :
|
||||
declined ? MTP_phoneCallDiscardReasonBusy() : MTP_phoneCallDiscardReasonHangup();
|
||||
finish(FinishType::Ended, reason);
|
||||
@@ -597,7 +597,7 @@ void Call::setState(State state) {
|
||||
break;
|
||||
case State::Ended:
|
||||
_delegate->playSound(Delegate::Sound::Ended);
|
||||
// fallthrough
|
||||
// [[fallthrough]]
|
||||
case State::EndedByOtherDevice:
|
||||
_delegate->callFinished(this);
|
||||
break;
|
||||
|
||||
@@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "messenger.h"
|
||||
#include "auth_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "calls/calls_call.h"
|
||||
#include "calls/calls_panel.h"
|
||||
@@ -195,7 +195,7 @@ void Instance::refreshServerConfig() {
|
||||
auto error = QJsonParseError { 0, QJsonParseError::NoError };
|
||||
auto document = QJsonDocument::fromJson(QByteArray::fromRawData(reinterpret_cast<const char*>(bytes.data()), bytes.size()), &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
LOG(("API Error: Faild to parse call config JSON, error: %1").arg(error.errorString()));
|
||||
LOG(("API Error: Failed to parse call config JSON, error: %1").arg(error.errorString()));
|
||||
return;
|
||||
} else if (!document.isObject()) {
|
||||
LOG(("API Error: Not an object received in call config JSON."));
|
||||
|
||||
@@ -30,7 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/effects/widget_fade_wrap.h"
|
||||
#include "messenger.h"
|
||||
#include "mainwindow.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "auth_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "observer_peer.h"
|
||||
@@ -473,6 +473,7 @@ void Panel::createUserpicCache(ImagePtr image) {
|
||||
if (cRetina()) _userPhoto.setDevicePixelRatio(cRetinaFactor());
|
||||
} else {
|
||||
auto filled = QImage(QSize(st::callWidth, st::callWidth) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
filled.setDevicePixelRatio(cRetinaFactor());
|
||||
{
|
||||
Painter p(&filled);
|
||||
EmptyUserpic(_user->colorIndex(), _user->name).paintSquare(p, 0, 0, st::callWidth, st::callWidth);
|
||||
|
||||
@@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "styles/style_calls.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "calls/calls_call.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "styles/style_boxes.h"
|
||||
@@ -56,8 +56,9 @@ DebugInfoBox::DebugInfoBox(QWidget*, base::weak_unique_ptr<Call> call) : _call(c
|
||||
}
|
||||
|
||||
void DebugInfoBox::prepare() {
|
||||
setTitle("Call Debug");
|
||||
addButton(lang(lng_close), [this] { closeBox(); });
|
||||
setTitle([] { return QString("Call Debug"); });
|
||||
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
_text = setInnerWidget(object_ptr<Ui::FlatLabel>(this, st::callDebugLabel));
|
||||
_text->setSelectable(true);
|
||||
updateText();
|
||||
|
||||
@@ -52,7 +52,7 @@ const style::TextStyle &BotKeyboard::Style::textStyle() const {
|
||||
return st::botKbStyle;
|
||||
}
|
||||
|
||||
void BotKeyboard::Style::repaint(const HistoryItem *item) const {
|
||||
void BotKeyboard::Style::repaint(gsl::not_null<const HistoryItem*> item) const {
|
||||
_parent->update();
|
||||
}
|
||||
|
||||
@@ -237,10 +237,10 @@ void BotKeyboard::updateSelected() {
|
||||
|
||||
if (!_impl) return;
|
||||
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
int x = rtl() ? st::botKbScroll.width : _st->margin;
|
||||
auto p = mapFromGlobal(_lastMousePos);
|
||||
auto x = rtl() ? st::botKbScroll.width : _st->margin;
|
||||
|
||||
auto link = _impl->getState(p.x() - x, p.y() - _st->margin);
|
||||
auto link = _impl->getState(p - QPoint(x, _st->margin));
|
||||
if (ClickHandler::setActive(link, this)) {
|
||||
Ui::Tooltip::Hide();
|
||||
setCursor(link ? style::cur_pointer : style::cur_default);
|
||||
|
||||
@@ -92,7 +92,7 @@ private:
|
||||
|
||||
void startPaint(Painter &p) const override;
|
||||
const style::TextStyle &textStyle() const override;
|
||||
void repaint(const HistoryItem *item) const override;
|
||||
void repaint(gsl::not_null<const HistoryItem*> item) const override;
|
||||
|
||||
protected:
|
||||
void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override;
|
||||
|
||||
@@ -28,6 +28,11 @@ switchPmButton: RoundButton(defaultBoxButton) {
|
||||
height: 34px;
|
||||
textTop: 7px;
|
||||
}
|
||||
stickersRestrictedLabel: FlatLabel(defaultFlatLabel) {
|
||||
width: 320px;
|
||||
align: align(center);
|
||||
textFg: noContactsColor;
|
||||
}
|
||||
|
||||
stickersTrendingHeader: 45px;
|
||||
stickersTrendingSkip: 15px;
|
||||
@@ -96,8 +101,6 @@ stickersReorderFg: windowSubTextFg;
|
||||
stickersRowDisabledOpacity: 0.4;
|
||||
stickersRowDuration: 200;
|
||||
|
||||
emojiIconFg: checkboxFg;
|
||||
emojiIconFgActive: windowBgActive;
|
||||
stickersSettings: icon {{ "emoji_settings", emojiIconFg }};
|
||||
stickersTrending: icon {{ "emoji_trending", emojiIconFg }};
|
||||
stickersTrendingActive: icon {{ "emoji_trending", emojiIconFgActive }};
|
||||
@@ -219,3 +222,19 @@ gifsSearchCancel: contactsSearchCancel;
|
||||
gifsSearchCancelPosition: point(1px, 1px);
|
||||
gifsSearchIcon: boxFieldSearchIcon;
|
||||
gifsSearchIconPosition: point(6px, 7px);
|
||||
|
||||
emojiSuggestionsDropdown: InnerDropdown(defaultInnerDropdown) {
|
||||
scroll: ScrollArea(defaultSolidScroll) {
|
||||
deltat: 0px;
|
||||
deltab: 0px;
|
||||
round: 1px;
|
||||
width: 8px;
|
||||
deltax: 3px;
|
||||
}
|
||||
scrollMargin: margins(0px, 5px, 0px, 5px);
|
||||
scrollPadding: margins(0px, 3px, 0px, 3px);
|
||||
}
|
||||
emojiSuggestionsMenu: Menu(defaultMenu) {
|
||||
itemPadding: margins(48px, 8px, 17px, 7px);
|
||||
widthMax: 512px;
|
||||
}
|
||||
|
||||
@@ -23,14 +23,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "lang.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
||||
namespace ChatHelpers {
|
||||
namespace {
|
||||
|
||||
constexpr auto kEmojiPanelPerRow = Ui::Emoji::kPanelPerRow;
|
||||
constexpr auto kEmojiPanelRowsPerPage = Ui::Emoji::kPanelRowsPerPage;
|
||||
constexpr auto kSaveRecentEmojiTimeout = 3000;
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -536,41 +535,7 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||
}
|
||||
|
||||
void EmojiListWidget::selectEmoji(EmojiPtr emoji) {
|
||||
auto &recent = Ui::Emoji::GetRecent();
|
||||
auto i = recent.begin(), e = recent.end();
|
||||
for (; i != e; ++i) {
|
||||
if (i->first == emoji) {
|
||||
++i->second;
|
||||
if (i->second > 0x8000) {
|
||||
for (auto j = recent.begin(); j != e; ++j) {
|
||||
if (j->second > 1) {
|
||||
j->second /= 2;
|
||||
} else {
|
||||
j->second = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i != recent.begin(); --i) {
|
||||
if ((i - 1)->second > i->second) {
|
||||
break;
|
||||
}
|
||||
qSwap(*i, *(i - 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == e) {
|
||||
while (recent.size() >= kEmojiPanelPerRow * kEmojiPanelRowsPerPage) recent.pop_back();
|
||||
recent.push_back(qMakePair(emoji, 1));
|
||||
for (i = recent.end() - 1; i != recent.begin(); --i) {
|
||||
if ((i - 1)->second > i->second) {
|
||||
break;
|
||||
}
|
||||
qSwap(*i, *(i - 1));
|
||||
}
|
||||
}
|
||||
emit saveConfigDelayed(kSaveRecentEmojiTimeout);
|
||||
|
||||
Ui::Emoji::AddRecent(emoji);
|
||||
emit selected(emoji);
|
||||
}
|
||||
|
||||
|
||||
40
Telegram/SourceFiles/chat_helpers/emoji_suggestions_helper.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "emoji_suggestions.h"
|
||||
#include "emoji_suggestions_data.h"
|
||||
|
||||
namespace Ui {
|
||||
namespace Emoji {
|
||||
|
||||
inline utf16string QStringToUTF16(const QString &string) {
|
||||
return utf16string(reinterpret_cast<const utf16char*>(string.constData()), string.size());
|
||||
}
|
||||
|
||||
inline QString QStringFromUTF16(utf16string string) {
|
||||
return QString::fromRawData(reinterpret_cast<const QChar*>(string.data()), string.size());
|
||||
}
|
||||
|
||||
constexpr auto kSuggestionMaxLength = internal::kReplacementMaxLength;
|
||||
|
||||
} // namespace Emoji
|
||||
} // namespace Ui
|
||||
587
Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp
Normal file
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
|
||||
#include "chat_helpers/emoji_suggestions_helper.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "ui/widgets/inner_dropdown.h"
|
||||
|
||||
namespace Ui {
|
||||
namespace Emoji {
|
||||
namespace {
|
||||
|
||||
constexpr auto kRowLimit = 5;
|
||||
|
||||
} // namespace
|
||||
|
||||
class SuggestionsWidget::Row {
|
||||
public:
|
||||
Row(gsl::not_null<EmojiPtr> emoji, const QString &label, const QString &replacement);
|
||||
Row(const Row &other) = delete;
|
||||
Row &operator=(const Row &other) = delete;
|
||||
Row(Row &&other) = default;
|
||||
Row &operator=(Row &&other) = default;
|
||||
~Row();
|
||||
|
||||
gsl::not_null<EmojiPtr> emoji() const {
|
||||
return _emoji;
|
||||
}
|
||||
const QString &label() const {
|
||||
return _label;
|
||||
}
|
||||
const QString &replacement() const {
|
||||
return _replacement;
|
||||
}
|
||||
RippleAnimation *ripple() const {
|
||||
return _ripple.get();
|
||||
}
|
||||
void setRipple(std::unique_ptr<RippleAnimation> ripple) {
|
||||
_ripple = std::move(ripple);
|
||||
}
|
||||
void resetRipple() {
|
||||
_ripple.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
gsl::not_null<EmojiPtr> _emoji;
|
||||
QString _label;
|
||||
QString _replacement;
|
||||
std::unique_ptr<RippleAnimation> _ripple;
|
||||
|
||||
};
|
||||
|
||||
SuggestionsWidget::Row::Row(gsl::not_null<EmojiPtr> emoji, const QString &label, const QString &replacement)
|
||||
: _emoji(emoji)
|
||||
, _label(label)
|
||||
, _replacement(replacement) {
|
||||
}
|
||||
|
||||
SuggestionsWidget::Row::~Row() = default;
|
||||
|
||||
SuggestionsWidget::SuggestionsWidget(QWidget *parent, const style::Menu &st) : TWidget(parent)
|
||||
, _st(&st)
|
||||
, _rowHeight(_st->itemPadding.top() + _st->itemFont->height + _st->itemPadding.bottom()) {
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
void SuggestionsWidget::showWithQuery(const QString &query) {
|
||||
if (_query == query) {
|
||||
return;
|
||||
}
|
||||
_query = query;
|
||||
auto rows = getRowsByQuery();
|
||||
if (rows.empty()) {
|
||||
toggleAnimated.notify(false, true);
|
||||
}
|
||||
clearSelection();
|
||||
_rows = std::move(rows);
|
||||
resizeToRows();
|
||||
update();
|
||||
if (!_rows.empty()) {
|
||||
setSelected(0);
|
||||
}
|
||||
if (!_rows.empty()) {
|
||||
toggleAnimated.notify(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SuggestionsWidget::Row> SuggestionsWidget::getRowsByQuery() const {
|
||||
auto result = std::vector<Row>();
|
||||
if (_query.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
auto suggestions = GetSuggestions(QStringToUTF16(_query));
|
||||
if (suggestions.empty()) {
|
||||
return result;
|
||||
}
|
||||
auto count = suggestions.size();
|
||||
auto suggestionsEmoji = std::vector<EmojiPtr>(count, nullptr);
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
suggestionsEmoji[i] = Find(QStringFromUTF16(suggestions[i].emoji()));
|
||||
}
|
||||
auto recents = 0;
|
||||
auto &recent = GetRecent();
|
||||
for (auto &item : recent) {
|
||||
auto emoji = item.first->original();
|
||||
if (!emoji) emoji = item.first;
|
||||
auto it = std::find(suggestionsEmoji.begin(), suggestionsEmoji.end(), emoji);
|
||||
if (it != suggestionsEmoji.end()) {
|
||||
auto index = (it - suggestionsEmoji.begin());
|
||||
if (index >= recents) {
|
||||
if (index > recents) {
|
||||
auto recentEmoji = suggestionsEmoji[index];
|
||||
auto recentSuggestion = suggestions[index];
|
||||
for (auto i = index; i != recents; --i) {
|
||||
suggestionsEmoji[i] = suggestionsEmoji[i - 1];
|
||||
suggestions[i] = suggestions[i - 1];
|
||||
}
|
||||
suggestionsEmoji[recents] = recentEmoji;
|
||||
suggestions[recents] = recentSuggestion;
|
||||
}
|
||||
++recents;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.reserve(kRowLimit);
|
||||
auto index = 0;
|
||||
for (auto &item : suggestions) {
|
||||
if (auto emoji = suggestionsEmoji[index++]) {
|
||||
if (emoji->hasVariants()) {
|
||||
auto it = cEmojiVariants().constFind(emoji->nonColoredId());
|
||||
if (it != cEmojiVariants().cend()) {
|
||||
emoji = emoji->variant(it.value());
|
||||
}
|
||||
}
|
||||
result.emplace_back(emoji, QStringFromUTF16(item.label()), QStringFromUTF16(item.replacement()));
|
||||
if (result.size() == kRowLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SuggestionsWidget::resizeToRows() {
|
||||
auto newWidth = 0;
|
||||
for (auto &row : _rows) {
|
||||
accumulate_max(newWidth, countWidth(row));
|
||||
}
|
||||
newWidth = snap(newWidth, _st->widthMin, _st->widthMax);
|
||||
auto newHeight = _st->skip + (_rows.size() * _rowHeight) + _st->skip;
|
||||
resize(newWidth, newHeight);
|
||||
}
|
||||
|
||||
int SuggestionsWidget::countWidth(const Row &row) {
|
||||
auto textw = _st->itemFont->width(row.label());
|
||||
return _st->itemPadding.left() + textw + _st->itemPadding.right();
|
||||
}
|
||||
|
||||
void SuggestionsWidget::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
auto ms = getms();
|
||||
auto clip = e->rect();
|
||||
|
||||
auto topskip = QRect(0, 0, width(), _st->skip);
|
||||
auto bottomskip = QRect(0, height() - _st->skip, width(), _st->skip);
|
||||
if (clip.intersects(topskip)) p.fillRect(clip.intersected(topskip), _st->itemBg);
|
||||
if (clip.intersects(bottomskip)) p.fillRect(clip.intersected(bottomskip), _st->itemBg);
|
||||
|
||||
auto top = _st->skip;
|
||||
p.setFont(_st->itemFont);
|
||||
auto from = floorclamp(clip.top() - top, _rowHeight, 0, _rows.size());
|
||||
auto to = ceilclamp(clip.top() + clip.height() - top, _rowHeight, 0, _rows.size());
|
||||
p.translate(0, top + from * _rowHeight);
|
||||
for (auto i = from; i != to; ++i) {
|
||||
auto &row = _rows[i];
|
||||
auto selected = (i == _selected || i == _pressed);
|
||||
p.fillRect(0, 0, width(), _rowHeight, selected ? _st->itemBgOver : _st->itemBg);
|
||||
if (auto ripple = row.ripple()) {
|
||||
ripple->paint(p, 0, 0, width(), ms);
|
||||
if (ripple->empty()) {
|
||||
row.resetRipple();
|
||||
}
|
||||
}
|
||||
auto emoji = row.emoji();
|
||||
auto esize = Ui::Emoji::Size(Ui::Emoji::Index() + 1);
|
||||
p.drawPixmapLeft((_st->itemPadding.left() - (esize / cIntRetinaFactor())) / 2, (_rowHeight - (esize / cIntRetinaFactor())) / 2, width(), App::emojiLarge(), QRect(emoji->x() * esize, emoji->y() * esize, esize, esize));
|
||||
p.setPen(selected ? _st->itemFgOver : _st->itemFg);
|
||||
p.drawTextLeft(_st->itemPadding.left(), _st->itemPadding.top(), width(), row.label());
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::keyPressEvent(QKeyEvent *e) {
|
||||
handleKeyEvent(e->key());
|
||||
}
|
||||
|
||||
void SuggestionsWidget::handleKeyEvent(int key) {
|
||||
if (key == Qt::Key_Enter || key == Qt::Key_Return || key == Qt::Key_Tab) {
|
||||
if (_selected >= 0 && _selected < _rows.size()) {
|
||||
triggered.notify(_rows[_selected].replacement(), true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((key != Qt::Key_Up && key != Qt::Key_Down) || _rows.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto delta = (key == Qt::Key_Down ? 1 : -1), start = _selected;
|
||||
if (start < 0 || start >= _rows.size()) {
|
||||
start = (delta > 0) ? (_rows.size() - 1) : 0;
|
||||
}
|
||||
auto newSelected = start + delta;
|
||||
if (newSelected < 0) {
|
||||
newSelected += _rows.size();
|
||||
} else if (newSelected >= _rows.size()) {
|
||||
newSelected -= _rows.size();
|
||||
}
|
||||
|
||||
_mouseSelection = false;
|
||||
setSelected(newSelected);
|
||||
}
|
||||
|
||||
void SuggestionsWidget::setSelected(int selected) {
|
||||
if (selected >= _rows.size()) {
|
||||
selected = -1;
|
||||
}
|
||||
if (_selected != selected) {
|
||||
updateSelectedItem();
|
||||
_selected = selected;
|
||||
updateSelectedItem();
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::setPressed(int pressed) {
|
||||
if (pressed >= _rows.size()) {
|
||||
pressed = -1;
|
||||
}
|
||||
if (_pressed != pressed) {
|
||||
_pressed = pressed;
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::clearMouseSelection() {
|
||||
if (_mouseSelection) {
|
||||
clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::clearSelection() {
|
||||
_mouseSelection = false;
|
||||
setSelected(-1);
|
||||
}
|
||||
|
||||
int SuggestionsWidget::itemTop(int index) {
|
||||
if (index > _rows.size()) {
|
||||
index = _rows.size();
|
||||
}
|
||||
return _st->skip + (_rowHeight * index);
|
||||
}
|
||||
|
||||
void SuggestionsWidget::updateItem(int index) {
|
||||
if (index >= 0 && index < _rows.size()) {
|
||||
update(0, itemTop(index), width(), _rowHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::updateSelectedItem() {
|
||||
updateItem(_selected);
|
||||
}
|
||||
|
||||
void SuggestionsWidget::mouseMoveEvent(QMouseEvent *e) {
|
||||
auto inner = rect().marginsRemoved(QMargins(0, _st->skip, 0, _st->skip));
|
||||
auto localPosition = e->pos();
|
||||
if (inner.contains(localPosition)) {
|
||||
_mouseSelection = true;
|
||||
updateSelection(e->globalPos());
|
||||
} else {
|
||||
clearMouseSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::updateSelection(QPoint globalPosition) {
|
||||
if (!_mouseSelection) return;
|
||||
|
||||
auto p = mapFromGlobal(globalPosition) - QPoint(0, _st->skip);
|
||||
auto selected = (p.y() >= 0) ? (p.y() / _rowHeight) : -1;
|
||||
setSelected((selected >= 0 && selected < _rows.size()) ? selected : -1);
|
||||
}
|
||||
void SuggestionsWidget::mousePressEvent(QMouseEvent *e) {
|
||||
if (!_mouseSelection) {
|
||||
return;
|
||||
}
|
||||
if (_selected >= 0 && _selected < _rows.size()) {
|
||||
setPressed(_selected);
|
||||
if (!_rows[_pressed].ripple()) {
|
||||
auto mask = RippleAnimation::rectMask(QSize(width(), _rowHeight));
|
||||
_rows[_pressed].setRipple(std::make_unique<RippleAnimation>(_st->ripple, std::move(mask), [this, selected = _pressed] {
|
||||
updateItem(selected);
|
||||
}));
|
||||
}
|
||||
_rows[_pressed].ripple()->add(mapFromGlobal(QCursor::pos()) - QPoint(0, itemTop(_pressed)));
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (_pressed >= 0 && _pressed < _rows.size()) {
|
||||
auto pressed = _pressed;
|
||||
setPressed(-1);
|
||||
if (_rows[pressed].ripple()) {
|
||||
_rows[pressed].ripple()->lastStop();
|
||||
}
|
||||
if (pressed == _selected) {
|
||||
triggered.notify(_rows[_selected].replacement(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsWidget::enterEventHook(QEvent *e) {
|
||||
auto mouse = QCursor::pos();
|
||||
if (!rect().marginsRemoved(QMargins(0, _st->skip, 0, _st->skip)).contains(mapFromGlobal(mouse))) {
|
||||
clearMouseSelection();
|
||||
}
|
||||
return TWidget::enterEventHook(e);
|
||||
}
|
||||
|
||||
void SuggestionsWidget::leaveEventHook(QEvent *e) {
|
||||
clearMouseSelection();
|
||||
return TWidget::leaveEventHook(e);
|
||||
}
|
||||
|
||||
SuggestionsController::SuggestionsController(QWidget *parent, gsl::not_null<QTextEdit*> field) : QObject(nullptr)
|
||||
, _field(field)
|
||||
, _container(parent, st::emojiSuggestionsDropdown)
|
||||
, _suggestions(_container->setOwnedWidget(object_ptr<Ui::Emoji::SuggestionsWidget>(parent, st::emojiSuggestionsMenu))) {
|
||||
_container->setAutoHiding(false);
|
||||
|
||||
_field->installEventFilter(this);
|
||||
connect(_field, &QTextEdit::textChanged, this, [this] { handleTextChange(); });
|
||||
connect(_field, &QTextEdit::cursorPositionChanged, this, [this] { handleCursorPositionChange(); });
|
||||
|
||||
subscribe(_suggestions->toggleAnimated, [this](bool visible) { suggestionsUpdated(visible); });
|
||||
subscribe(_suggestions->triggered, [this](QString replacement) { replaceCurrent(replacement); });
|
||||
updateForceHidden();
|
||||
|
||||
handleTextChange();
|
||||
}
|
||||
|
||||
void SuggestionsController::handleTextChange() {
|
||||
_ignoreCursorPositionChange = true;
|
||||
InvokeQueued(this, [this] { _ignoreCursorPositionChange = false; });
|
||||
|
||||
auto query = getEmojiQuery();
|
||||
if (query.isEmpty() || _textChangeAfterKeyPress) {
|
||||
_suggestions->showWithQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
QString SuggestionsController::getEmojiQuery() {
|
||||
if (!cReplaceEmojis()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
auto cursor = _field->textCursor();
|
||||
auto position = _field->textCursor().position();
|
||||
if (cursor.anchor() != position) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
auto findTextPart = [this, &position] {
|
||||
auto document = _field->document();
|
||||
auto block = document->findBlock(position);
|
||||
for (auto i = block.begin(); !i.atEnd(); ++i) {
|
||||
auto fragment = i.fragment();
|
||||
if (!fragment.isValid()) continue;
|
||||
|
||||
auto from = fragment.position();
|
||||
auto till = from + fragment.length();
|
||||
if (from >= position || till < position) {
|
||||
continue;
|
||||
}
|
||||
if (fragment.charFormat().isImageFormat()) {
|
||||
continue;
|
||||
}
|
||||
position -= from;
|
||||
_queryStartPosition = from;
|
||||
return fragment.text();
|
||||
}
|
||||
return QString();
|
||||
};
|
||||
|
||||
auto text = findTextPart();
|
||||
if (text.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
auto isSuggestionChar = [](QChar ch) {
|
||||
return (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_') || (ch == '-') || (ch == '+');
|
||||
};
|
||||
auto isGoodCharBeforeSuggestion = [isSuggestionChar](QChar ch) {
|
||||
return !isSuggestionChar(ch) || (ch == 0);
|
||||
};
|
||||
t_assert(position > 0 && position <= text.size());
|
||||
for (auto i = position; i != 0;) {
|
||||
auto ch = text[--i];
|
||||
if (ch == ':') {
|
||||
auto beforeColon = (i < 1) ? QChar(0) : text[i - 1];
|
||||
if (isGoodCharBeforeSuggestion(beforeColon)) {
|
||||
// At least one letter after colon.
|
||||
if (position > i + 1) {
|
||||
// Skip colon and the first letter.
|
||||
_queryStartPosition += i + 2;
|
||||
return text.mid(i, position - i);
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
if (position - i > kSuggestionMaxLength) {
|
||||
return QString();
|
||||
}
|
||||
if (!isSuggestionChar(ch)) {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void SuggestionsController::replaceCurrent(const QString &replacement) {
|
||||
auto cursor = _field->textCursor();
|
||||
auto suggestion = getEmojiQuery();
|
||||
if (suggestion.isEmpty()) {
|
||||
_suggestions->showWithQuery(QString());
|
||||
} else {
|
||||
cursor.setPosition(cursor.position() - suggestion.size(), QTextCursor::KeepAnchor);
|
||||
cursor.insertText(replacement + ' ');
|
||||
}
|
||||
|
||||
auto emojiText = GetSuggestionEmoji(QStringToUTF16(replacement));
|
||||
if (auto emoji = Find(QStringFromUTF16(emojiText))) {
|
||||
if (emoji->hasVariants()) {
|
||||
auto it = cEmojiVariants().constFind(emoji->nonColoredId());
|
||||
if (it != cEmojiVariants().cend()) {
|
||||
emoji = emoji->variant(it.value());
|
||||
}
|
||||
}
|
||||
AddRecent(emoji);
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsController::handleCursorPositionChange() {
|
||||
InvokeQueued(this, [this] {
|
||||
if (_ignoreCursorPositionChange) {
|
||||
return;
|
||||
}
|
||||
_suggestions->showWithQuery(QString());
|
||||
});
|
||||
}
|
||||
|
||||
void SuggestionsController::suggestionsUpdated(bool visible) {
|
||||
_shown = visible;
|
||||
if (_shown) {
|
||||
_container->resizeToContent();
|
||||
updateGeometry();
|
||||
if (!_forceHidden) {
|
||||
_container->showAnimated(Ui::PanelAnimation::Origin::BottomLeft);
|
||||
}
|
||||
} else if (!_forceHidden) {
|
||||
_container->hideAnimated();
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsController::updateGeometry() {
|
||||
auto cursor = _field->textCursor();
|
||||
cursor.setPosition(_queryStartPosition);
|
||||
auto aroundRect = _field->cursorRect(cursor);
|
||||
aroundRect.setTopLeft(_field->viewport()->mapToGlobal(aroundRect.topLeft()));
|
||||
aroundRect.setTopLeft(_container->parentWidget()->mapFromGlobal(aroundRect.topLeft()));
|
||||
auto boundingRect = _container->parentWidget()->rect();
|
||||
auto origin = rtl() ? PanelAnimation::Origin::BottomRight : PanelAnimation::Origin::BottomLeft;
|
||||
auto point = rtl() ? (aroundRect.topLeft() + QPoint(aroundRect.width(), 0)) : aroundRect.topLeft();
|
||||
point -= rtl() ? QPoint(_container->width() - st::emojiSuggestionsDropdown.padding.right(), _container->height()) : QPoint(st::emojiSuggestionsDropdown.padding.left(), _container->height());
|
||||
if (rtl()) {
|
||||
if (point.x() < boundingRect.x()) {
|
||||
point.setX(boundingRect.x());
|
||||
}
|
||||
if (point.x() + _container->width() > boundingRect.x() + boundingRect.width()) {
|
||||
point.setX(boundingRect.x() + boundingRect.width() - _container->width());
|
||||
}
|
||||
} else {
|
||||
if (point.x() + _container->width() > boundingRect.x() + boundingRect.width()) {
|
||||
point.setX(boundingRect.x() + boundingRect.width() - _container->width());
|
||||
}
|
||||
if (point.x() < boundingRect.x()) {
|
||||
point.setX(boundingRect.x());
|
||||
}
|
||||
}
|
||||
if (point.y() < boundingRect.y()) {
|
||||
point.setY(aroundRect.y() + aroundRect.height());
|
||||
origin = (origin == PanelAnimation::Origin::BottomRight) ? PanelAnimation::Origin::TopRight : PanelAnimation::Origin::TopLeft;
|
||||
}
|
||||
_container->move(point);
|
||||
}
|
||||
|
||||
void SuggestionsController::updateForceHidden() {
|
||||
_forceHidden = !_field->isVisible();
|
||||
if (_forceHidden) {
|
||||
_container->hideFast();
|
||||
} else if (_shown) {
|
||||
_container->showFast();
|
||||
}
|
||||
}
|
||||
|
||||
bool SuggestionsController::eventFilter(QObject *object, QEvent *event) {
|
||||
if (object == _field) {
|
||||
auto type = event->type();
|
||||
switch (type) {
|
||||
case QEvent::Move:
|
||||
case QEvent::Resize: {
|
||||
if (_shown) {
|
||||
updateGeometry();
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::Show:
|
||||
case QEvent::ShowToParent:
|
||||
case QEvent::Hide:
|
||||
case QEvent::HideToParent: {
|
||||
updateForceHidden();
|
||||
} break;
|
||||
|
||||
case QEvent::KeyPress: {
|
||||
auto key = static_cast<QKeyEvent*>(event)->key();
|
||||
switch (key) {
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
if (_shown && !_forceHidden) {
|
||||
_suggestions->handleKeyEvent(key);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Escape:
|
||||
if (_shown && !_forceHidden) {
|
||||
_suggestions->showWithQuery(QString());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
_textChangeAfterKeyPress = true;
|
||||
InvokeQueued(this, [this] { _textChangeAfterKeyPress = false; });
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
|
||||
void SuggestionsController::raise() {
|
||||
_container->raise();
|
||||
}
|
||||
|
||||
} // namespace Emoji
|
||||
} // namespace Ui
|
||||
108
Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/effects/panel_animation.h"
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class InnerDropdown;
|
||||
class FlatTextarea;
|
||||
|
||||
namespace Emoji {
|
||||
|
||||
class SuggestionsWidget : public TWidget {
|
||||
public:
|
||||
SuggestionsWidget(QWidget *parent, const style::Menu &st);
|
||||
|
||||
void showWithQuery(const QString &query);
|
||||
void handleKeyEvent(int key);
|
||||
|
||||
base::Observable<bool> toggleAnimated;
|
||||
base::Observable<QString> triggered;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void enterEventHook(QEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
|
||||
private:
|
||||
class Row;
|
||||
|
||||
std::vector<Row> getRowsByQuery() const;
|
||||
void resizeToRows();
|
||||
int countWidth(const Row &row);
|
||||
void setSelected(int selected);
|
||||
void setPressed(int pressed);
|
||||
void clearMouseSelection();
|
||||
void clearSelection();
|
||||
void updateSelectedItem();
|
||||
int itemTop(int index);
|
||||
void updateItem(int index);
|
||||
void updateSelection(QPoint globalPosition);
|
||||
|
||||
gsl::not_null<const style::Menu*> _st;
|
||||
|
||||
QString _query;
|
||||
std::vector<Row> _rows;
|
||||
|
||||
int _rowHeight = 0;
|
||||
bool _mouseSelection = false;
|
||||
int _selected = -1;
|
||||
int _pressed = -1;
|
||||
|
||||
};
|
||||
|
||||
class SuggestionsController : public QObject, private base::Subscriber {
|
||||
public:
|
||||
SuggestionsController(QWidget *parent, gsl::not_null<QTextEdit*> field);
|
||||
|
||||
void raise();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
private:
|
||||
void handleCursorPositionChange();
|
||||
void handleTextChange();
|
||||
QString getEmojiQuery();
|
||||
void suggestionsUpdated(bool visible);
|
||||
void updateGeometry();
|
||||
void updateForceHidden();
|
||||
void replaceCurrent(const QString &replacement);
|
||||
|
||||
bool _shown = false;
|
||||
bool _forceHidden = false;
|
||||
int _queryStartPosition = 0;
|
||||
bool _ignoreCursorPositionChange = false;
|
||||
bool _textChangeAfterKeyPress = false;
|
||||
QPointer<QTextEdit> _field;
|
||||
object_ptr<InnerDropdown> _container;
|
||||
QPointer<SuggestionsWidget> _suggestions;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Emoji
|
||||
} // namespace Ui
|
||||
@@ -99,7 +99,7 @@ void FieldAutocomplete::showFiltered(PeerData *peer, QString query, bool addInli
|
||||
bool resetScroll = (_type != type || _filter != plainQuery);
|
||||
if (resetScroll) {
|
||||
_type = type;
|
||||
_filter = textAccentFold(plainQuery.toString());
|
||||
_filter = TextUtilities::RemoveAccents(plainQuery.toString());
|
||||
}
|
||||
_addInlineBots = addInlineBots;
|
||||
|
||||
|
||||