Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e922e5be39 | ||
|
|
296c800b39 | ||
|
|
c39bf239ea | ||
|
|
2ab3cda743 | ||
|
|
a627ed0929 | ||
|
|
8b503d4930 | ||
|
|
6e833baf91 | ||
|
|
3dbe187f56 | ||
|
|
e569b8c5f9 | ||
|
|
2becd307df | ||
|
|
3c18532612 | ||
|
|
2f85997c9f | ||
|
|
e8ead2974b | ||
|
|
bb7730eee1 | ||
|
|
0518a456f8 | ||
|
|
8e3274cd8f | ||
|
|
cce99a96ac | ||
|
|
b84abbec08 | ||
|
|
be87118778 | ||
|
|
27a4d0f029 | ||
|
|
b842761ea3 | ||
|
|
60f45ab9b3 | ||
|
|
5f0741a0a5 | ||
|
|
ed4b9bc40b | ||
|
|
51a6ec0952 | ||
|
|
686abd63b5 | ||
|
|
da2191e9d5 | ||
|
|
33d2ec0f54 | ||
|
|
6df0591e82 | ||
|
|
d1b9b8e3a3 | ||
|
|
b21f72fef0 | ||
|
|
697fdd4294 | ||
|
|
4964b8b488 | ||
|
|
6ae68b337d | ||
|
|
28899a642b | ||
|
|
4518e94c8a | ||
|
|
59b0b0659a |
4
.github/CONTRIBUTING.md
vendored
@@ -118,7 +118,7 @@ If you already have multiple commits, you can add the commits together (squash t
|
||||
1. Open `Git Bash` (or `Git Shell`)
|
||||
2. Enter following command to squash the recent {N} commits: `git reset --soft HEAD~{N} && git commit` (replace `{N}` with the number of commits you want to squash)
|
||||
3. Press <kbd>i</kbd> to get into Insert-mode
|
||||
4. Enter the commit message of the new commit (and add the [signature](#sign-your-work) at the and)
|
||||
4. Enter the commit message of the new commit (and add the [signature](#sign-your-work) at the end)
|
||||
5. After adding the message, press <kbd>ESC</kbd> to get out of the Insert-mode
|
||||
6. Write `:wq` and press <kbd>Enter</kbd> to save the new message or write `:q!` to discard your changes
|
||||
7. Enter `git push --force` to push the new commit to the remote repository
|
||||
@@ -154,4 +154,4 @@ Don't forget to [sign your patch](#sign-your-work) to put it in the public domai
|
||||
[help_change_commit_message]: https://help.github.com/articles/changing-a-commit-message/
|
||||
[commit_message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[pr]: https://github.com/telegramdesktop/tdesktop/compare
|
||||
[build_instructions]: https://github.com/telegramdesktop/tdesktop/blob/master/README.md#build-instructions
|
||||
[build_instructions]: https://github.com/telegramdesktop/tdesktop/blob/master/README.md#build-instructions
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This is the complete source code and the build instructions for the alpha version of the official desktop client for the [Telegram][telegram] messenger, based on the [Telegram API][telegram_api] and the [MTProto][telegram_proto] secure protocol.
|
||||
|
||||
[](https://badge.fury.io/gh/telegramdesktop%2Ftdesktop)
|
||||
[](https://github.com/telegramdesktop/tdesktop/releases)
|
||||
[](https://travis-ci.org/telegramdesktop/tdesktop)
|
||||
|
||||
The source code is published under GPLv3 with OpenSSL exception, the license is available [here][license].
|
||||
|
||||
@@ -24,6 +24,9 @@ TextPalette {
|
||||
linkFg: color;
|
||||
monoFg: color;
|
||||
selectBg: color;
|
||||
selectFg: color;
|
||||
selectLinkFg: color;
|
||||
selectMonoFg: color;
|
||||
selectOverlay: color;
|
||||
}
|
||||
|
||||
@@ -52,6 +55,9 @@ defaultTextPalette: TextPalette {
|
||||
linkFg: windowActiveTextFg;
|
||||
monoFg: windowSubTextFg;
|
||||
selectBg: msgInBgSelected;
|
||||
selectFg: historyTextInFgSelected;
|
||||
selectLinkFg: historyLinkInFgSelected;
|
||||
selectMonoFg: msgInMonoFgSelected;
|
||||
selectOverlay: msgSelectOverlay;
|
||||
}
|
||||
defaultTextStyle: TextStyle {
|
||||
@@ -125,6 +131,9 @@ serviceTextPalette: TextPalette(defaultTextPalette) {
|
||||
linkFg: msgServiceFg;
|
||||
monoFg: msgServiceFg;
|
||||
selectBg: msgServiceBgSelected;
|
||||
selectFg: msgServiceFg;
|
||||
selectLinkFg: msgServiceFg;
|
||||
selectMonoFg: msgServiceFg;
|
||||
selectOverlay: msgServiceBgSelected;
|
||||
}
|
||||
serviceTextStyle: TextStyle(defaultTextStyle) {
|
||||
@@ -133,15 +142,31 @@ serviceTextStyle: TextStyle(defaultTextStyle) {
|
||||
linkFontOver: font(fsize semibold underline);
|
||||
}
|
||||
inTextPalette: TextPalette(defaultTextPalette) {
|
||||
linkFg: historyLinkInFg;
|
||||
monoFg: msgInMonoFg;
|
||||
selectBg: msgInBgSelected;
|
||||
selectFg: historyTextInFgSelected;
|
||||
selectLinkFg: historyLinkInFgSelected;
|
||||
selectMonoFg: msgInMonoFgSelected;
|
||||
selectOverlay: msgSelectOverlay;
|
||||
}
|
||||
inTextPaletteSelected: TextPalette(inTextPalette) {
|
||||
linkFg: historyLinkInFgSelected;
|
||||
monoFg: msgInMonoFgSelected;
|
||||
}
|
||||
outTextPalette: TextPalette(defaultTextPalette) {
|
||||
linkFg: historyLinkOutFg;
|
||||
monoFg: msgOutMonoFg;
|
||||
selectBg: msgOutBgSelected;
|
||||
selectFg: historyTextOutFgSelected;
|
||||
selectLinkFg: historyLinkOutFgSelected;
|
||||
selectMonoFg: msgOutMonoFgSelected;
|
||||
selectOverlay: msgSelectOverlay;
|
||||
}
|
||||
outTextPaletteSelected: TextPalette(outTextPalette) {
|
||||
linkFg: historyLinkOutFgSelected;
|
||||
monoFg: msgOutMonoFgSelected;
|
||||
}
|
||||
fwdTextStyle: TextStyle(semiboldTextStyle) {
|
||||
linkFontOver: semiboldFont;
|
||||
}
|
||||
@@ -268,8 +293,6 @@ toastFadeOutDuration: 1000;
|
||||
|
||||
historyReplyCancelIcon: icon {{ "box_button_close", historyReplyCancelFg }};
|
||||
historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }};
|
||||
boxSearchCancelIcon: icon {{ "box_button_close", boxSearchCancelIconFg }};
|
||||
boxSearchCancelIconOver: icon {{ "box_button_close", boxSearchCancelIconFgOver }};
|
||||
boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }};
|
||||
boxTitleCloseIconOver: icon {{ "box_button_close", boxTitleCloseFgOver }};
|
||||
|
||||
@@ -277,3 +300,5 @@ notifyFadeRight: icon {{ "fade_horizontal", notificationBg }};
|
||||
|
||||
stickerIconLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }};
|
||||
stickerIconRight: icon {{ "fade_horizontal", emojiPanCategories }};
|
||||
|
||||
transparentPlaceholderSize: 4px;
|
||||
|
||||
@@ -21,468 +21,484 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
// basic
|
||||
windowBg: #ffffff; // white: fallback for background
|
||||
windowFg: #000000; // black: fallback for text color
|
||||
windowBgOver: #f1f1f1; // light gray: fallback for over background
|
||||
windowFg: #000000; // black: fallback for text
|
||||
windowBgOver: #f1f1f1; // light gray: fallback for background with mouse over
|
||||
windowBgRipple: #e5e5e5; // darker gray: fallback for ripple effect
|
||||
windowFgOver: windowFg; // black: fallback for over text color
|
||||
windowSubTextFg: #999999; // gray: fallback for subtext color
|
||||
windowSubTextFgOver: #919191; // gray over light blue: fallback for subtext over color
|
||||
windowBoldFg: #222222; // dark gray: fallback for bold text color
|
||||
windowBoldFgOver: #222222; // dark gray: fallback for over bold text color
|
||||
windowFgOver: windowFg; // black: fallback for text with mouse over
|
||||
windowSubTextFg: #999999; // gray: fallback for additional text
|
||||
windowSubTextFgOver: #919191; // darker gray: fallback for additional text with mouse over
|
||||
windowBoldFg: #222222; // dark gray: fallback for bold text
|
||||
windowBoldFgOver: #222222; // dark gray: fallback for bold text with mouse over
|
||||
windowBgActive: #40a7e3; // bright blue: fallback for blue filled active areas
|
||||
windowFgActive: #ffffff; // text on bright blue: fallback for text on active areas
|
||||
windowActiveTextFg: #168acd; // online blue: fallback for active color
|
||||
windowShadowFg: #000000; // black: fallback for shadow color
|
||||
windowFgActive: #ffffff; // white: fallback for text on active areas
|
||||
windowActiveTextFg: #168acd; // online blue: fallback for active text like online status
|
||||
windowShadowFg: #000000; // black: fallback for shadow
|
||||
windowShadowFgFallback: #f1f1f1; // gray: fallback for shadow without opacity
|
||||
|
||||
shadowFg: #00000018;
|
||||
slideFadeOutBg: #0000003c;
|
||||
slideFadeOutShadowFg: windowShadowFg;
|
||||
shadowFg: #00000018; // most shadows (including opacity)
|
||||
slideFadeOutBg: #0000003c; // slide animation (chat to profile) fade out filling
|
||||
slideFadeOutShadowFg: windowShadowFg; // slide animation (chat to profile) fade out right section shadow
|
||||
|
||||
imageBg: #000000;
|
||||
imageBgTransparent: #ffffff;
|
||||
imageBg: #000000; // image background fallback (when photo size is less than minimum allowed)
|
||||
imageBgTransparent: #ffffff; // image background when displaying an image with opacity where no opacity is needed
|
||||
|
||||
// widgets
|
||||
activeButtonBg: windowBgActive;
|
||||
activeButtonBgOver: #39a5db;
|
||||
activeButtonBgRipple: #2095d0;
|
||||
activeButtonFg: windowFgActive;
|
||||
activeButtonFgOver: activeButtonFg;
|
||||
activeButtonSecondaryFg: #cceeff;
|
||||
activeButtonSecondaryFgOver: activeButtonSecondaryFg;
|
||||
activeLineFg: #37a1de;
|
||||
activeLineFgError: #e48383;
|
||||
activeButtonBg: windowBgActive; // default active button background
|
||||
activeButtonBgOver: #39a5db; // default active button background with mouse over
|
||||
activeButtonBgRipple: #2095d0; // default active button ripple effect
|
||||
activeButtonFg: windowFgActive; // default active button text
|
||||
activeButtonFgOver: activeButtonFg; // default active button text with mouse over
|
||||
activeButtonSecondaryFg: #cceeff; // default active button additional text (selected messages counter in forward / delete buttons)
|
||||
activeButtonSecondaryFgOver: activeButtonSecondaryFg; // default active button additional text with mouse over
|
||||
activeLineFg: #37a1de; // default active line (like code input field bottom border when you log in and field is focused)
|
||||
activeLineFgError: #e48383; // default active line for error state (like code input field bottom border when you log in and you've entered incorrect code)
|
||||
|
||||
lightButtonBg: windowBg;
|
||||
lightButtonBgOver: #e3f1fa;
|
||||
lightButtonBgRipple: #c9e4f6;
|
||||
lightButtonFg: windowActiveTextFg;
|
||||
lightButtonFgOver: lightButtonFg;
|
||||
lightButtonBg: windowBg; // default light button background (like buttons in boxes)
|
||||
lightButtonBgOver: #e3f1fa; // default light button background with mouse over
|
||||
lightButtonBgRipple: #c9e4f6; // default light button ripple effect
|
||||
lightButtonFg: windowActiveTextFg; // default light button text
|
||||
lightButtonFgOver: lightButtonFg; // default light button text with mouse over
|
||||
|
||||
attentionButtonFg: #d14e4e;
|
||||
attentionButtonFgOver: #d14e4e;
|
||||
attentionButtonBgOver: #fcdfde;
|
||||
attentionButtonBgRipple: #f4c3c2;
|
||||
attentionButtonFg: #d14e4e; // default attention button text (like confirm button on log out)
|
||||
attentionButtonFgOver: #d14e4e; // default attention button text with mouse over
|
||||
attentionButtonBgOver: #fcdfde; // default attention button background with mouse over
|
||||
attentionButtonBgRipple: #f4c3c2; // default attention button ripple effect
|
||||
|
||||
outlineButtonBg: windowBg;
|
||||
outlineButtonBgOver: lightButtonBgOver;
|
||||
outlineButtonOutlineFg: windowBgActive;
|
||||
outlineButtonBgRipple: lightButtonBgRipple;
|
||||
outlineButtonBg: windowBg; // default left outlined button background (like shared media links in profiles)
|
||||
outlineButtonBgOver: lightButtonBgOver; // default left outlined button background with mouse over
|
||||
outlineButtonOutlineFg: windowBgActive; // default left outlined button left outline border
|
||||
outlineButtonBgRipple: lightButtonBgRipple; // default left outlined button ripple effect
|
||||
|
||||
menuBg: windowBg;
|
||||
menuBgOver: windowBgOver;
|
||||
menuBgRipple: windowBgRipple;
|
||||
menuIconFg: #a8a8a8;
|
||||
menuIconFgOver: #999999;
|
||||
menuSubmenuArrowFg: #373737;
|
||||
menuFgDisabled: #cccccc;
|
||||
menuSeparatorFg: #f1f1f1;
|
||||
menuBg: windowBg; // default popup menu background
|
||||
menuBgOver: windowBgOver; // default popup menu item background with mouse over
|
||||
menuBgRipple: windowBgRipple; // default popup menu item ripple effect
|
||||
menuIconFg: #a8a8a8; // default popup menu item icon (like main menu)
|
||||
menuIconFgOver: #999999; // default popup menu item icon with mouse over
|
||||
menuSubmenuArrowFg: #373737; // default popup menu submenu arrow icon (like in message field context menu in case of RTL system language)
|
||||
menuFgDisabled: #cccccc; // default popup menu item disabled text (like unavailable items in message field context menu)
|
||||
menuSeparatorFg: #f1f1f1; // default popup menu separator (like in message field context menu)
|
||||
|
||||
scrollBarBg: #00000053;
|
||||
scrollBarBgOver: #0000007a;
|
||||
scrollBg: #0000001a;
|
||||
scrollBgOver: #0000002c;
|
||||
scrollBarBg: #00000053; // default scroll bar current rectangle, the bar itself (like in chats list)
|
||||
scrollBarBgOver: #0000007a; // default scroll bar current rectangle with mouse over it
|
||||
scrollBg: #0000001a; // default scroll bar background
|
||||
scrollBgOver: #0000002c; // default scroll bar background with mouse over the scroll bar
|
||||
|
||||
smallCloseIconFg: #c7c7c7;
|
||||
smallCloseIconFgOver: #a3a3a3;
|
||||
smallCloseIconFg: #c7c7c7; // small X icon (like in Show all sessions box to the right for sessions termination)
|
||||
smallCloseIconFgOver: #a3a3a3; // small X icon with mouse over
|
||||
|
||||
radialFg: windowFgActive;
|
||||
radialBg: #00000056;
|
||||
radialFg: windowFgActive; // default radial loader line (like in Media Viewer when loading a photo)
|
||||
radialBg: #00000056; // default radial loader background (like in Media Viewer when loading a photo)
|
||||
|
||||
placeholderFg: windowSubTextFg;
|
||||
placeholderFgActive: #aaaaaa;
|
||||
inputBorderFg: #e0e0e0;
|
||||
filterInputBorderFg: #54c3f3;
|
||||
filterInputInactiveBg: windowBgOver;
|
||||
checkboxFg: #b3b3b3;
|
||||
placeholderFg: windowSubTextFg; // default input field placeholder when field is not focused (like in phone input field when you log in)
|
||||
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)
|
||||
|
||||
sliderBgInactive: #e1eaef;
|
||||
sliderBgActive: windowBgActive;
|
||||
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)
|
||||
|
||||
tooltipBg: #eef2f5;
|
||||
tooltipFg: #5d6c80;
|
||||
tooltipBorderFg: #c9d1db;
|
||||
tooltipBg: #eef2f5; // tooltip background (like when you put mouse over the message timestamp and wait)
|
||||
tooltipFg: #5d6c80; // tooltip text
|
||||
tooltipBorderFg: #c9d1db; // tooltip border
|
||||
|
||||
// custom title bar for Windows and macOS
|
||||
titleShadow: #00000003;
|
||||
titleBg: windowBgOver;
|
||||
titleBgActive: titleBg;
|
||||
titleButtonBg: titleBg;
|
||||
titleButtonFg: #ababab;
|
||||
titleButtonBgOver: #e5e5e5;
|
||||
titleButtonFgOver: #9a9a9a;
|
||||
titleButtonBgActive: titleButtonBg;
|
||||
titleButtonFgActive: titleButtonFg;
|
||||
titleButtonBgActiveOver: titleButtonBgOver;
|
||||
titleButtonFgActiveOver: titleButtonFgOver;
|
||||
titleButtonCloseBg: titleButtonBg;
|
||||
titleButtonCloseFg: titleButtonFg;
|
||||
titleButtonCloseBgOver: #e81123;
|
||||
titleButtonCloseFgOver: windowFgActive;
|
||||
titleButtonCloseBgActive: titleButtonCloseBg;
|
||||
titleButtonCloseFgActive: titleButtonCloseFg;
|
||||
titleButtonCloseBgActiveOver: titleButtonCloseBgOver;
|
||||
titleButtonCloseFgActiveOver: titleButtonCloseFgOver;
|
||||
titleFg: #acacac;
|
||||
titleFgActive: #3e3c3e;
|
||||
titleShadow: #00000003; // one pixel line shadow at the bottom of custom window title
|
||||
titleBg: windowBgOver; // custom window title background when window is inactive
|
||||
titleBgActive: titleBg; // custom window title background when window is active
|
||||
titleButtonBg: titleBg; // custom window title minimize/maximize/restore button background when window is inactive (Windows only)
|
||||
titleButtonFg: #ababab; // custom window title minimize/maximize/restore button icon when window is inactive (Windows only)
|
||||
titleButtonBgOver: #e5e5e5; // custom window title minimize/maximize/restore button background with mouse over when window is inactive (Windows only)
|
||||
titleButtonFgOver: #9a9a9a; // custom window title minimize/maximize/restore button icon with mouse over when window is inactive (Windows only)
|
||||
titleButtonBgActive: titleButtonBg; // custom window title minimize/maximize/restore button background when window is active (Windows only)
|
||||
titleButtonFgActive: titleButtonFg; // custom window title minimize/maximize/restore button icon when window is active (Windows only)
|
||||
titleButtonBgActiveOver: titleButtonBgOver; // custom window title minimize/maximize/restore button background with mouse over when window is active (Windows only)
|
||||
titleButtonFgActiveOver: titleButtonFgOver; // custom window title minimize/maximize/restore button icon with mouse over when window is active (Windows only)
|
||||
titleButtonCloseBg: titleButtonBg; // custom window title close button background when window is inactive (Windows only)
|
||||
titleButtonCloseFg: titleButtonFg; // custom window title close button icon when window is inactive (Windows only)
|
||||
titleButtonCloseBgOver: #e81123; // custom window title close button background with mouse over when window is inactive (Windows only)
|
||||
titleButtonCloseFgOver: windowFgActive; // custom window title close button icon with mouse over when window is inactive (Windows only)
|
||||
titleButtonCloseBgActive: titleButtonCloseBg; // custom window title close button background when window is active (Windows only)
|
||||
titleButtonCloseFgActive: titleButtonCloseFg; // custom window title close button icon when window is active (Windows only)
|
||||
titleButtonCloseBgActiveOver: titleButtonCloseBgOver; // custom window title close button background with mouse over when window is active (Windows only)
|
||||
titleButtonCloseFgActiveOver: titleButtonCloseFgOver; // custom window title close button icon with mouse over when window is active (Windows only)
|
||||
titleFg: #acacac; // custom window title text when window is inactive (macOS only)
|
||||
titleFgActive: #3e3c3e; // custom window title text when window is active (macOS only)
|
||||
|
||||
// tray icon
|
||||
trayCounterBg: #f23c34;
|
||||
trayCounterBgMute: #888888;
|
||||
trayCounterFg: #ffffff;
|
||||
trayCounterBgMacInvert: #ffffff;
|
||||
trayCounterFgMacInvert: #ffffff01;
|
||||
trayCounterBg: #f23c34; // tray icon counter background
|
||||
trayCounterBgMute: #888888; // tray icon counter background if all unread messages are muted
|
||||
trayCounterFg: #ffffff; // tray icon counter text
|
||||
trayCounterBgMacInvert: #ffffff; // tray icon counter background when tray icon is pressed or when dark theme of macOS is used (macOS only)
|
||||
trayCounterFgMacInvert: #ffffff01; // tray icon counter text when tray icon is pressed or when dark theme of macOS is used (macOS only)
|
||||
|
||||
// layers
|
||||
layerBg: #0000007f;
|
||||
layerBg: #0000007f; // box and main menu background layer fade
|
||||
|
||||
cancelIconFg: menuIconFg;
|
||||
cancelIconFgOver: menuIconFgOver;
|
||||
cancelIconFg: menuIconFg; // default for settings close icon and box search cancel icon
|
||||
cancelIconFgOver: menuIconFgOver; // default for settings close icon and box search cancel icon with mouse over
|
||||
|
||||
// boxes
|
||||
boxBg: windowBg;
|
||||
boxTextFg: windowFg;
|
||||
boxTextFgGood: #4ab44a;
|
||||
boxTextFgError: #d84d4d;
|
||||
boxTitleFg: #404040;
|
||||
boxSearchBg: boxBg;
|
||||
boxSearchCancelIconFg: cancelIconFg;
|
||||
boxSearchCancelIconFgOver: cancelIconFgOver;
|
||||
boxBg: windowBg; // box background
|
||||
boxTextFg: windowFg; // box text
|
||||
boxTextFgGood: #4ab44a; // accepted box text (like when choosing username that is not occupied)
|
||||
boxTextFgError: #d84d4d; // rejecting box text (like when choosing username that is occupied)
|
||||
boxTitleFg: #404040; // box title text
|
||||
boxSearchBg: boxBg; // box search field background (like in contacts box)
|
||||
|
||||
boxTitleAdditionalFg: #808080;
|
||||
boxTitleCloseFg: cancelIconFg;
|
||||
boxTitleCloseFgOver: cancelIconFgOver;
|
||||
boxTitleAdditionalFg: #808080; // box title additional text (like in create group box when you see chosen members count)
|
||||
boxTitleCloseFg: cancelIconFg; // settings close icon and box search cancel icon (like in contacts box)
|
||||
boxTitleCloseFgOver: cancelIconFgOver; // settings close icon and box search cancel icon (like in contacts box) with mouse over
|
||||
|
||||
membersAboutLimitFg: windowSubTextFgOver;
|
||||
//boxSearchCancelIconFg: cancelIconFg; // search cancel X button icon (like in contacts box) (not implemented yet)
|
||||
//boxSearchCancelIconFgOver: cancelIconFgOver; // search cancel X button icon with mouse over (not implemented yet)
|
||||
|
||||
contactsBg: windowBg;
|
||||
contactsBgOver: windowBgOver;
|
||||
contactsNameFg: boxTextFg;
|
||||
contactsStatusFg: windowSubTextFg;
|
||||
contactsStatusFgOver: windowSubTextFgOver;
|
||||
contactsStatusFgOnline: windowActiveTextFg;
|
||||
membersAboutLimitFg: windowSubTextFgOver; // text in channel members box about the limit (max 200 last members are shown)
|
||||
|
||||
photoCropFadeBg: layerBg;
|
||||
photoCropPointFg: #ffffff7f;
|
||||
contactsBg: windowBg; // contacts (and some other) box row background
|
||||
contactsBgOver: windowBgOver; // contacts (and some other) box row background with mouse over
|
||||
contactsNameFg: boxTextFg; // contacts (and some other) box row name text
|
||||
contactsStatusFg: windowSubTextFg; // contacts (and some other) box row additional text (like last seen stamp)
|
||||
contactsStatusFgOver: windowSubTextFgOver; // contacts (and some other) box row additional text (like last seen stamp) with mouse over
|
||||
contactsStatusFgOnline: windowActiveTextFg; // contacts (and some other) box row active additional text (like online status)
|
||||
|
||||
photoCropFadeBg: layerBg; // avatar crop box fade background (when choosing a new photo in Settings or for a group)
|
||||
photoCropPointFg: #ffffff7f; // avatar crop box corner rectangles (when choosing a new photo in Settings or for a group)
|
||||
|
||||
// intro
|
||||
introBg: windowBg;
|
||||
introTitleFg: windowBoldFg;
|
||||
introDescriptionFg: windowSubTextFg;
|
||||
introErrorFg: windowSubTextFg;
|
||||
introBg: windowBg; // login background
|
||||
introTitleFg: windowBoldFg; // login title text
|
||||
introDescriptionFg: windowSubTextFg; // login description text
|
||||
introErrorFg: windowSubTextFg; // login error text (like when providing a wrong log in code)
|
||||
|
||||
introCoverTopBg: #0f89d0;
|
||||
introCoverBottomBg: #39b0f0;
|
||||
introCoverIconsFg: #5ec6ff;
|
||||
introCoverPlaneTrace: #5ec6ff69;
|
||||
introCoverPlaneInner: #c6d8e8;
|
||||
introCoverPlaneOuter: #a1bed4;
|
||||
introCoverPlaneTop: #ffffff;
|
||||
introCoverTopBg: #0f89d0; // intro gradient top (from)
|
||||
introCoverBottomBg: #39b0f0; // intro gradient bottom (to)
|
||||
introCoverIconsFg: #5ec6ff; // intro cloud graphics
|
||||
introCoverPlaneTrace: #5ec6ff69; // intro plane traces
|
||||
introCoverPlaneInner: #c6d8e8; // intro plane part
|
||||
introCoverPlaneOuter: #a1bed4; // intro plane part
|
||||
introCoverPlaneTop: #ffffff; // intro plane part
|
||||
|
||||
// dialogs
|
||||
dialogsMenuIconFg: menuIconFg;
|
||||
dialogsMenuIconFgOver: menuIconFgOver;
|
||||
dialogsMenuIconFg: menuIconFg; // main menu and lock telegram icon
|
||||
dialogsMenuIconFgOver: menuIconFgOver; // main menu and lock telegram icon with mouse over
|
||||
|
||||
dialogsBg: windowBg;
|
||||
dialogsNameFg: windowBoldFg;
|
||||
dialogsChatIconFg: dialogsNameFg;
|
||||
dialogsDateFg: windowSubTextFg;
|
||||
dialogsTextFg: windowSubTextFg;
|
||||
dialogsTextFgService: windowActiveTextFg;
|
||||
dialogsDraftFg: #dd4b39;
|
||||
dialogsVerifiedIconBg: windowBgActive;
|
||||
dialogsVerifiedIconFg: windowFgActive;
|
||||
dialogsSendingIconFg: #c1c1c1;
|
||||
dialogsSentIconFg: #5dc452;
|
||||
dialogsUnreadBg: windowBgActive;
|
||||
dialogsUnreadBgMuted: #bbbbbb;
|
||||
dialogsUnreadFg: windowFgActive;
|
||||
dialogsBg: windowBg; // chat list background
|
||||
dialogsNameFg: windowBoldFg; // chat list name text
|
||||
dialogsChatIconFg: dialogsNameFg; // chat list group or channel icon
|
||||
dialogsDateFg: windowSubTextFg; // chat list date text
|
||||
dialogsTextFg: windowSubTextFg; // chat list message text
|
||||
dialogsTextFgService: windowActiveTextFg; // chat list group sender name text (or media message type text)
|
||||
dialogsDraftFg: #dd4b39; // chat list draft label
|
||||
dialogsVerifiedIconBg: windowBgActive; // chat list verified icon background
|
||||
dialogsVerifiedIconFg: windowFgActive; // chat list verified icon check
|
||||
dialogsSendingIconFg: #c1c1c1; // chat list sending message icon (clock)
|
||||
dialogsSentIconFg: #5dc452; // chat list sent message tick / double tick icon
|
||||
dialogsUnreadBg: windowBgActive; // chat list unread badge background for not muted chat
|
||||
dialogsUnreadBgMuted: #bbbbbb; // chat list unread badge background for muted chat
|
||||
dialogsUnreadFg: windowFgActive; // chat list unread badge text
|
||||
|
||||
dialogsBgOver: windowBgOver;
|
||||
dialogsNameFgOver: windowBoldFgOver;
|
||||
dialogsChatIconFgOver: dialogsNameFgOver;
|
||||
dialogsDateFgOver: windowSubTextFgOver;
|
||||
dialogsTextFgOver: windowSubTextFgOver;
|
||||
dialogsTextFgServiceOver: dialogsTextFgService;
|
||||
dialogsDraftFgOver: dialogsDraftFg;
|
||||
dialogsVerifiedIconBgOver: dialogsVerifiedIconBg;
|
||||
dialogsVerifiedIconFgOver: dialogsVerifiedIconFg;
|
||||
dialogsSendingIconFgOver: dialogsSendingIconFg;
|
||||
dialogsSentIconFgOver: dialogsSentIconFg;
|
||||
dialogsUnreadBgOver: dialogsUnreadBg;
|
||||
dialogsUnreadBgMutedOver: dialogsUnreadBgMuted;
|
||||
dialogsUnreadFgOver: dialogsUnreadFg;
|
||||
dialogsBgOver: windowBgOver; // chat list background with mouse over
|
||||
dialogsNameFgOver: windowBoldFgOver; // chat list name text with mouse over
|
||||
dialogsChatIconFgOver: dialogsNameFgOver; // chat list group or channel icon with mouse over
|
||||
dialogsDateFgOver: windowSubTextFgOver; // chat list date text with mouse over
|
||||
dialogsTextFgOver: windowSubTextFgOver; // chat list message text with mouse over
|
||||
dialogsTextFgServiceOver: dialogsTextFgService; // chat list group sender name text with mouse over
|
||||
dialogsDraftFgOver: dialogsDraftFg; // chat list draft label with mouse over
|
||||
dialogsVerifiedIconBgOver: dialogsVerifiedIconBg; // chat list verified icon background with mouse over
|
||||
dialogsVerifiedIconFgOver: dialogsVerifiedIconFg; // chat list verified icon check with mouse over
|
||||
dialogsSendingIconFgOver: dialogsSendingIconFg; // chat list sending message icon (clock) with mouse over
|
||||
dialogsSentIconFgOver: dialogsSentIconFg; // chat list sent message tick / double tick icon with mouse over
|
||||
dialogsUnreadBgOver: dialogsUnreadBg; // chat list unread badge background for not muted chat with mouse over
|
||||
dialogsUnreadBgMutedOver: dialogsUnreadBgMuted; // chat list unread badge background for muted chat with mouse over
|
||||
dialogsUnreadFgOver: dialogsUnreadFg; // chat list unread badge text with mouse over
|
||||
|
||||
dialogsBgActive: #419fd9;
|
||||
dialogsNameFgActive: windowFgActive;
|
||||
dialogsChatIconFgActive: dialogsNameFgActive;
|
||||
dialogsDateFgActive: windowFgActive;
|
||||
dialogsTextFgActive: windowFgActive;
|
||||
dialogsTextFgServiceActive: dialogsTextFgActive;
|
||||
dialogsDraftFgActive: #c6e1f7;
|
||||
dialogsVerifiedIconBgActive: dialogsTextFgActive;
|
||||
dialogsVerifiedIconFgActive: dialogsBgActive;
|
||||
dialogsSendingIconFgActive: #ffffff99;
|
||||
dialogsSentIconFgActive: dialogsTextFgActive;
|
||||
dialogsUnreadBgActive: dialogsTextFgActive;
|
||||
dialogsUnreadBgMutedActive: dialogsDraftFgActive;
|
||||
dialogsUnreadFgActive: dialogsBgActive;
|
||||
dialogsBgActive: #419fd9; // chat list background for current (active) chat
|
||||
dialogsNameFgActive: windowFgActive; // chat list name text for current (active) chat
|
||||
dialogsChatIconFgActive: dialogsNameFgActive; // chat list group or channel icon for current (active) chat
|
||||
dialogsDateFgActive: windowFgActive; // chat list date text for current (active) chat
|
||||
dialogsTextFgActive: windowFgActive; // chat list message text for current (active) chat
|
||||
dialogsTextFgServiceActive: dialogsTextFgActive; // chat list group sender name text for current (active) chat
|
||||
dialogsDraftFgActive: #c6e1f7; // chat list draft label for current (active) chat
|
||||
dialogsVerifiedIconBgActive: dialogsTextFgActive; // chat list verified icon background for current (active) chat
|
||||
dialogsVerifiedIconFgActive: dialogsBgActive; // chat list verified icon check for current (active) chat
|
||||
dialogsSendingIconFgActive: #ffffff99; // chat list sending message icon (clock) for current (active) chat
|
||||
dialogsSentIconFgActive: dialogsTextFgActive; // chat list sent message tick / double tick icon for current (active) chat
|
||||
dialogsUnreadBgActive: dialogsTextFgActive; // chat list unread badge background for not muted chat for current (active) chat
|
||||
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
|
||||
|
||||
dialogsForwardBg: dialogsBgActive;
|
||||
dialogsForwardFg: dialogsNameFgActive;
|
||||
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)
|
||||
|
||||
searchedBarBg: windowBgOver;
|
||||
searchedBarBorder: shadowFg;
|
||||
searchedBarFg: windowSubTextFgOver;
|
||||
searchedBarBg: windowBgOver; // search results bar background (in chats list, contacts box..)
|
||||
searchedBarFg: windowSubTextFgOver; // search results bar text (in chats list, contacts box..)
|
||||
|
||||
// history
|
||||
topBarBg: windowBg;
|
||||
topBarBg: windowBg; // top bar background (in chat view, media overview..)
|
||||
|
||||
emojiPanBg: windowBg;
|
||||
emojiPanCategories: #f7f7f7 | windowBg;
|
||||
emojiPanHeaderFg: windowSubTextFg;
|
||||
emojiPanHeaderBg: #fffffff2 | emojiPanBg;
|
||||
stickerPanDeleteBg: #000000cc;
|
||||
stickerPanDeleteFg: windowFgActive;
|
||||
stickerPreviewBg: #ffffffb0;
|
||||
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
|
||||
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)
|
||||
|
||||
historyTextInFg: windowFg;
|
||||
historyTextOutFg: windowFg;
|
||||
historyCaptionInFg: historyTextInFg;
|
||||
historyCaptionOutFg: historyTextOutFg;
|
||||
historyFileNameInFg: historyTextInFg;
|
||||
historyFileNameOutFg: historyTextOutFg;
|
||||
historyOutIconFg: dialogsSentIconFg;
|
||||
historyOutIconFgSelected: #4da79f;
|
||||
historyIconFgInverted: windowFgActive;
|
||||
historySendingOutIconFg: #98d292;
|
||||
historySendingInIconFg: #a0adb5;
|
||||
historySendingInvertedIconFg: #ffffffc8;
|
||||
historyTextInFg: windowFg; // inbox message text
|
||||
historyTextInFgSelected: historyTextInFg; // inbox message selected text or text in a selected message
|
||||
historyTextOutFg: windowFg; // outbox message text
|
||||
historyTextOutFgSelected: historyTextOutFg; // outbox message selected text or text in a selected message
|
||||
historyLinkInFg: windowActiveTextFg; // inbox message link
|
||||
historyLinkInFgSelected: historyLinkInFg; // inbox message link in a selected text or message
|
||||
historyLinkOutFg: windowActiveTextFg; // outbox message link
|
||||
historyLinkOutFgSelected: historyLinkOutFg; // outbox message link in a selected text or message
|
||||
historyFileNameInFg: historyTextInFg; // inbox media filename text
|
||||
historyFileNameInFgSelected: historyFileNameInFg; // inbox media filename text in a selected message
|
||||
historyFileNameOutFg: historyTextOutFg; // outbox media filename text
|
||||
historyFileNameOutFgSelected: historyFileNameOutFg; // outbox media filename text in a selected message
|
||||
historyOutIconFg: dialogsSentIconFg; // outbox message tick / double tick icon
|
||||
historyOutIconFgSelected: #4da79f; // outbox message tick / double tick icon in a selected message
|
||||
historyIconFgInverted: windowFgActive; // media message tick / double tick icon (like in sent photo)
|
||||
historySendingOutIconFg: #98d292; // outbox sending message icon (clock)
|
||||
historySendingInIconFg: #a0adb5; // inbox sending message icon (clock) (like in sent messages to yourself or in sent messages to a channel)
|
||||
historySendingInvertedIconFg: #ffffffc8; // media sending message icon (clock) (like in sent photo)
|
||||
|
||||
historySystemBg: #89a0b47f;
|
||||
historySystemBgSelected: #bbc8d4a2;
|
||||
historySystemFg: windowFgActive;
|
||||
historyUnreadBarBg: #fcfbfa; // new unread messages bar background
|
||||
historyUnreadBarBorder: shadowFg; // new unread messages bar shadow
|
||||
historyUnreadBarFg: #538bb4; // new unread messages bar text
|
||||
|
||||
historyUnreadBarBg: #fcfbfa;
|
||||
historyUnreadBarBorder: shadowFg;
|
||||
historyUnreadBarFg: #538bb4;
|
||||
historyForwardChooseBg: #0000004c; // forwarding messages in a large window size "choose recipient" background
|
||||
historyForwardChooseFg: windowFgActive; // forwarding messages in a large window size "choose recipient" text
|
||||
|
||||
historyForwardChooseBg: #0000004c;
|
||||
historyForwardChooseFg: windowFgActive;
|
||||
historyPeer1NameFg: #c03d33; // red group member name
|
||||
historyPeer1NameFgSelected: historyPeer1NameFg; // red group member name in a selected message
|
||||
historyPeer1UserpicBg: #e17076; // red userpic background
|
||||
historyPeer2NameFg: #4fad2d; // green group member name
|
||||
historyPeer2NameFgSelected: historyPeer2NameFg; // green group member name in a selected message
|
||||
historyPeer2UserpicBg: #7bc862; // green userpic background
|
||||
historyPeer3NameFg: #d09306; // yellow group member name
|
||||
historyPeer3NameFgSelected: historyPeer3NameFg; // yellow group member name in a selected message
|
||||
historyPeer3UserpicBg: #e5ca77; // yellow userpic background
|
||||
historyPeer4NameFg: windowActiveTextFg; // blue group member name
|
||||
historyPeer4NameFgSelected: historyPeer4NameFg; // blue group member name in a selected message
|
||||
historyPeer4UserpicBg: #65aadd; // blue userpic background
|
||||
historyPeer5NameFg: #8544d6; // purple group member name
|
||||
historyPeer5NameFgSelected: historyPeer5NameFg; // purple group member name in a selected message
|
||||
historyPeer5UserpicBg: #a695e7; // purple userpic background
|
||||
historyPeer6NameFg: #cd4073; // pink group member name
|
||||
historyPeer6NameFgSelected: historyPeer6NameFg; // pink group member name in a selected message
|
||||
historyPeer6UserpicBg: #ee7aae; // pink userpic background
|
||||
historyPeer7NameFg: #2996ad; // sea group member name
|
||||
historyPeer7NameFgSelected: historyPeer7NameFg; // sea group member name in a selected message
|
||||
historyPeer7UserpicBg: #6ec9cb; // sea userpic background
|
||||
historyPeer8NameFg: #ce671b; // orange group member name
|
||||
historyPeer8NameFgSelected: historyPeer8NameFg; // orange group member name in a selected message
|
||||
historyPeer8UserpicBg: #faa774; // orange userpic background
|
||||
historyPeerUserpicFg: windowFgActive; // default userpic initials
|
||||
|
||||
historyPeer1NameFg: #c03d33; // red
|
||||
historyPeer1UserpicBg: #e17076;
|
||||
historyPeer2NameFg: #4fad2d; // green
|
||||
historyPeer2UserpicBg: #7bc862;
|
||||
historyPeer3NameFg: #d09306; // yellow
|
||||
historyPeer3UserpicBg: #e5ca77;
|
||||
historyPeer4NameFg: windowActiveTextFg; // blue
|
||||
historyPeer4UserpicBg: #65aadd;
|
||||
historyPeer5NameFg: #8544d6; // purple
|
||||
historyPeer5UserpicBg: #a695e7;
|
||||
historyPeer6NameFg: #cd4073; // pink
|
||||
historyPeer6UserpicBg: #ee7aae;
|
||||
historyPeer7NameFg: #2996ad; // sea
|
||||
historyPeer7UserpicBg: #6ec9cb;
|
||||
historyPeer8NameFg: #ce671b; // orange
|
||||
historyPeer8UserpicBg: #faa774;
|
||||
historyPeerUserpicFg: windowFgActive;
|
||||
// Some values are marked as (adjusted), it means they're adjusted by
|
||||
// hue and saturation of the average background color if user chooses
|
||||
// some other (not bundled to this color theme) background. If the
|
||||
// bundled background is used those colors are not adjusted in any way.
|
||||
historyScrollBarBg: #517c417a; // scroll bar current rectangle, the bar itself in the chat view (adjusted)
|
||||
historyScrollBarBgOver: #517c41bc; // scroll bar current rectangle with mouse over it in the chat view (adjusted)
|
||||
historyScrollBg: #517c414c; // scroll bar background (adjusted)
|
||||
historyScrollBgOver: #517c416b; // scroll bar background with mouse over the scroll bar (adjusted)
|
||||
|
||||
historyScrollBarBg: #517c417a;
|
||||
historyScrollBarBgOver: #517c41bc;
|
||||
historyScrollBg: #517c414c;
|
||||
historyScrollBgOver: #517c416b;
|
||||
msgInBg: windowBg; // inbox message background
|
||||
msgInBgSelected: #c2dcf2; // inbox selected message background (and background of selected text in those messages)
|
||||
msgOutBg: #effdde; // outbox message background
|
||||
msgOutBgSelected: #b7dbdb; // outbox selected message background (and background of selected text in those messages)
|
||||
msgSelectOverlay: #358cd44c; // overlay which is filling the media parts of selected messages (like in selected photo message)
|
||||
msgStickerOverlay: #358cd47f; // overlay which is filling the selected sticker message
|
||||
msgInServiceFg: windowActiveTextFg; // inbox message information text (like information about a forwarded message original sender)
|
||||
msgInServiceFgSelected: windowActiveTextFg; // inbox selected message information text (like information about a forwarded message original sender)
|
||||
msgOutServiceFg: #3a8e26; // outbox message information text (like information about a forwarded message original sender)
|
||||
msgOutServiceFgSelected: #367570; // outbox message information text (like information about a forwarded message original sender)
|
||||
msgInShadow: #748ea229; // inbox message shadow (below the bubble)
|
||||
msgInShadowSelected: #548dbb29; // inbox selected message shadow (below the bubble)
|
||||
msgOutShadow: #3ac34740; // outbox message shadow (below the bubble)
|
||||
msgOutShadowSelected: #37a78e40; // outbox selected message shadow (below the bubble)
|
||||
msgInDateFg: #a0acb6; // inbox message time text
|
||||
msgInDateFgSelected: #6a9cc5; // inbox selected message time text
|
||||
msgOutDateFg: #6cc264; // outbox message time text
|
||||
msgOutDateFgSelected: #50a79c; // outbox selected message time text
|
||||
msgServiceFg: windowFgActive; // service message text (like date dividers or service message about the group title being changed)
|
||||
msgServiceBg: #517c417f; // service message background (like in a service message about group title being changed) (adjusted)
|
||||
msgServiceBgSelected: #96b38ba2; // service message selected text background (like in a service message about group title being changed) (adjusted)
|
||||
msgInReplyBarColor: activeLineFg; // inbox message reply outline
|
||||
msgInReplyBarSelColor: activeLineFg; // inbox selected message reply outline
|
||||
msgOutReplyBarColor: historyOutIconFg; // outbox message reply outline
|
||||
msgOutReplyBarSelColor: historyOutIconFgSelected; // outbox selected message reply outline
|
||||
msgImgReplyBarColor: msgServiceFg; // sticker message reply outline
|
||||
msgInMonoFg: #4e7391; // inbox message monospace text (like a message sent with `test` text)
|
||||
msgOutMonoFg: #469165; // outbox message monospace text
|
||||
msgInMonoFgSelected: msgInMonoFg; // inbox message monospace text in a selected text or message
|
||||
msgOutMonoFgSelected: msgOutMonoFg; // outbox message monospace text in a selected text or message
|
||||
msgDateImgFg: msgServiceFg; // media message time text (like time text in a sent photo)
|
||||
msgDateImgBg: #00000054; // media message time bubble background (like time bubble in a sent photo) or file with thumbnail download icon circle background
|
||||
msgDateImgBgOver: #00000074; // media message download icon circle background with mouse over (like file with thumbnail download icon)
|
||||
msgDateImgBgSelected: #1c4a7187; // selected media message time bubble background
|
||||
|
||||
msgInBg: windowBg;
|
||||
msgInBgSelected: #c2dcf2; // #358cd4 with 30% opacity
|
||||
msgOutBg: #effdde;
|
||||
msgOutBgSelected: #b7dbdb;
|
||||
msgSelectOverlay: #358cd44c;
|
||||
msgStickerOverlay: #358cd47f;
|
||||
msgInServiceFg: windowActiveTextFg;
|
||||
msgInServiceFgSelected: windowActiveTextFg;
|
||||
msgOutServiceFg: #3a8e26;
|
||||
msgOutServiceFgSelected: #367570;
|
||||
msgInShadow: #748ea229;
|
||||
msgInShadowSelected: #548dbb29;
|
||||
msgOutShadow: #3ac34740;
|
||||
msgOutShadowSelected: #37a78e40;
|
||||
msgInDateFg: #a0acb6;
|
||||
msgInDateFgSelected: #6a9cc5;
|
||||
msgOutDateFg: #6cc264;
|
||||
msgOutDateFgSelected: #50a79c;
|
||||
msgServiceFg: windowFgActive;
|
||||
msgServiceBg: #517c417f;
|
||||
msgServiceBgSelected: #96b38ba2;
|
||||
msgInReplyBarColor: activeLineFg;
|
||||
msgInReplyBarSelColor: activeLineFg;
|
||||
msgOutReplyBarColor: historyOutIconFg;
|
||||
msgOutReplyBarSelColor: historyOutIconFgSelected;
|
||||
msgImgReplyBarColor: msgServiceFg;
|
||||
msgInMonoFg: #4e7391;
|
||||
msgOutMonoFg: #469165;
|
||||
msgDateImgFg: msgServiceFg;
|
||||
msgDateImgBg: #00000054;
|
||||
msgDateImgBgOver: #00000074;
|
||||
msgDateImgBgSelected: #1c4a7187;
|
||||
msgFileThumbLinkInFg: lightButtonFg; // inbox media file message with thumbnail download / open with button text
|
||||
msgFileThumbLinkInFgSelected: lightButtonFgOver; // inbox selected media file message with thumbnail download / open with button text
|
||||
msgFileThumbLinkOutFg: #5eba5b; // outbox media file message with thumbnail download / open with button text
|
||||
msgFileThumbLinkOutFgSelected: #31a298; // outbox selected media file message with thumbnail download / open with button text
|
||||
msgFileInBg: windowBgActive; // inbox audio file download circle background
|
||||
msgFileInBgOver: #4eade3; // inbox audio file download circle background with mouse over
|
||||
msgFileInBgSelected: #51a3d3; // inbox selected audio file download circle background
|
||||
msgFileOutBg: #78c67f; // outbox audio file download circle background
|
||||
msgFileOutBgOver: #6bc272; // outbox audio file download circle background with mouse over
|
||||
msgFileOutBgSelected: #5fb389; // outbox selected audio file download circle background
|
||||
|
||||
msgFileThumbLinkInFg: lightButtonFg;
|
||||
msgFileThumbLinkInFgSelected: lightButtonFgOver;
|
||||
msgFileThumbLinkOutFg: #5eba5b;
|
||||
msgFileThumbLinkOutFgSelected: #31a298;
|
||||
msgFileInBg: windowBgActive;
|
||||
msgFileInBgOver: #4eade3;
|
||||
msgFileInBgSelected: #51a3d3;
|
||||
msgFileOutBg: #78c67f;
|
||||
msgFileOutBgOver: #6bc272;
|
||||
msgFileOutBgSelected: #5fb389;
|
||||
msgFile1Bg: #72b1df; // blue shared links / files without image square thumbnail
|
||||
msgFile1BgDark: #5c9ece; // blue shared files without image download circle background
|
||||
msgFile1BgOver: #5294c4; // blue shared files without image download circle background with mouse over
|
||||
msgFile1BgSelected: #5099d0; // blue shared files without image download circle background if file is selected
|
||||
msgFile2Bg: #61b96e; // green shared links / shared files without image square thumbnail
|
||||
msgFile2BgDark: #4da859; // green shared files without image download circle background
|
||||
msgFile2BgOver: #44a050; // green shared files without image download circle background with mouse over
|
||||
msgFile2BgSelected: #46a07e; // green shared files without image download circle background if file is selected
|
||||
msgFile3Bg: #e47272; // red shared links / shared files without image square thumbnail
|
||||
msgFile3BgDark: #cd5b5e; // red shared files without image download circle background
|
||||
msgFile3BgOver: #c35154; // red shared files without image download circle background with mouse over
|
||||
msgFile3BgSelected: #9f6a82; // red shared files without image download circle background if file is selected
|
||||
msgFile4Bg: #efc274; // yellow shared links / shared files without image square thumbnail
|
||||
msgFile4BgDark: #e6a561; // yellow shared files without image download circle background
|
||||
msgFile4BgOver: #dc9c5a; // yellow shared files without image download circle background with mouse over
|
||||
msgFile4BgSelected: #b19d84; // yellow shared files without image download circle background if file is selected
|
||||
|
||||
msgFile1Bg: #72b1df; // blue
|
||||
msgFile1BgDark: #5c9ece;
|
||||
msgFile1BgOver: #5294c4;
|
||||
msgFile1BgSelected: #5099d0;
|
||||
msgFile2Bg: #61b96e; // green
|
||||
msgFile2BgDark: #4da859;
|
||||
msgFile2BgOver: #44a050;
|
||||
msgFile2BgSelected: #46a07e;
|
||||
msgFile3Bg: #e47272; // red
|
||||
msgFile3BgDark: #cd5b5e;
|
||||
msgFile3BgOver: #c35154;
|
||||
msgFile3BgSelected: #9f6a82;
|
||||
msgFile4Bg: #efc274; // yellow
|
||||
msgFile4BgDark: #e6a561;
|
||||
msgFile4BgOver: #dc9c5a;
|
||||
msgFile4BgSelected: #b19d84;
|
||||
historyFileInIconFg: msgInBg; // inbox file without thumbnail (like audio file) download arrow icon
|
||||
historyFileInIconFgSelected: msgInBgSelected; // inbox selected file without thumbnail (like audio file) download arrow icon
|
||||
historyFileInRadialFg: historyFileInIconFg; // inbox file without thumbnail (like audio file) radial download animation line
|
||||
historyFileInRadialFgSelected: historyFileInIconFgSelected; // inbox selected file without thumbnail (like audio file) radial download animation line
|
||||
historyFileOutIconFg: msgOutBg; // outbox file without thumbnail (like audio file) download arrow icon
|
||||
historyFileOutIconFgSelected: msgOutBgSelected; // outbox selected file without thumbnail (like audio file) download arrow icon
|
||||
historyFileOutRadialFg: historyFileOutIconFg; // outbox file without thumbnail (like audio file) radial download animation line
|
||||
historyFileOutRadialFgSelected: historyFileOutIconFgSelected; // outbox selected file without thumbnail (like audio file) radial download animation line
|
||||
historyFileThumbIconFg: msgInBg; // file with thumbnail (or photo / video) download arrow icon
|
||||
historyFileThumbIconFgSelected: msgInBgSelected; // selected file with thumbnail (or photo / video) download arrow icon
|
||||
historyFileThumbRadialFg: historyFileThumbIconFg; // file with thumbnail (or photo / video) radial download animation line
|
||||
historyFileThumbRadialFgSelected: historyFileThumbIconFgSelected; // selected file with thumbnail (or photo / video) radial download animation line
|
||||
|
||||
historyFileInIconFg: msgInBg;
|
||||
historyFileInIconFgSelected: msgInBgSelected;
|
||||
historyFileInRadialFg: historyFileInIconFg;
|
||||
historyFileInRadialFgSelected: historyFileInIconFgSelected;
|
||||
historyFileOutIconFg: msgOutBg;
|
||||
historyFileOutIconFgSelected: msgOutBgSelected;
|
||||
historyFileOutRadialFg: historyFileOutIconFg;
|
||||
historyFileOutRadialFgSelected: historyFileOutIconFgSelected;
|
||||
historyFileThumbIconFg: msgInBg;
|
||||
historyFileThumbIconFgSelected: msgInBgSelected;
|
||||
historyFileThumbRadialFg: historyFileThumbIconFg;
|
||||
historyFileThumbRadialFgSelected: historyFileThumbIconFgSelected;
|
||||
msgWaveformInActive: windowBgActive; // inbox voice message active waveform lines (like played part of currently playing voice message)
|
||||
msgWaveformInActiveSelected: #51a3d3; // inbox selected voice message active waveform lines (like played part of currently playing voice message)
|
||||
msgWaveformInInactive: #d4dee6; // inbox voice message inactive waveform lines (like upcoming part of currently playing voice message)
|
||||
msgWaveformInInactiveSelected: #9cc1e1; // inbox selected voice message inactive waveform lines (like upcoming part of currently playing voice message)
|
||||
msgWaveformOutActive: #78c67f; // outbox voice message active waveform lines (like played part of currently playing voice message)
|
||||
msgWaveformOutActiveSelected: #6badad; // outbox selected voice message active waveform lines (like played part of currently playing voice message)
|
||||
msgWaveformOutInactive: #b3e2b4; // outbox voice message inactive waveform lines (like upcoming part of currently playing voice message)
|
||||
msgWaveformOutInactiveSelected: #91c3c3; // outbox selected voice message inactive waveform lines (like upcoming part of currently playing voice message)
|
||||
|
||||
msgWaveformInActive: windowBgActive;
|
||||
msgWaveformInActiveSelected: #51a3d3;
|
||||
msgWaveformInInactive: #d4dee6;
|
||||
msgWaveformInInactiveSelected: #9cc1e1;
|
||||
msgWaveformOutActive: #78c67f;
|
||||
msgWaveformOutActiveSelected: #6badad;
|
||||
msgWaveformOutInactive: #b3e2b4;
|
||||
msgWaveformOutInactiveSelected: #91c3c3;
|
||||
msgBotKbOverBgAdd: #ffffff20; // this is painted over a bot inline keyboard button (which has msgServiceBg background) when mouse is over that button
|
||||
msgBotKbIconFg: msgServiceFg; // bot inline keyboard button icon in the top-right corner (like in @vote bot when a poll is ready to be shared)
|
||||
msgBotKbRippleBg: #00000020; // bot inline keyboard button ripple effect
|
||||
|
||||
msgBotKbOverBgAdd: #ffffff20;
|
||||
msgBotKbIconFg: msgServiceFg;
|
||||
msgBotKbRippleBg: #00000020;
|
||||
mediaInFg: msgInDateFg; // inbox media message status text (like in file that is being downloaded)
|
||||
mediaInFgSelected: msgInDateFgSelected; // inbox selected media message status text (like in file that is being downloaded)
|
||||
mediaOutFg: msgOutDateFg; // outbox media message status text (like in file that is being downloaded)
|
||||
mediaOutFgSelected: msgOutDateFgSelected; // outbox selected media message status text (like in file that is being downloaded)
|
||||
|
||||
mediaInFg: msgInDateFg;
|
||||
mediaInFgSelected: msgInDateFgSelected;
|
||||
mediaOutFg: msgOutDateFg;
|
||||
mediaOutFgSelected: msgOutDateFgSelected;
|
||||
youtubePlayIconBg: #e83131c8; // youtube play icon background (when a link to a youtube video with a webpage preview is sent)
|
||||
youtubePlayIconFg: windowFgActive; // youtube play icon arrow (when a link to a youtube video with a webpage preview is sent)
|
||||
videoPlayIconBg: #0000007f; // other video play icon background (like when a link to a vimeo video with a webpage preview is sent)
|
||||
videoPlayIconFg: #ffffff; // other video play icon arrow (like when a link to a vimeo video with a webpage preview is sent)
|
||||
toastBg: #000000b2; // toast notification background (like when you click on your t.me link when editing your username)
|
||||
toastFg: windowFgActive; // toast notification text (like when you click on your t.me link when editing your username)
|
||||
|
||||
youtubePlayIconBg: #e83131c8;
|
||||
youtubePlayIconFg: windowFgActive;
|
||||
videoPlayIconBg: #0000007f;
|
||||
videoPlayIconFg: #ffffff;
|
||||
toastBg: #000000b2;
|
||||
toastFg: windowFgActive;
|
||||
reportSpamBg: emojiPanHeaderBg; // report spam panel background (like a non contact user writes your for the first time)
|
||||
reportSpamFg: windowFg; // report spam panel text (when you send a report from that panel)
|
||||
|
||||
reportSpamBg: emojiPanHeaderBg;
|
||||
reportSpamFg: windowFg;
|
||||
historyToDownBg: windowBg; // arrow button background (to scroll to the end of the viewed chat)
|
||||
historyToDownBgOver: windowBgOver; // arrow button background with mouse over
|
||||
historyToDownBgRipple: windowBgRipple; // arrow button ripple effect
|
||||
historyToDownFg: menuIconFg; // arrow button icon
|
||||
historyToDownFgOver: menuIconFgOver; // arrow button icon with mouse over
|
||||
historyToDownShadow: #00000040; // arrow button shadow
|
||||
|
||||
historyToDownBg: windowBg;
|
||||
historyToDownBgOver: windowBgOver;
|
||||
historyToDownBgRipple: windowBgRipple;
|
||||
historyToDownFg: menuIconFg;
|
||||
historyToDownFgOver: menuIconFgOver;
|
||||
historyToDownShadow: #00000040;
|
||||
historyComposeAreaBg: msgInBg; // history compose area background (message write area / reply information / forwarding information)
|
||||
historyComposeAreaFg: historyTextInFg; // history compose area text
|
||||
historyComposeAreaFgService: msgInDateFg; // history compose area text when replying to a media message
|
||||
historyComposeIconFg: menuIconFg; // history compose area icon (like emoji, attach, bot command..)
|
||||
historyComposeIconFgOver: menuIconFgOver; // history compose area icon with mouse over
|
||||
historySendIconFg: windowBgActive; // send message icon
|
||||
historySendIconFgOver: windowBgActive; // send message icon with mouse over
|
||||
historyPinnedBg: historyComposeAreaBg; // pinned message area background
|
||||
historyReplyBg: historyComposeAreaBg; // reply / forward / edit message area background
|
||||
historyReplyIconFg: windowBgActive; // reply / forward / edit message left icon
|
||||
historyReplyCancelFg: cancelIconFg; // reply / forward / edit message cancel button
|
||||
historyReplyCancelFgOver: cancelIconFgOver; // reply / forward / edit message cancel button with mouse over
|
||||
|
||||
historyComposeAreaBg: msgInBg;
|
||||
historyComposeAreaFg: historyTextInFg;
|
||||
historyComposeAreaFgService: msgInDateFg;
|
||||
historyComposeIconFg: menuIconFg;
|
||||
historyComposeIconFgOver: menuIconFgOver;
|
||||
historySendIconFg: windowBgActive;
|
||||
historySendIconFgOver: windowBgActive;
|
||||
historyPinnedBg: historyComposeAreaBg;
|
||||
historyReplyBg: historyComposeAreaBg;
|
||||
historyReplyIconFg: windowBgActive;
|
||||
historyReplyCancelFg: cancelIconFg;
|
||||
historyReplyCancelFgOver: cancelIconFgOver;
|
||||
|
||||
historyComposeButtonBg: historyComposeAreaBg;
|
||||
historyComposeButtonBgOver: windowBgOver;
|
||||
historyComposeButtonBgRipple: windowBgRipple;
|
||||
historyComposeButtonBg: historyComposeAreaBg; // unblock / join channel / mute channel button background
|
||||
historyComposeButtonBgOver: windowBgOver; // unblock / join channel / mute channel button background with mouse over
|
||||
historyComposeButtonBgRipple: windowBgRipple; // unblock / join channel / mute channel button ripple effect
|
||||
|
||||
// overview
|
||||
overviewCheckBg: #00000040;
|
||||
overviewCheckFg: windowBg;
|
||||
overviewCheckFgActive: windowBg;
|
||||
overviewPhotoSelectOverlay: #40ace333;
|
||||
overviewCheckBg: #00000040; // shared files / links checkbox background for not selected rows when some rows are selected
|
||||
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
|
||||
|
||||
// profile
|
||||
profileStatusFgOver: #7c99b2;
|
||||
profileVerifiedCheckBg: windowBgActive;
|
||||
profileVerifiedCheckFg: windowFgActive;
|
||||
profileAdminStartFg: windowBgActive;
|
||||
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
|
||||
|
||||
// settings
|
||||
notificationsBoxMonitorFg: windowFg;
|
||||
notificationsBoxScreenBg: dialogsBgActive; // #6389a8;
|
||||
notificationsBoxMonitorFg: windowFg; // custom notifications settings box monitor color
|
||||
notificationsBoxScreenBg: dialogsBgActive; // #6389a8; // custom notifications settings box monitor screen background
|
||||
|
||||
notificationSampleUserpicFg: windowBgActive;
|
||||
notificationSampleCloseFg: #d7d7d7 | windowSubTextFg;
|
||||
notificationSampleTextFg: #d7d7d7 | windowSubTextFg;
|
||||
notificationSampleNameFg: #939393 | windowSubTextFg;
|
||||
notificationSampleUserpicFg: windowBgActive; // custom notifications settings box small sample userpic placeholder
|
||||
notificationSampleCloseFg: #d7d7d7 | windowSubTextFg; // custom notifications settings box small sample close button placeholder
|
||||
notificationSampleTextFg: #d7d7d7 | windowSubTextFg; // custom notifications settings box small sample text placeholder
|
||||
notificationSampleNameFg: #939393 | windowSubTextFg; // custom notifications settings box small sample name placeholder
|
||||
|
||||
mainMenuBg: windowBg;
|
||||
mainMenuCoverBg: dialogsBgActive;
|
||||
mainMenuCoverFg: windowFgActive;
|
||||
mainMenuBg: windowBg; // main menu background
|
||||
mainMenuCoverBg: dialogsBgActive; // main menu top cover background
|
||||
mainMenuCoverFg: windowFgActive; // main menu top cover text
|
||||
|
||||
mediaPlayerBg: windowBg;
|
||||
mediaPlayerActiveFg: windowBgActive;
|
||||
mediaPlayerInactiveFg: sliderBgInactive;
|
||||
mediaPlayerDisabledFg: #9dd1ef;
|
||||
mediaPlayerBg: windowBg; // audio file player background
|
||||
mediaPlayerActiveFg: windowBgActive; // audio file player playback progress already played part
|
||||
mediaPlayerInactiveFg: sliderBgInactive; // audio file player playback progress upcoming (not played yet) part with mouse over
|
||||
mediaPlayerDisabledFg: #9dd1ef; // audio file player loading progress (when you're playing an audio file and switch to the previous one which is not loaded yet)
|
||||
|
||||
// mediaview
|
||||
mediaviewFileBg: windowBg;
|
||||
mediaviewFileNameFg: windowFg;
|
||||
mediaviewFileSizeFg: windowSubTextFg;
|
||||
mediaviewFileRedCornerFg: #d55959;
|
||||
mediaviewFileYellowCornerFg: #e8a659;
|
||||
mediaviewFileGreenCornerFg: #49a957;
|
||||
mediaviewFileBlueCornerFg: #599dcf;
|
||||
mediaviewFileExtFg: activeButtonFg;
|
||||
mediaviewFileBg: windowBg; // file rectangle background (when you view a png file in Media Viewer and go to a previous, not loaded yet, file)
|
||||
mediaviewFileNameFg: windowFg; // file name in file rectangle
|
||||
mediaviewFileSizeFg: windowSubTextFg; // file size text in file rectangle
|
||||
mediaviewFileRedCornerFg: #d55959; // red file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .pdf)
|
||||
mediaviewFileYellowCornerFg: #e8a659; // yellow file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .zip)
|
||||
mediaviewFileGreenCornerFg: #49a957; // green file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .exe)
|
||||
mediaviewFileBlueCornerFg: #599dcf; // blue file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .dmg)
|
||||
mediaviewFileExtFg: activeButtonFg; // file extension text in file thumbnail placeholder in file rectangle
|
||||
|
||||
mediaviewMenuBg: #383838;
|
||||
mediaviewMenuBgOver: #505050;
|
||||
mediaviewMenuBgRipple: #676767;
|
||||
mediaviewMenuFg: windowFgActive;
|
||||
mediaviewMenuBg: #383838; // context menu in Media Viewer background
|
||||
mediaviewMenuBgOver: #505050; // context menu item background with mouse over
|
||||
mediaviewMenuBgRipple: #676767; // context menu item ripple effect
|
||||
mediaviewMenuFg: windowFgActive; // context menu item text
|
||||
|
||||
mediaviewBg: #222222eb;
|
||||
mediaviewVideoBg: imageBg;
|
||||
mediaviewControlBg: #0000003c;
|
||||
mediaviewControlFg: windowFgActive;
|
||||
mediaviewCaptionBg: #11111180;
|
||||
mediaviewCaptionFg: mediaviewControlFg;
|
||||
mediaviewTextLinkFg: #91d9ff;
|
||||
mediaviewSaveMsgBg: toastBg;
|
||||
mediaviewSaveMsgFg: toastFg;
|
||||
mediaviewBg: #222222eb; // Media Viewer background
|
||||
mediaviewVideoBg: imageBg; // Media Viewer background when viewing a video in full screen
|
||||
mediaviewControlBg: #0000003c; // controls background (like next photo / previous photo)
|
||||
mediaviewControlFg: windowFgActive; // controls icon (like next photo / previous photo)
|
||||
mediaviewCaptionBg: #11111180; // caption text background (when viewing photo with caption)
|
||||
mediaviewCaptionFg: mediaviewControlFg; // caption text
|
||||
mediaviewTextLinkFg: #91d9ff; // caption text link
|
||||
mediaviewSaveMsgBg: toastBg; // save to file toast message background in Media Viewer
|
||||
mediaviewSaveMsgFg: toastFg; // save to file toast message text
|
||||
|
||||
mediaviewPlaybackActive: #c7c7c7;
|
||||
mediaviewPlaybackInactive: #252525;
|
||||
mediaviewPlaybackActiveOver: #ffffff;
|
||||
mediaviewPlaybackInactiveOver: #474747;
|
||||
mediaviewPlaybackProgressFg: #ffffffc7;
|
||||
mediaviewPlaybackIconFg: mediaviewPlaybackActive;
|
||||
mediaviewPlaybackIconFgOver: mediaviewPlaybackActiveOver;
|
||||
mediaviewTransparentBg: #ffffff;
|
||||
mediaviewTransparentFg: #cccccc;
|
||||
mediaviewPlaybackActive: #c7c7c7; // video playback progress already played part
|
||||
mediaviewPlaybackInactive: #252525; // video playback progress upcoming (not played yet) part
|
||||
mediaviewPlaybackActiveOver: #ffffff; // video playback progress already played part with mouse over
|
||||
mediaviewPlaybackInactiveOver: #474747; // video playback progress upcoming (not played yet) part with mouse over
|
||||
mediaviewPlaybackProgressFg: #ffffffc7; // video playback progress text
|
||||
mediaviewPlaybackIconFg: mediaviewPlaybackActive; // video playback controls icon
|
||||
mediaviewPlaybackIconFgOver: mediaviewPlaybackActiveOver; // video playback controls icon with mouse over
|
||||
mediaviewTransparentBg: #ffffff; // transparent filling part (when viewing a transparent .png file in Media Viewer)
|
||||
mediaviewTransparentFg: #cccccc; // another transparent filling part
|
||||
|
||||
// notification
|
||||
notificationBg: windowBg;
|
||||
notificationBg: windowBg; // custom notification window background
|
||||
|
||||
@@ -124,8 +124,6 @@ boxTextFgGood: #4ab44a;
|
||||
boxTextFgError: #d84d4d;
|
||||
boxTitleFg: #404040;
|
||||
boxSearchBg: boxBg;
|
||||
boxSearchCancelIconFg: cancelIconFg;
|
||||
boxSearchCancelIconFgOver: cancelIconFgOver;
|
||||
boxTitleAdditionalFg: #808080;
|
||||
boxTitleCloseFg: cancelIconFg;
|
||||
boxTitleCloseFgOver: cancelIconFgOver;
|
||||
@@ -196,7 +194,6 @@ dialogsUnreadFgActive: dialogsBgActive;
|
||||
dialogsForwardBg: dialogsBgActive;
|
||||
dialogsForwardFg: dialogsNameFgActive;
|
||||
searchedBarBg: windowBgOver;
|
||||
searchedBarBorder: shadowFg;
|
||||
searchedBarFg: windowSubTextFgOver;
|
||||
topBarBg: windowBg;
|
||||
emojiPanBg: windowBg;
|
||||
@@ -218,9 +215,6 @@ historyIconFgInverted: windowFgActive;
|
||||
historySendingOutIconFg: #98d292;
|
||||
historySendingInIconFg: #a0adb5;
|
||||
historySendingInvertedIconFg: #ffffffc8;
|
||||
historySystemBg: #89a0b47f;
|
||||
historySystemBgSelected: #bbc8d4a2;
|
||||
historySystemFg: windowFgActive;
|
||||
historyUnreadBarBg: #fcfbfa;
|
||||
historyUnreadBarBorder: shadowFg;
|
||||
historyUnreadBarFg: #538bb4;
|
||||
|
||||
BIN
Telegram/Resources/icons/color_slider_arrow.png
Normal file
|
After Width: | Height: | Size: 152 B |
BIN
Telegram/Resources/icons/color_slider_arrow@2x.png
Normal file
|
After Width: | Height: | Size: 193 B |
BIN
Telegram/Resources/icons/color_slider_arrow_vertical.png
Normal file
|
After Width: | Height: | Size: 175 B |
BIN
Telegram/Resources/icons/color_slider_arrow_vertical@2x.png
Normal file
|
After Width: | Height: | Size: 236 B |
@@ -224,7 +224,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_settings_crop_profile" = "Select a square 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";
|
||||
|
||||
"lng_username_title" = "Username";
|
||||
@@ -296,6 +295,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_settings_bg_use_default" = "Use default color theme";
|
||||
"lng_settings_bg_from_gallery" = "Choose from gallery";
|
||||
"lng_settings_bg_from_file" = "Choose from file";
|
||||
"lng_settings_bg_edit_theme" = "Edit theme";
|
||||
"lng_settings_bg_tile" = "Tile background";
|
||||
"lng_settings_adaptive_wide" = "Adaptive layout for wide screens";
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
||||
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
||||
"lng_new_version_text" = "— New option to minimize the chat list into a column of profile pictures. Resize the list by clicking and dragging.\n— Fixed drag-n-drop images from Firefox on Windows.\n— Bug fixes and other minor improvements.";
|
||||
"lng_new_version_text" = "— Click and drag to reorder pinned chats.\n— Bug fixes and other minor improvements.";
|
||||
|
||||
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
||||
|
||||
@@ -1023,6 +1023,22 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_confirm_phone_send" = "Send";
|
||||
"lng_confirm_phone_enter_code" = "Please enter the code.";
|
||||
|
||||
"lng_theme_editor_no_keys" = "No keys in the palette yet";
|
||||
"lng_theme_editor_cant_change_theme" = "You can not apply new themes while you're editing the color palette. Please close the theme editor first.";
|
||||
"lng_theme_editor_new_keys" = "Not in the palette yet";
|
||||
"lng_theme_editor_background_image" = "Background image";
|
||||
"lng_theme_editor_saved_to_jpg" = "Saved to JPEG, {size}";
|
||||
"lng_theme_editor_read_from_jpg" = "JPEG image, {size}";
|
||||
"lng_theme_editor_read_from_png" = "PNG image, {size}";
|
||||
"lng_theme_editor_export" = "Export";
|
||||
"lng_theme_editor_choose_image" = "Choose background image";
|
||||
"lng_theme_editor_save_palette" = "Save palette file";
|
||||
"lng_theme_editor_choose_name" = "Save theme file";
|
||||
"lng_theme_editor_error" = "The editor encountered an error :( See 'log.txt' for details.";
|
||||
"lng_theme_editor_done" = "Theme exported successfully!";
|
||||
"lng_theme_editor_title" = "Edit color palette";
|
||||
"lng_theme_editor_export_button" = "Export theme";
|
||||
|
||||
// Not used
|
||||
|
||||
"lng_topbar_info" = "Info";
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}";
|
||||
"lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen";
|
||||
"lng_new_version_text" = "— Chatliste lässt sich zusammenschieben, so dass man nur noch die Profilbilder sehen kann.\n— Drag und Drop von Bildern klappt wieder mit Firefox (Windows)\n— Fehlerbehebungen und sonstige Verbesserungen.";
|
||||
"lng_new_version_text" = "— Angeheftete Chats lassen sich verschieben (gedrückt halten und nach oben oder unter ziehen).\n— Fehlerbehebungen und sonstige Softwareoptimierungen.";
|
||||
|
||||
"lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen";
|
||||
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_new_version_wrap" = "Telegram Desktop ha sido actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}";
|
||||
"lng_new_version_minor" = "— Corrección de errores y otras mejoras menores";
|
||||
"lng_new_version_text" = "— Nueva opción para minimizar la lista de chats en una columna de imágenes de perfil. Cambia el tamaño de la lista haciendo clic y arrastrando.\n— Arrastrar y soltar arreglado para las imágenes desde Firefox en Windows.\n— Corrección de errores y otras mejoras menores.";
|
||||
"lng_new_version_text" = "— Arrastra un chat anclado para cambiar su posición.\n— Corrección de errores y otras mejoras menores.";
|
||||
|
||||
"lng_menu_insert_unicode" = "Insertar caracteres de control Unicode";
|
||||
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli aggiornamenti è disponibile qui:\n{link}";
|
||||
"lng_new_version_minor" = "— Risoluzione di problemi e altri miglioramenti minori";
|
||||
"lng_new_version_text" = "— Nuova opzione per minimizzare la lista delle chat in una colonna di foto profilo. Ridimensiona la lista cliccando e trascinando.\n— Risolto il problema del trascinamento delle immagini da Firefox su Windows.\n— Risoluzione di problemi e altri miglioramenti minori.";
|
||||
"lng_new_version_text" = "— Premi e trascina per riordinare le chat fissate.\n— Risoluzione di problemi e altri miglioramenti minori.";
|
||||
|
||||
"lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode";
|
||||
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}";
|
||||
"lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상";
|
||||
"lng_new_version_text" = "— 대화방목록 크기를 프로필사진 목록으로 최소화하는 옵션 추가. 클릭 후 드래그를 하여 리스트 크기 조절 가능\n— 윈도우 파이어폭스에서 이미지 드래그 후 드롭 수정\n— 버그 수정 및 일부 기능 향상";
|
||||
"lng_new_version_text" = "— 클릭 후 드래그로 고정된 대화 순서 변경\n— 버그 수정 및 일부기능 향상";
|
||||
|
||||
"lng_menu_insert_unicode" = "유니코드 문자를 입력하세요.";
|
||||
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
|
||||
"lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen";
|
||||
"lng_new_version_text" = "— Nieuwe optie, minimaliseer het overzicht met chats naar een overzicht van profielfoto's. Formaat wijzigen door de lijst aan te klikken en te slepen.\n— Probleem het slepen en neerzetten van afbeeldingen vanuit Firefox onder Windows opgelost.\n— Probleemoplossing en andere kleine verbeteringen.";
|
||||
"lng_new_version_text" = "— Klik en sleep om de volgorde van vastgezette chats aan te passen.\n— Probleemoplossing en andere kleine verbeteringen.";
|
||||
|
||||
"lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen";
|
||||
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
"lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}";
|
||||
"lng_new_version_minor" = "— Resolução de bugs e outras melhorias menores";
|
||||
"lng_new_version_text" = "— Nova opção para minimizar a lista de conversas em uma coluna com fotos de perfil. Redimensione a lista clicando e arrastando.\n— Resolvido o problema ao arrastar e soltar imagens do Firefox no Windows.\n— Resoluções de erros e melhorias menores.";
|
||||
"lng_new_version_text" = "— Clique e arraste para reordenar os chats fixados.\n— Resolução de bugs e outras melhorias.";
|
||||
|
||||
"lng_menu_insert_unicode" = "Inserir caractere de controle Unicode";
|
||||
|
||||
|
||||
43
Telegram/Resources/uwp/AppX/AppxManifest.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
|
||||
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap uap2 uap3 rescap">
|
||||
<Identity Name="TelegramDesktop"
|
||||
ProcessorArchitecture="x64"
|
||||
Publisher="CN=Telegram Messenger LLP, O=Telegram Messenger LLP, L=London, C=GB"
|
||||
Version="1.0.8.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
<Description>Telegram Desktop official messenger</Description>
|
||||
<Logo>Assets\logo\logo.png</Logo>
|
||||
</Properties>
|
||||
<Resources>
|
||||
<Resource Language="en-us" />
|
||||
</Resources>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14316.0" MaxVersionTested="10.0.14316.0" />
|
||||
</Dependencies>
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust"/>
|
||||
</Capabilities>
|
||||
<Applications>
|
||||
<Application Id="Telegram.TelegramDesktop.Store" Executable="Telegram.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
BackgroundColor="transparent"
|
||||
DisplayName="Telegram Desktop"
|
||||
Square150x150Logo="Assets\logo150\logo150.png"
|
||||
Square44x44Logo="Assets\logo44\logo44.png"
|
||||
Description="Telegram Desktop official messenger" />
|
||||
<Extensions>
|
||||
<uap3:Extension Category="windows.protocol">
|
||||
<uap3:Protocol Name="tg" Parameters="-- "%1"" />
|
||||
</uap3:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
</Package>
|
||||
BIN
Telegram/Resources/uwp/AppX/Assets/logo/logo.scale-100.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo/logo.scale-125.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo/logo.scale-150.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo/logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo/logo.scale-400.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo150/logo150.scale-100.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo150/logo150.scale-125.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo150/logo150.scale-150.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo150/logo150.scale-200.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo150/logo150.scale-400.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo44/logo44.scale-100.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo44/logo44.scale-125.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo44/logo44.scale-150.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo44/logo44.scale-200.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
Telegram/Resources/uwp/AppX/Assets/logo44/logo44.scale-400.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 852 B |
|
After Width: | Height: | Size: 852 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
23
Telegram/Resources/uwp/priconfig.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<resources targetOsVersion="10.0.0" majorVersion="1">
|
||||
<index root="\" startIndexAt="\">
|
||||
<default>
|
||||
<qualifier name="Language" value="en-US"/>
|
||||
<qualifier name="Contrast" value="standard"/>
|
||||
<qualifier name="Scale" value="100"/>
|
||||
<qualifier name="HomeRegion" value="001"/>
|
||||
<qualifier name="TargetSize" value="256"/>
|
||||
<qualifier name="LayoutDirection" value="LTR"/>
|
||||
<qualifier name="Theme" value="dark"/>
|
||||
<qualifier name="AlternateForm" value=""/>
|
||||
<qualifier name="DXFeatureLevel" value="DX9"/>
|
||||
<qualifier name="Configuration" value=""/>
|
||||
<qualifier name="DeviceFamily" value="Universal"/>
|
||||
<qualifier name="Custom" value=""/>
|
||||
</default>
|
||||
<indexer-config type="folder" foldernameAsQualifier="true" filenameAsQualifier="true" qualifierDelimiter="."/>
|
||||
<indexer-config type="resw" convertDotsToSlashes="true" initialPath=""/>
|
||||
<indexer-config type="resjson" initialPath=""/>
|
||||
<indexer-config type="PRI"/>
|
||||
</index>
|
||||
</resources>
|
||||
@@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,2,0
|
||||
PRODUCTVERSION 1,0,2,0
|
||||
FILEVERSION 1,0,8,0
|
||||
PRODUCTVERSION 1,0,8,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -51,10 +51,11 @@ BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileVersion", "1.0.2.0"
|
||||
VALUE "FileDescription", "Telegram Desktop official messenger"
|
||||
VALUE "FileVersion", "1.0.8.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "1.0.2.0"
|
||||
VALUE "ProductVersion", "1.0.8.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,2,0
|
||||
PRODUCTVERSION 1,0,2,0
|
||||
FILEVERSION 1,0,8,0
|
||||
PRODUCTVERSION 1,0,8,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -42,11 +42,11 @@ BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileDescription", "Telegram Updater"
|
||||
VALUE "FileVersion", "1.0.2.0"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "1.0.8.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "1.0.2.0"
|
||||
VALUE "ProductVersion", "1.0.8.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -30,7 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "historywidget.h"
|
||||
#include "localstorage.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "window/window_theme.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
|
||||
ApiWrap::ApiWrap(QObject *parent) : QObject(parent)
|
||||
, _messageDataResolveDelayed(new SingleDelayedCall(this, "resolveMessageDatas")) {
|
||||
|
||||
@@ -44,7 +44,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "apiwrap.h"
|
||||
#include "numbers.h"
|
||||
#include "observer_peer.h"
|
||||
#include "window/window_theme.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
|
||||
@@ -195,9 +195,7 @@ namespace {
|
||||
Global::SetLocalPasscode(false);
|
||||
Global::RefLocalPasscodeChanged().notify();
|
||||
}
|
||||
if (audioPlayer()) {
|
||||
audioPlayer()->stopAndClear();
|
||||
}
|
||||
Media::Player::mixer()->stopAndClear();
|
||||
if (auto w = wnd()) {
|
||||
w->tempDirDelete(Local::ClearManagerAll);
|
||||
w->notifyClearFast();
|
||||
@@ -2436,7 +2434,7 @@ namespace {
|
||||
|
||||
void playSound() {
|
||||
if (Global::SoundNotify() && !Platform::Notifications::skipAudio()) {
|
||||
audioPlayNotify();
|
||||
Media::Player::PlayNotify();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ using GifItems = QHash<Media::Clip::Reader*, HistoryItem*>;
|
||||
using PhotosData = QHash<PhotoId, PhotoData*>;
|
||||
using DocumentsData = QHash<DocumentId, DocumentData*>;
|
||||
|
||||
struct LocationCoords;
|
||||
class LocationCoords;
|
||||
struct LocationData;
|
||||
|
||||
namespace App {
|
||||
|
||||
@@ -34,7 +34,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "autoupdater.h"
|
||||
#include "core/observer.h"
|
||||
#include "observer_peer.h"
|
||||
#include "window/window_theme.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "history/history_location_manager.h"
|
||||
@@ -699,7 +699,7 @@ AppClass::AppClass() : QObject() {
|
||||
|
||||
if (cLaunchMode() == LaunchModeAutoStart && !cAutoStart()) {
|
||||
psAutoStart(false, true);
|
||||
application()->quit();
|
||||
App::quit();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1069,9 +1069,9 @@ void AppClass::checkMapVersion() {
|
||||
if (Local::oldMapVersion() < AppVersion) {
|
||||
if (Local::oldMapVersion()) {
|
||||
QString versionFeatures;
|
||||
if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 1000001) {
|
||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Resize chats list with mouse press-and-drag\n\xe2\x80\x94 Drag-n-drop images from Firefox fixed in Windows\n\xe2\x80\x94 Bug fixes and other minor improvements");
|
||||
} else if (!(cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 1000002) {
|
||||
if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 1000008) {
|
||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Click and drag on waveform to play audio from a chosen moment.");
|
||||
} else if (!(cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 1000005) {
|
||||
versionFeatures = langNewVersionText();
|
||||
} else {
|
||||
versionFeatures = lang(lng_new_version_minor).trimmed();
|
||||
|
||||
@@ -252,16 +252,14 @@ void AbstractBox::paintEvent(QPaintEvent *e) {
|
||||
void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) {
|
||||
p.setFont(st::boxTitleFont);
|
||||
p.setPen(st::boxTitleFg);
|
||||
if (_layerType) {
|
||||
auto titleWidth = st::boxTitleFont->width(title);
|
||||
p.drawTextLeft(st::boxLayerTitlePosition.x(), st::boxLayerTitlePosition.y(), width(), title, titleWidth);
|
||||
if (!additional.isEmpty()) {
|
||||
p.setFont(st::boxLayerTitleAdditionalFont);
|
||||
p.setPen(st::boxTitleAdditionalFg);
|
||||
p.drawTextLeft(st::boxLayerTitlePosition.x() + titleWidth + st::boxLayerTitleAdditionalSkip, st::boxLayerTitlePosition.y() + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), additional);
|
||||
}
|
||||
} else {
|
||||
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), title);
|
||||
auto titleWidth = st::boxTitleFont->width(title);
|
||||
auto titleLeft = _layerType ? st::boxLayerTitlePosition.x() : st::boxTitlePosition.x();
|
||||
auto titleTop = _layerType ? st::boxLayerTitlePosition.y() : st::boxTitlePosition.y();
|
||||
p.drawTextLeft(titleLeft, titleTop, width(), title, titleWidth);
|
||||
if (!additional.isEmpty()) {
|
||||
p.setFont(st::boxLayerTitleAdditionalFont);
|
||||
p.setPen(st::boxTitleAdditionalFg);
|
||||
p.drawTextLeft(titleLeft + titleWidth + st::boxLayerTitleAdditionalSkip, titleTop + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), additional);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -246,12 +246,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
template <typename BoxType, typename ...Args>
|
||||
inline object_ptr<BoxType> Box(Args&&... args) {
|
||||
auto parent = static_cast<QWidget*>(nullptr);
|
||||
return object_ptr<BoxType>(parent, std_::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
enum CreatingGroupType {
|
||||
CreatingGroupNone,
|
||||
CreatingGroupGroup,
|
||||
|
||||
@@ -542,10 +542,7 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
|
||||
if (_linkOver) {
|
||||
Application::clipboard()->setText(_channel->inviteLink());
|
||||
|
||||
Ui::Toast::Config toast;
|
||||
toast.text = lang(lng_create_channel_link_copied);
|
||||
Ui::Toast::Show(App::wnd(), toast);
|
||||
Ui::Toast::Show(lang(lng_create_channel_link_copied));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "lang.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "window/window_theme.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "styles/style_overview.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
|
||||
@@ -530,3 +530,23 @@ usernameTextStyle: TextStyle(passcodeTextStyle) {
|
||||
usernameDefaultFg: windowSubTextFg;
|
||||
|
||||
downloadPathSkip: 10px;
|
||||
|
||||
colorEditWidth: 390px;
|
||||
colorEditSkip: 10px;
|
||||
colorPickerSize: 256px;
|
||||
colorPickerMarkRadius: 6px;
|
||||
colorPickerMarkLine: 1px;
|
||||
colorSliderSkip: 8px;
|
||||
colorSliderArrowLeft: icon {{ "color_slider_arrow", sliderBgActive }};
|
||||
colorSliderArrowRight: icon {{ "color_slider_arrow-flip_horizontal", sliderBgActive }};
|
||||
colorSliderArrowTop: icon {{ "color_slider_arrow_vertical", sliderBgActive }};
|
||||
colorSliderArrowBottom: icon {{ "color_slider_arrow_vertical-flip_vertical", sliderBgActive }};
|
||||
colorSliderWidth: 19px;
|
||||
colorSampleSize: size(60px, 34px);
|
||||
colorFieldSkip: 13px;
|
||||
colorValueInput: InputField(defaultInputField) {
|
||||
textMargins: margins(16px, 3px, 0px, 2px);
|
||||
heightMin: 27px;
|
||||
}
|
||||
colorResultInput: InputField(colorValueInput) {
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ void ConfirmBox::mousePressEvent(QMouseEvent *e) {
|
||||
void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_lastMousePos = e->globalPos();
|
||||
updateHover();
|
||||
if (ClickHandlerPtr activated = ClickHandler::unpressed()) {
|
||||
if (auto activated = ClickHandler::unpressed()) {
|
||||
Ui::hideLayer();
|
||||
App::activateClickHandler(activated, e->button());
|
||||
}
|
||||
@@ -241,10 +241,7 @@ void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
|
||||
mouseMoveEvent(e);
|
||||
if (_linkOver) {
|
||||
Application::clipboard()->setText(_link);
|
||||
|
||||
Ui::Toast::Config toast;
|
||||
toast.text = lang(lng_create_channel_link_copied);
|
||||
Ui::Toast::Show(App::wnd(), toast);
|
||||
Ui::Toast::Show(lang(lng_create_channel_link_copied));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "boxes/photocropbox.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "window/window_theme.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "observer_peer.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
|
||||
@@ -116,11 +116,13 @@ void DownloadPathBox::onEditPath() {
|
||||
}
|
||||
|
||||
void DownloadPathBox::save() {
|
||||
#ifndef OS_WIN_STORE
|
||||
Global::SetDownloadPath(_default->checked() ? QString() : (_temp->checked() ? qsl("tmp") : _path));
|
||||
Global::SetDownloadPathBookmark((_default->checked() || _temp->checked()) ? QByteArray() : _pathBookmark);
|
||||
Local::writeUserSettings();
|
||||
Global::RefDownloadPathChanged().notify();
|
||||
closeBox();
|
||||
#endif // OS_WIN_STORE
|
||||
}
|
||||
|
||||
void DownloadPathBox::setPathText(const QString &text) {
|
||||
|
||||
908
Telegram/SourceFiles/boxes/editcolorbox.cpp
Normal file
@@ -0,0 +1,908 @@
|
||||
/*
|
||||
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 "stdafx.h"
|
||||
#include "boxes/editcolorbox.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "styles/style_mediaview.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
|
||||
class EditColorBox::Picker : public TWidget {
|
||||
public:
|
||||
Picker(QWidget *parent, QColor color);
|
||||
|
||||
float64 valueX() const {
|
||||
return _x;
|
||||
}
|
||||
float64 valueY() const {
|
||||
return _y;
|
||||
}
|
||||
|
||||
base::Observable<void> &changed() {
|
||||
return _changed;
|
||||
}
|
||||
void setHSV(int hue, int saturation, int brightness);
|
||||
void setRGB(int red, int green, int blue);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e);
|
||||
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
|
||||
private:
|
||||
void setFromColor(QColor color);
|
||||
QCursor generateCursor();
|
||||
|
||||
void preparePalette();
|
||||
void updateCurrentPoint(QPoint localPosition);
|
||||
|
||||
QColor _topleft;
|
||||
QColor _topright;
|
||||
QColor _bottomleft;
|
||||
QColor _bottomright;
|
||||
|
||||
QImage _palette;
|
||||
bool _paletteInvalidated = false;
|
||||
float64 _x = 0.;
|
||||
float64 _y = 0.;
|
||||
|
||||
bool _choosing = false;
|
||||
base::Observable<void> _changed;
|
||||
|
||||
};
|
||||
|
||||
QCursor EditColorBox::Picker::generateCursor() {
|
||||
auto diameter = convertScale(16);
|
||||
auto line = convertScale(1);
|
||||
auto size = ((diameter + 2 * line) >= 32) ? 64 : 32;
|
||||
auto cursor = QImage(QSize(size, size) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
cursor.setDevicePixelRatio(cRetinaFactor());
|
||||
cursor.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&cursor);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
auto pen = QPen(Qt::white);
|
||||
pen.setWidth(3 * line);
|
||||
p.setPen(pen);
|
||||
p.drawEllipse((size - diameter) / 2, (size - diameter) / 2, diameter, diameter);
|
||||
pen = QPen(Qt::black);
|
||||
pen.setWidth(line);
|
||||
p.setPen(pen);
|
||||
p.drawEllipse((size - diameter) / 2, (size - diameter) / 2, diameter, diameter);
|
||||
}
|
||||
return QCursor(QPixmap::fromImage(cursor));
|
||||
}
|
||||
|
||||
EditColorBox::Picker::Picker(QWidget *parent, QColor color) : TWidget(parent) {
|
||||
setCursor(generateCursor());
|
||||
|
||||
auto size = QSize(st::colorPickerSize, st::colorPickerSize);
|
||||
resize(size);
|
||||
|
||||
_palette = QImage(size * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
setFromColor(color);
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
preparePalette();
|
||||
|
||||
p.drawImage(0, 0, _palette);
|
||||
|
||||
auto left = anim::color(_topleft, _bottomleft, _y);
|
||||
auto right = anim::color(_topright, _bottomright, _y);
|
||||
auto color = anim::color(left, right, _x);
|
||||
auto lightness = 0.2989 * color.redF() + 0.5870 * color.greenF() + 0.1140 * color.blueF();
|
||||
auto pen = QPen((lightness > 0.6) ? QColor(0, 0, 0) : QColor(255, 255, 255));
|
||||
pen.setWidth(st::colorPickerMarkLine);
|
||||
p.setPen(pen);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
auto x = anim::interpolate(0, width() - 1, _x);
|
||||
auto y = anim::interpolate(0, height() - 1, _y);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
||||
p.drawEllipse(QRect(x - st::colorPickerMarkRadius, y - st::colorPickerMarkRadius, 2 * st::colorPickerMarkRadius, 2 * st::colorPickerMarkRadius));
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::mousePressEvent(QMouseEvent *e) {
|
||||
_choosing = true;
|
||||
updateCurrentPoint(e->pos());
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_choosing) {
|
||||
updateCurrentPoint(e->pos());
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_choosing = false;
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::preparePalette() {
|
||||
if (!_paletteInvalidated) return;
|
||||
_paletteInvalidated = false;
|
||||
|
||||
auto size = _palette.width();
|
||||
auto ints = reinterpret_cast<uint32*>(_palette.bits());
|
||||
auto intsAddPerLine = (_palette.bytesPerLine() - size * sizeof(uint32)) / sizeof(uint32);
|
||||
|
||||
constexpr auto Large = 1024 * 1024;
|
||||
constexpr auto LargeBit = 20; // n / Large == (n >> LargeBit)
|
||||
auto part = Large / size;
|
||||
|
||||
auto topleft = anim::shifted(_topleft);
|
||||
auto topright = anim::shifted(_topright);
|
||||
auto bottomleft = anim::shifted(_bottomleft);
|
||||
auto bottomright = anim::shifted(_bottomright);
|
||||
|
||||
auto y_accumulated = 0;
|
||||
for (auto y = 0; y != size; ++y, y_accumulated += part) {
|
||||
auto y_ratio = y_accumulated >> (LargeBit - 8); // (y_accumulated * 256) / Large;
|
||||
// 0 <= y_accumulated < Large
|
||||
// 0 <= y_ratio < 256
|
||||
|
||||
auto top_ratio = 255 - y_ratio;
|
||||
auto bottom_ratio = y_ratio;
|
||||
|
||||
auto left = anim::reshifted(bottomleft * bottom_ratio + topleft * top_ratio);
|
||||
auto right = anim::reshifted(bottomright * bottom_ratio + topright * top_ratio);
|
||||
|
||||
auto x_accumulated = 0;
|
||||
for (auto x = 0; x != size; ++x, x_accumulated += part) {
|
||||
auto x_ratio = x_accumulated >> (LargeBit - 8); // (x_accumulated * 256) / Large;
|
||||
// 0 <= x_accumulated < Large
|
||||
// 0 <= x_ratio < 256
|
||||
|
||||
auto left_ratio = 255 - x_ratio;
|
||||
auto right_ratio = x_ratio;
|
||||
|
||||
*ints++ = anim::unshifted(left * left_ratio + right * right_ratio);
|
||||
}
|
||||
ints += intsAddPerLine;
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::updateCurrentPoint(QPoint localPosition) {
|
||||
auto x = snap(localPosition.x(), 0, width()) / float64(width());
|
||||
auto y = snap(localPosition.y(), 0, height()) / float64(height());
|
||||
if (_x != x || _y != y) {
|
||||
_x = x;
|
||||
_y = y;
|
||||
update();
|
||||
_changed.notify();
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::setHSV(int hue, int saturation, int brightness) {
|
||||
_topleft = QColor(255, 255, 255);
|
||||
_topright.setHsv(qMax(0, hue), 255, 255);
|
||||
_topright = _topright.toRgb();
|
||||
_bottomleft = _bottomright = QColor(0, 0, 0);
|
||||
|
||||
_paletteInvalidated = true;
|
||||
update();
|
||||
|
||||
_x = snap(saturation / 255., 0., 1.);
|
||||
_y = 1. - snap(brightness / 255., 0., 1.);
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::setRGB(int red, int green, int blue) {
|
||||
setFromColor(QColor(red, green, blue));
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::setFromColor(QColor color) {
|
||||
setHSV(color.hsvHue(), color.hsvSaturation(), color.value());
|
||||
}
|
||||
|
||||
class EditColorBox::Slider : public TWidget {
|
||||
public:
|
||||
enum class Direction {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
};
|
||||
enum class Type {
|
||||
Hue,
|
||||
Opacity,
|
||||
};
|
||||
Slider(QWidget *parent, Direction direction, Type type, QColor color);
|
||||
|
||||
base::Observable<void> &changed() {
|
||||
return _changed;
|
||||
}
|
||||
float64 value() const {
|
||||
return _value;
|
||||
}
|
||||
void setValue(float64 value) {
|
||||
_value = snap(value, 0., 1.);
|
||||
update();
|
||||
}
|
||||
void setHSV(int hue, int saturation, int brightness);
|
||||
void setRGB(int red, int green, int blue);
|
||||
void setAlpha(int alpha);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
float64 valueFromColor(QColor color) const;
|
||||
float64 valueFromHue(int hue) const;
|
||||
bool isHorizontal() const {
|
||||
return (_direction == Direction::Horizontal);
|
||||
}
|
||||
void colorUpdated();
|
||||
void prepareMinSize();
|
||||
void generatePixmap();
|
||||
void updatePixmapFromMask();
|
||||
void updateCurrentPoint(QPoint localPosition);
|
||||
|
||||
Direction _direction = Direction::Horizontal;
|
||||
Type _type = Type::Hue;
|
||||
|
||||
QColor _color;
|
||||
float64 _value = 0;
|
||||
|
||||
QImage _mask;
|
||||
QPixmap _pixmap;
|
||||
QBrush _transparent;
|
||||
|
||||
bool _choosing = false;
|
||||
base::Observable<void> _changed;
|
||||
|
||||
};
|
||||
|
||||
EditColorBox::Slider::Slider(QWidget *parent, Direction direction, Type type, QColor color) : TWidget(parent)
|
||||
, _direction(direction)
|
||||
, _type(type)
|
||||
, _color(color.red(), color.green(), color.blue())
|
||||
, _value(valueFromColor(color))
|
||||
, _transparent((_type == Type::Hue) ? QBrush() : style::transparentPlaceholderBrush()) {
|
||||
prepareMinSize();
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::prepareMinSize() {
|
||||
auto minSize = st::colorSliderSkip + st::colorSliderWidth + st::colorSliderSkip;
|
||||
resize(minSize, minSize);
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
auto to = rect().marginsRemoved(QMargins(st::colorSliderSkip, st::colorSliderSkip, st::colorSliderSkip, st::colorSliderSkip));
|
||||
Ui::Shadow::paint(p, to, width(), st::defaultRoundShadow);
|
||||
if (_type == Type::Opacity) {
|
||||
p.fillRect(to, _transparent);
|
||||
}
|
||||
p.drawPixmap(to, _pixmap, _pixmap.rect());
|
||||
if (isHorizontal()) {
|
||||
auto x = st::colorSliderSkip + qRound(_value * to.width());
|
||||
st::colorSliderArrowTop.paint(p, x - st::colorSliderArrowTop.width() / 2, 0, width());
|
||||
st::colorSliderArrowBottom.paint(p, x - st::colorSliderArrowBottom.width() / 2, height() - st::colorSliderArrowBottom.height(), width());
|
||||
} else {
|
||||
auto y = st::colorSliderSkip + qRound(_value * to.height());
|
||||
st::colorSliderArrowLeft.paint(p, 0, y - st::colorSliderArrowLeft.height() / 2, width());
|
||||
st::colorSliderArrowRight.paint(p, width() - st::colorSliderArrowRight.width(), y - st::colorSliderArrowRight.height() / 2, width());
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::resizeEvent(QResizeEvent *e) {
|
||||
generatePixmap();
|
||||
update();
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::mousePressEvent(QMouseEvent *e) {
|
||||
_choosing = true;
|
||||
updateCurrentPoint(e->pos());
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_choosing) {
|
||||
updateCurrentPoint(e->pos());
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_choosing = false;
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::generatePixmap() {
|
||||
auto size = (isHorizontal() ? width() : height()) * cIntRetinaFactor();
|
||||
auto image = QImage(size, cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(cRetinaFactor());
|
||||
auto ints = reinterpret_cast<uint32*>(image.bits());
|
||||
auto intsPerLine = image.bytesPerLine() / sizeof(uint32);
|
||||
auto intsPerLineAdded = intsPerLine - size;
|
||||
|
||||
constexpr auto Large = 1024 * 1024;
|
||||
constexpr auto LargeBit = 20; // n / Large == (n >> LargeBit)
|
||||
auto part = Large / size;
|
||||
|
||||
if (_type == Type::Hue) {
|
||||
QColor color;
|
||||
for (auto x = 0; x != size; ++x) {
|
||||
color.setHsv(x * 360 / size, 255, 255);
|
||||
auto value = anim::getPremultiplied(color.toRgb());
|
||||
for (auto y = 0; y != cIntRetinaFactor(); ++y) {
|
||||
ints[y * intsPerLine] = value;
|
||||
}
|
||||
++ints;
|
||||
}
|
||||
if (!isHorizontal()) {
|
||||
image = std_::move(image).transformed(QTransform(0, -1, 1, 0, 0, 0));
|
||||
}
|
||||
_pixmap = App::pixmapFromImageInPlace(std_::move(image));
|
||||
} else {
|
||||
auto color = anim::shifted(QColor(255, 255, 255, 255));
|
||||
auto transparent = anim::shifted(QColor(255, 255, 255, 0));
|
||||
for (auto y = 0; y != cIntRetinaFactor(); ++y) {
|
||||
auto x_accumulated = 0;
|
||||
for (auto x = 0; x != size; ++x, x_accumulated += part) {
|
||||
auto x_ratio = x_accumulated >> (LargeBit - 8);
|
||||
// 0 <= x_accumulated < Large
|
||||
// 0 <= x_ratio < 256
|
||||
|
||||
*ints++ = anim::unshifted(color * x_ratio + transparent * (255 - x_ratio));
|
||||
}
|
||||
ints += intsPerLineAdded;
|
||||
}
|
||||
if (!isHorizontal()) {
|
||||
image = std_::move(image).transformed(QTransform(0, -1, 1, 0, 0, 0));
|
||||
}
|
||||
_mask = std_::move(image);
|
||||
updatePixmapFromMask();
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::setHSV(int hue, int saturation, int brightness) {
|
||||
if (_type == Type::Hue) {
|
||||
// hue == 360 converts to 0 if done in general way
|
||||
_value = valueFromHue(hue);
|
||||
update();
|
||||
} else {
|
||||
_color.setHsv(hue, saturation, brightness);
|
||||
colorUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::setRGB(int red, int green, int blue) {
|
||||
_color.setRgb(red, green, blue);
|
||||
colorUpdated();
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::colorUpdated() {
|
||||
if (_type == Type::Hue) {
|
||||
_value = valueFromColor(_color);
|
||||
} else if (!_mask.isNull()) {
|
||||
updatePixmapFromMask();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
float64 EditColorBox::Slider::valueFromColor(QColor color) const {
|
||||
return (_type == Type::Hue) ? valueFromHue(color.hsvHue()) : color.alphaF();
|
||||
}
|
||||
|
||||
float64 EditColorBox::Slider::valueFromHue(int hue) const {
|
||||
return (1. - snap(hue, 0, 360) / 360.);
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::setAlpha(int alpha) {
|
||||
if (_type == Type::Opacity) {
|
||||
_value = snap(alpha, 0, 255) / 255.;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::updatePixmapFromMask() {
|
||||
_pixmap = App::pixmapFromImageInPlace(style::colorizeImage(_mask, _color));
|
||||
}
|
||||
|
||||
void EditColorBox::Slider::updateCurrentPoint(QPoint localPosition) {
|
||||
auto coord = (isHorizontal() ? localPosition.x() : localPosition.y()) - st::colorSliderSkip;
|
||||
auto maximum = (isHorizontal() ? width() : height()) - 2 * st::colorSliderSkip;
|
||||
auto value = snap(coord, 0, maximum) / float64(maximum);
|
||||
if (_value != value) {
|
||||
_value = value;
|
||||
update();
|
||||
_changed.notify();
|
||||
}
|
||||
}
|
||||
|
||||
class EditColorBox::Field : public Ui::MaskedInputField {
|
||||
public:
|
||||
Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit, const QString &units = QString());
|
||||
|
||||
int value() const {
|
||||
return getLastText().toInt();
|
||||
}
|
||||
|
||||
void setTextWithFocus(const QString &text) {
|
||||
setText(text);
|
||||
if (hasFocus()) {
|
||||
selectAll();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) override;
|
||||
void paintAdditionalPlaceholder(Painter &p, TimeMs ms) override;
|
||||
|
||||
void wheelEvent(QWheelEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
private:
|
||||
void changeValue(int delta);
|
||||
|
||||
QString _placeholder, _units;
|
||||
int _limit = 0;
|
||||
int _digitLimit = 1;
|
||||
int _wheelDelta = 0;
|
||||
|
||||
};
|
||||
|
||||
EditColorBox::Field::Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit, const QString &units) : Ui::MaskedInputField(parent, st)
|
||||
, _placeholder(placeholder)
|
||||
, _units(units)
|
||||
, _limit(limit)
|
||||
, _digitLimit(QString::number(_limit).size()) {
|
||||
}
|
||||
|
||||
void EditColorBox::Field::correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) {
|
||||
QString newText;
|
||||
int oldPos(nowCursor), newPos(-1), oldLen(now.length());
|
||||
|
||||
newText.reserve(oldLen);
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
if (i == oldPos) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
|
||||
QChar ch(now[i]);
|
||||
if (ch.isDigit()) {
|
||||
newText += ch;
|
||||
}
|
||||
if (newText.size() >= _digitLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newPos < 0 || newPos > newText.size()) {
|
||||
newPos = newText.size();
|
||||
}
|
||||
if (newText.toInt() > _limit) {
|
||||
newText = QString::number(_limit);
|
||||
newPos = newText.size();
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(now);
|
||||
startPlaceholderAnimation();
|
||||
nowCursor = -1;
|
||||
}
|
||||
if (newPos != nowCursor) {
|
||||
nowCursor = newPos;
|
||||
setCursorPosition(nowCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Field::paintAdditionalPlaceholder(Painter &p, TimeMs ms) {
|
||||
p.setFont(_st.font);
|
||||
p.setPen(_st.placeholderFg);
|
||||
auto inner = QRect(_st.textMargins.right(), _st.textMargins.top(), width() - 2 * _st.textMargins.right(), height() - _st.textMargins.top() - _st.textMargins.bottom());
|
||||
p.drawText(inner, _placeholder, style::al_topleft);
|
||||
if (!_units.isEmpty()) {
|
||||
p.drawText(inner, _units, style::al_topright);
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Field::wheelEvent(QWheelEvent *e) {
|
||||
if (!hasFocus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto deltaX = e->angleDelta().x(), deltaY = e->angleDelta().y();
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
deltaY *= -1;
|
||||
} else {
|
||||
deltaX *= -1;
|
||||
}
|
||||
_wheelDelta += (qAbs(deltaX) > qAbs(deltaY)) ? deltaX : deltaY;
|
||||
|
||||
constexpr auto step = 5;
|
||||
if (auto delta = _wheelDelta / step) {
|
||||
_wheelDelta -= delta * step;
|
||||
changeValue(delta);
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Field::changeValue(int delta) {
|
||||
auto currentValue = value();
|
||||
auto newValue = snap(currentValue + delta, 0, _limit);
|
||||
if (newValue != currentValue) {
|
||||
setText(QString::number(newValue));
|
||||
setFocus();
|
||||
selectAll();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::Field::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Up) {
|
||||
changeValue(1);
|
||||
} else if (e->key() == Qt::Key_Down) {
|
||||
changeValue(-1);
|
||||
} else {
|
||||
MaskedInputField::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
class EditColorBox::ResultField : public Ui::MaskedInputField {
|
||||
public:
|
||||
ResultField(QWidget *parent, const style::InputField &st);
|
||||
|
||||
void setTextWithFocus(const QString &text) {
|
||||
setText(text);
|
||||
if (hasFocus()) {
|
||||
selectAll();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) override;
|
||||
void paintAdditionalPlaceholder(Painter &p, TimeMs ms) override;
|
||||
|
||||
};
|
||||
|
||||
EditColorBox::ResultField::ResultField(QWidget *parent, const style::InputField &st) : Ui::MaskedInputField(parent, st) {
|
||||
}
|
||||
|
||||
void EditColorBox::ResultField::correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) {
|
||||
QString newText;
|
||||
int oldPos(nowCursor), newPos(-1), oldLen(now.length());
|
||||
|
||||
newText.reserve(oldLen);
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
if (i == oldPos) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
|
||||
QChar ch(now[i]);
|
||||
auto code = ch.unicode();
|
||||
if ((code >= '0' && code <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
|
||||
newText += ch;
|
||||
}
|
||||
if (newText.size() >= 8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newPos < 0 || newPos > newText.size()) {
|
||||
newPos = newText.size();
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(now);
|
||||
startPlaceholderAnimation();
|
||||
nowCursor = -1;
|
||||
}
|
||||
if (newPos != nowCursor) {
|
||||
nowCursor = newPos;
|
||||
setCursorPosition(nowCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::ResultField::paintAdditionalPlaceholder(Painter &p, TimeMs ms) {
|
||||
p.setFont(_st.font);
|
||||
p.setPen(_st.placeholderFg);
|
||||
p.drawText(QRect(_st.textMargins.right(), _st.textMargins.top(), width(), height() - _st.textMargins.top() - _st.textMargins.bottom()), "#", style::al_topleft);
|
||||
}
|
||||
|
||||
EditColorBox::EditColorBox(QWidget*, const QString &title, QColor current) : BoxContent()
|
||||
, _title(title)
|
||||
, _picker(this, current)
|
||||
, _hueSlider(this, Slider::Direction::Vertical, Slider::Type::Hue, current)
|
||||
, _opacitySlider(this, Slider::Direction::Horizontal, Slider::Type::Opacity, current)
|
||||
, _hueField(this, st::colorValueInput, "H", 360, QString() + QChar(176)) // degree character
|
||||
, _saturationField(this, st::colorValueInput, "S", 100, "%")
|
||||
, _brightnessField(this, st::colorValueInput, "B", 100, "%")
|
||||
, _redField(this, st::colorValueInput, "R", 255)
|
||||
, _greenField(this, st::colorValueInput, "G", 255)
|
||||
, _blueField(this, st::colorValueInput, "B", 255)
|
||||
, _result(this, st::colorResultInput)
|
||||
, _transparent(style::transparentPlaceholderBrush())
|
||||
, _current(current)
|
||||
, _new(current) {
|
||||
}
|
||||
|
||||
void EditColorBox::prepare() {
|
||||
setTitle(_title);
|
||||
|
||||
connect(_hueField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
connect(_saturationField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
connect(_brightnessField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
connect(_redField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
connect(_greenField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
connect(_blueField, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
connect(_result, SIGNAL(changed()), this, SLOT(onFieldChanged()));
|
||||
|
||||
connect(_hueField, SIGNAL(submitted(bool)), this, SLOT(onFieldSubmitted()));
|
||||
connect(_saturationField, SIGNAL(submitted(bool)), this, SLOT(onFieldSubmitted()));
|
||||
connect(_brightnessField, SIGNAL(submitted(bool)), this, SLOT(onFieldSubmitted()));
|
||||
connect(_redField, SIGNAL(submitted(bool)), this, SLOT(onFieldSubmitted()));
|
||||
connect(_greenField, SIGNAL(submitted(bool)), this, SLOT(onFieldSubmitted()));
|
||||
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(); });
|
||||
|
||||
auto height = st::colorEditSkip + st::colorPickerSize + st::colorEditSkip + st::colorSliderWidth + st::colorEditSkip;
|
||||
setDimensions(st::colorEditWidth, height);
|
||||
|
||||
subscribe(_picker->changed(), [this] { updateFromControls(); });
|
||||
subscribe(_hueSlider->changed(), [this] { updateFromControls(); });
|
||||
subscribe(_opacitySlider->changed(), [this] { updateFromControls(); });
|
||||
updateFromControls();
|
||||
}
|
||||
|
||||
void EditColorBox::setInnerFocus() {
|
||||
_result->setFocus();
|
||||
_result->selectAll();
|
||||
}
|
||||
|
||||
void EditColorBox::onFieldChanged() {
|
||||
auto emitter = sender();
|
||||
auto checkHSVSender = [this, emitter](QObject *field) {
|
||||
if (emitter == field) {
|
||||
updateFromHSVFields();
|
||||
}
|
||||
};
|
||||
auto checkRGBSender = [this, emitter](QObject *field) {
|
||||
if (emitter == field) {
|
||||
updateFromRGBFields();
|
||||
}
|
||||
};
|
||||
checkHSVSender(_hueField);
|
||||
checkHSVSender(_saturationField);
|
||||
checkHSVSender(_brightnessField);
|
||||
checkRGBSender(_redField);
|
||||
checkRGBSender(_greenField);
|
||||
checkRGBSender(_blueField);
|
||||
if (emitter == _result) {
|
||||
updateFromResultField();
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::onFieldSubmitted() {
|
||||
Ui::MaskedInputField *fields[] = {
|
||||
_hueField,
|
||||
_saturationField,
|
||||
_brightnessField,
|
||||
_redField,
|
||||
_greenField,
|
||||
_blueField,
|
||||
_result
|
||||
};
|
||||
for (auto i = 0, count = int(base::array_size(fields)); i + 1 != count; ++i) {
|
||||
if (fields[i]->hasFocus()) {
|
||||
fields[i + 1]->setFocus();
|
||||
fields[i + 1]->selectAll();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_result->hasFocus()) {
|
||||
saveColor();
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::saveColor() {
|
||||
_cancelCallback = base::lambda<void()>();
|
||||
if (_saveCallback) {
|
||||
_saveCallback(_new.toRgb());
|
||||
}
|
||||
closeBox();
|
||||
}
|
||||
|
||||
void EditColorBox::updateHSVFields() {
|
||||
auto hue = qRound((1. - _hueSlider->value()) * 360);
|
||||
auto saturation = qRound(_picker->valueX() * 255);
|
||||
auto brightness = qRound((1. - _picker->valueY()) * 255);
|
||||
auto alpha = qRound(_opacitySlider->value() * 255);
|
||||
_hueField->setTextWithFocus(QString::number(hue));
|
||||
_saturationField->setTextWithFocus(QString::number(percentFromByte(saturation)));
|
||||
_brightnessField->setTextWithFocus(QString::number(percentFromByte(brightness)));
|
||||
}
|
||||
|
||||
void EditColorBox::updateRGBFields() {
|
||||
_redField->setTextWithFocus(QString::number(_new.red()));
|
||||
_greenField->setTextWithFocus(QString::number(_new.green()));
|
||||
_blueField->setTextWithFocus(QString::number(_new.blue()));
|
||||
}
|
||||
|
||||
void EditColorBox::updateResultField() {
|
||||
auto text = QString();
|
||||
auto addHex = [&text](int value) {
|
||||
if (value >= 0 && value <= 9) {
|
||||
text.append('0' + value);
|
||||
} else if (value >= 10 && value <= 15) {
|
||||
text.append('a' + (value - 10));
|
||||
}
|
||||
};
|
||||
auto addValue = [addHex](int value) {
|
||||
addHex(value / 16);
|
||||
addHex(value % 16);
|
||||
};
|
||||
addValue(_new.red());
|
||||
addValue(_new.green());
|
||||
addValue(_new.blue());
|
||||
if (_new.alpha() != 255) {
|
||||
addValue(_new.alpha());
|
||||
}
|
||||
_result->setTextWithFocus(text);
|
||||
}
|
||||
|
||||
void EditColorBox::resizeEvent(QResizeEvent *e) {
|
||||
auto fullwidth = _picker->width() + 2 * (st::colorEditSkip - st::colorSliderSkip) + _hueSlider->width() + st::colorSampleSize.width();
|
||||
auto left = (width() - fullwidth) / 2;
|
||||
_picker->moveToLeft(left, st::colorEditSkip);
|
||||
_hueSlider->setGeometryToLeft(_picker->x() + _picker->width() + st::colorEditSkip - st::colorSliderSkip, st::colorEditSkip - st::colorSliderSkip, _hueSlider->width(), st::colorPickerSize + 2 * st::colorSliderSkip);
|
||||
_opacitySlider->setGeometryToLeft(_picker->x() - st::colorSliderSkip, _picker->y() + _picker->height() + st::colorEditSkip - st::colorSliderSkip, _picker->width() + 2 * st::colorSliderSkip, _opacitySlider->height());
|
||||
auto fieldLeft = _hueSlider->x() + _hueSlider->width() - st::colorSliderSkip + st::colorEditSkip;
|
||||
auto fieldWidth = st::colorSampleSize.width();
|
||||
auto fieldHeight = _hueField->height();
|
||||
_newRect = QRect(fieldLeft, st::colorEditSkip, fieldWidth, st::colorSampleSize.height());
|
||||
_currentRect = _newRect.translated(0, st::colorSampleSize.height());
|
||||
_hueField->setGeometryToLeft(fieldLeft, _currentRect.y() + _currentRect.height() + st::colorFieldSkip, fieldWidth, fieldHeight);
|
||||
_saturationField->setGeometryToLeft(fieldLeft, _hueField->y() + _hueField->height(), fieldWidth, fieldHeight);
|
||||
_brightnessField->setGeometryToLeft(fieldLeft, _saturationField->y() + _saturationField->height(), fieldWidth, fieldHeight);
|
||||
_redField->setGeometryToLeft(fieldLeft, _brightnessField->y() + _brightnessField->height() + st::colorFieldSkip, fieldWidth, fieldHeight);
|
||||
_greenField->setGeometryToLeft(fieldLeft, _redField->y() + _redField->height(), fieldWidth, fieldHeight);
|
||||
_blueField->setGeometryToLeft(fieldLeft, _greenField->y() + _greenField->height(), fieldWidth, fieldHeight);
|
||||
_result->setGeometryToLeft(fieldLeft - (st::colorEditSkip + st::colorSliderWidth), _opacitySlider->y() + _opacitySlider->height() - st::colorSliderSkip - _result->height(), fieldWidth + (st::colorEditSkip + st::colorSliderWidth), fieldHeight);
|
||||
}
|
||||
|
||||
void EditColorBox::paintEvent(QPaintEvent *e) {
|
||||
BoxContent::paintEvent(e);
|
||||
|
||||
Painter p(this);
|
||||
Ui::Shadow::paint(p, _picker->geometry(), width(), st::defaultRoundShadow);
|
||||
|
||||
Ui::Shadow::paint(p, QRect(_newRect.x(), _newRect.y(), _newRect.width(), _newRect.height() + _currentRect.height()), width(), st::defaultRoundShadow);
|
||||
if (_new.alphaF() < 1.) {
|
||||
p.fillRect(myrtlrect(_newRect), _transparent);
|
||||
}
|
||||
p.fillRect(myrtlrect(_newRect), _new);
|
||||
if (_current.alphaF() < 1.) {
|
||||
p.fillRect(myrtlrect(_currentRect), _transparent);
|
||||
}
|
||||
p.fillRect(myrtlrect(_currentRect), _current);
|
||||
}
|
||||
|
||||
void EditColorBox::mousePressEvent(QMouseEvent *e) {
|
||||
if (myrtlrect(_currentRect).contains(e->pos())) {
|
||||
updateFromColor(_current);
|
||||
}
|
||||
}
|
||||
|
||||
void EditColorBox::updateFromColor(QColor color) {
|
||||
_new = color;
|
||||
updateControlsFromColor();
|
||||
updateRGBFields();
|
||||
updateHSVFields();
|
||||
updateResultField();
|
||||
update();
|
||||
}
|
||||
|
||||
void EditColorBox::updateFromControls() {
|
||||
auto hue = qRound((1. - _hueSlider->value()) * 360);
|
||||
auto saturation = qRound(_picker->valueX() * 255);
|
||||
auto brightness = qRound((1. - _picker->valueY()) * 255);
|
||||
auto alpha = qRound(_opacitySlider->value() * 255);
|
||||
setHSV(hue, saturation, brightness, alpha);
|
||||
updateHSVFields();
|
||||
updateControlsFromHSV(hue, saturation, brightness);
|
||||
}
|
||||
|
||||
void EditColorBox::updateFromHSVFields() {
|
||||
auto hue = _hueField->value();
|
||||
auto saturation = percentToByte(_saturationField->value());
|
||||
auto brightness = percentToByte(_brightnessField->value());
|
||||
auto alpha = qRound(_opacitySlider->value() * 255);
|
||||
setHSV(hue, saturation, brightness, alpha);
|
||||
updateControlsFromHSV(hue, saturation, brightness);
|
||||
}
|
||||
|
||||
void EditColorBox::updateFromRGBFields() {
|
||||
auto red = _redField->value();
|
||||
auto blue = _blueField->value();
|
||||
auto green = _greenField->value();
|
||||
auto alpha = qRound(_opacitySlider->value() * 255);
|
||||
setRGB(red, green, blue, alpha);
|
||||
updateResultField();
|
||||
}
|
||||
|
||||
void EditColorBox::updateFromResultField() {
|
||||
auto text = _result->getLastText();
|
||||
if (text.size() != 6 && text.size() != 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto fromHex = [](QChar hex) {
|
||||
auto code = hex.unicode();
|
||||
if (code >= 'A' && code <= 'F') {
|
||||
return (code - 'A' + 10);
|
||||
} else if (code >= 'a' && code <= 'f') {
|
||||
return (code - 'a' + 10);
|
||||
}
|
||||
return code - '0';
|
||||
};
|
||||
auto fromChars = [fromHex](QChar a, QChar b) {
|
||||
return fromHex(a) * 0x10 + fromHex(b);
|
||||
};
|
||||
auto red = fromChars(text[0], text[1]);
|
||||
auto green = fromChars(text[2], text[3]);
|
||||
auto blue = fromChars(text[4], text[5]);
|
||||
auto alpha = (text.size() == 8) ? fromChars(text[6], text[7]) : 255;
|
||||
setRGB(red, green, blue, alpha);
|
||||
updateRGBFields();
|
||||
}
|
||||
|
||||
void EditColorBox::updateControlsFromHSV(int hue, int saturation, int brightness) {
|
||||
_picker->setHSV(hue, saturation, brightness);
|
||||
_hueSlider->setHSV(hue, saturation, brightness);
|
||||
_opacitySlider->setHSV(hue, saturation, brightness);
|
||||
}
|
||||
|
||||
void EditColorBox::updateControlsFromColor() {
|
||||
auto red = _new.red();
|
||||
auto green = _new.green();
|
||||
auto blue = _new.blue();
|
||||
auto alpha = _new.alpha();
|
||||
_picker->setRGB(red, green, blue);
|
||||
_hueSlider->setRGB(red, green, blue);
|
||||
_opacitySlider->setRGB(red, green, blue);
|
||||
_opacitySlider->setAlpha(alpha);
|
||||
}
|
||||
|
||||
void EditColorBox::setHSV(int hue, int saturation, int value, int alpha) {
|
||||
_new.setHsv(hue, saturation, value, alpha);
|
||||
updateRGBFields();
|
||||
updateResultField();
|
||||
update();
|
||||
}
|
||||
|
||||
void EditColorBox::setRGB(int red, int green, int blue, int alpha) {
|
||||
_new.setRgb(red, green, blue, alpha);
|
||||
updateControlsFromColor();
|
||||
updateHSVFields();
|
||||
update();
|
||||
}
|
||||
115
Telegram/SourceFiles/boxes/editcolorbox.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
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/abstractbox.h"
|
||||
|
||||
class EditColorBox : public BoxContent {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditColorBox(QWidget*, const QString &title, QColor current = QColor(255, 255, 255));
|
||||
|
||||
void setSaveCallback(base::lambda<void(QColor)> &&callback) {
|
||||
_saveCallback = std_::move(callback);
|
||||
}
|
||||
|
||||
void setCancelCallback(base::lambda<void()> &&callback) {
|
||||
_cancelCallback = std_::move(callback);
|
||||
}
|
||||
|
||||
void showColor(QColor color) {
|
||||
updateFromColor(color);
|
||||
}
|
||||
|
||||
void closeHook() override {
|
||||
if (_cancelCallback) {
|
||||
_cancelCallback();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
|
||||
void setInnerFocus() override;
|
||||
|
||||
private slots:
|
||||
void onFieldChanged();
|
||||
void onFieldSubmitted();
|
||||
|
||||
private:
|
||||
void saveColor();
|
||||
|
||||
void updateFromColor(QColor color);
|
||||
void updateControlsFromColor();
|
||||
void updateControlsFromHSV(int hue, int saturation, int brightness);
|
||||
void updateHSVFields();
|
||||
void updateRGBFields();
|
||||
void updateResultField();
|
||||
void updateFromControls();
|
||||
void updateFromHSVFields();
|
||||
void updateFromRGBFields();
|
||||
void updateFromResultField();
|
||||
void setHSV(int hue, int saturation, int brightness, int alpha);
|
||||
void setRGB(int red, int green, int blue, int alpha);
|
||||
|
||||
int percentFromByte(int byte) {
|
||||
return snap(qRound(byte * 100 / 255.), 0, 100);
|
||||
}
|
||||
int percentToByte(int percent) {
|
||||
return snap(qRound(percent * 255 / 100.), 0, 255);
|
||||
}
|
||||
|
||||
class Picker;
|
||||
class Slider;
|
||||
class Field;
|
||||
class ResultField;
|
||||
|
||||
QString _title;
|
||||
|
||||
object_ptr<Picker> _picker;
|
||||
object_ptr<Slider> _hueSlider;
|
||||
object_ptr<Slider> _opacitySlider;
|
||||
|
||||
object_ptr<Field> _hueField;
|
||||
object_ptr<Field> _saturationField;
|
||||
object_ptr<Field> _brightnessField;
|
||||
object_ptr<Field> _redField;
|
||||
object_ptr<Field> _greenField;
|
||||
object_ptr<Field> _blueField;
|
||||
object_ptr<ResultField> _result;
|
||||
|
||||
QBrush _transparent;
|
||||
QColor _current;
|
||||
QColor _new;
|
||||
|
||||
QRect _currentRect;
|
||||
QRect _newRect;
|
||||
|
||||
base::lambda<void(QColor)> _saveCallback;
|
||||
base::lambda<void()> _cancelCallback;
|
||||
|
||||
};
|
||||
@@ -135,7 +135,7 @@ void EmojiBox::paintEvent(QPaintEvent *e) {
|
||||
int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2;
|
||||
for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) {
|
||||
if (j->emoji) {
|
||||
p.drawPixmap(QPoint(left + (st::emojiReplaceWidth - _esize) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2), App::emojiLarge(), QRect(j->emoji->x * _esize, j->emoji->y * _esize, _esize, _esize));
|
||||
p.drawPixmap(QPoint(left + (st::emojiReplaceWidth - (_esize / cIntRetinaFactor())) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2), App::emojiLarge(), QRect(j->emoji->x * _esize, j->emoji->y * _esize, _esize, _esize));
|
||||
}
|
||||
QRect trect(left, top + (st::emojiReplaceHeight + _blockHeight) / 2 - st::emojiTextFont->height, st::emojiReplaceWidth, st::emojiTextFont->height);
|
||||
p.drawText(trect, j->text, QTextOption(Qt::AlignHCenter | Qt::AlignTop));
|
||||
|
||||
@@ -330,7 +330,7 @@ void SessionsBox::Inner::onTerminateAll() {
|
||||
_terminateBox->closeBox();
|
||||
_terminateBox = nullptr;
|
||||
}
|
||||
// MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
|
||||
MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
|
||||
emit terminateAll();
|
||||
})), KeepOtherLayers);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "history/history_media_types.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "window/window_theme.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
|
||||
ShareBox::ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback)
|
||||
@@ -872,9 +872,7 @@ void shareGameScoreFromItem(HistoryItem *item) {
|
||||
|
||||
QApplication::clipboard()->setText(CreateInternalLinkHttps(bot->username + qsl("?game=") + shortName));
|
||||
|
||||
Ui::Toast::Config toast;
|
||||
toast.text = lang(lng_share_game_link_copied);
|
||||
Ui::Toast::Show(App::wnd(), toast);
|
||||
Ui::Toast::Show(lang(lng_share_game_link_copied));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -892,10 +890,7 @@ void shareGameScoreFromItem(HistoryItem *item) {
|
||||
}
|
||||
data->requests.remove(requestId);
|
||||
if (data->requests.empty()) {
|
||||
Ui::Toast::Config toast;
|
||||
toast.text = lang(lng_share_done);
|
||||
Ui::Toast::Show(App::wnd(), toast);
|
||||
|
||||
Ui::Toast::Show(lang(lng_share_done));
|
||||
Ui::hideLayer();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -860,7 +860,7 @@ void StickersBox::Inner::onUpdateSelected() {
|
||||
}
|
||||
_rows[_dragging]->yadd = anim::value(local.y() - _dragStart.y(), local.y() - _dragStart.y());
|
||||
_animStartTimes[_dragging] = 0;
|
||||
_a_shifting.step(getms(), true);
|
||||
_a_shifting.step(ms, true);
|
||||
|
||||
auto countDraggingScrollDelta = [this, local] {
|
||||
if (local.y() < _visibleTop) {
|
||||
|
||||
@@ -161,10 +161,7 @@ void UsernameBox::onChanged() {
|
||||
|
||||
void UsernameBox::onLinkClick() {
|
||||
Application::clipboard()->setText(CreateInternalLinkHttps(getName()));
|
||||
|
||||
Ui::Toast::Config toast;
|
||||
toast.text = lang(lng_username_copied);
|
||||
Ui::Toast::Show(App::wnd(), toast);
|
||||
Ui::Toast::Show(lang(lng_username_copied));
|
||||
}
|
||||
|
||||
void UsernameBox::onUpdateDone(const MTPUser &user) {
|
||||
|
||||
@@ -52,8 +52,6 @@ Token invalidToken() {
|
||||
return { Type::Invalid, QString(), ConstUtf8String(nullptr, 0), false };
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
BasicTokenizedFile::BasicTokenizedFile(const QString &filepath) : reader_(filepath) {
|
||||
@@ -152,6 +150,22 @@ Type BasicTokenizedFile::uniteLastTokens(Type type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
QString BasicTokenizedFile::getCurrentLineComment() {
|
||||
if (lineNumber_ > singleLineComments_.size()) {
|
||||
reader_.logError(kErrorInternal, lineNumber_) << "internal tokenizer error (line number larger than comments list size).";
|
||||
failed_ = true;
|
||||
return QString();
|
||||
}
|
||||
auto commentBytes = singleLineComments_[lineNumber_ - 1].mid(2); // Skip "//"
|
||||
CheckedUtf8String comment(commentBytes);
|
||||
if (!comment.isValid()) {
|
||||
reader_.logError(kErrorIncorrectUtf8String, lineNumber_) << "incorrect UTF-8 string in the comment.";
|
||||
failed_ = true;
|
||||
return QString();
|
||||
}
|
||||
return comment.toString().trimmed();
|
||||
}
|
||||
|
||||
Type BasicTokenizedFile::readNameOrNumber() {
|
||||
while (!reader_.atEnd()) {
|
||||
if (!isDigitChar(reader_.currentChar())) {
|
||||
|
||||
@@ -77,7 +77,11 @@ public:
|
||||
};
|
||||
|
||||
bool read() {
|
||||
return reader_.read();
|
||||
if (reader_.read()) {
|
||||
singleLineComments_ = reader_.singleLineComments();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool atEnd() const {
|
||||
return reader_.atEnd();
|
||||
@@ -90,6 +94,8 @@ public:
|
||||
return failed_;
|
||||
}
|
||||
|
||||
QString getCurrentLineComment();
|
||||
|
||||
// Log error to std::cerr with 'code' at the current position in file.
|
||||
LogStream logError(int code) const;
|
||||
LogStream logErrorUnexpectedToken() const;
|
||||
@@ -124,6 +130,7 @@ private:
|
||||
int currentToken_ = 0;
|
||||
int lineNumber_ = 1;
|
||||
bool failed_ = false;
|
||||
QVector<QByteArray> singleLineComments_;
|
||||
|
||||
// Where the last (currently read) token has started.
|
||||
const char *tokenStart_ = nullptr;
|
||||
|
||||
@@ -86,10 +86,17 @@ bool CleanFile::read() {
|
||||
offset = ch;
|
||||
}
|
||||
};
|
||||
auto feedComment = [this, &offset, end](const char *ch) {
|
||||
|
||||
auto lineNumber = 0;
|
||||
auto feedComment = [this, &offset, end, &lineNumber](const char *ch, bool save = false) {
|
||||
if (ch > offset) {
|
||||
// comments_.push_back({ content_.size(), QByteArray(offset, ch - offset) });
|
||||
if (result_.isEmpty()) result_.reserve(end - offset - 2);
|
||||
if (save) {
|
||||
singleLineComments_.resize(lineNumber + 1);
|
||||
singleLineComments_[lineNumber] = QByteArray(offset, ch - offset);
|
||||
}
|
||||
if (result_.isEmpty()) {
|
||||
result_.reserve(end - offset - 2);
|
||||
}
|
||||
result_.append(' ');
|
||||
offset = ch;
|
||||
}
|
||||
@@ -105,6 +112,9 @@ bool CleanFile::read() {
|
||||
}
|
||||
}
|
||||
if (insideString) {
|
||||
if (currentChar == '\n') {
|
||||
++lineNumber;
|
||||
}
|
||||
++ch;
|
||||
continue;
|
||||
}
|
||||
@@ -114,12 +124,14 @@ bool CleanFile::read() {
|
||||
insideComment = InsideComment::SingleLine;
|
||||
ch += 2;
|
||||
} else if (insideComment == InsideComment::SingleLine && currentChar == '\r' && nextChar == '\n') {
|
||||
feedComment(ch);
|
||||
feedComment(ch, true);
|
||||
ch += 2;
|
||||
++lineNumber;
|
||||
insideComment = InsideComment::None;
|
||||
} else if (insideComment == InsideComment::SingleLine && currentChar == '\n') {
|
||||
feedComment(ch);
|
||||
feedComment(ch, true);
|
||||
++ch;
|
||||
++lineNumber;
|
||||
insideComment = InsideComment::None;
|
||||
} else if (insideComment == InsideComment::None && currentChar == '/' && nextChar == '*') {
|
||||
feedContent(ch);
|
||||
@@ -132,15 +144,21 @@ bool CleanFile::read() {
|
||||
} else if (insideComment == InsideComment::MultiLine && currentChar == '\r' && nextChar == '\n') {
|
||||
feedComment(ch);
|
||||
ch += 2;
|
||||
++lineNumber;
|
||||
feedContent(ch);
|
||||
} else if (insideComment == InsideComment::MultiLine && currentChar == '\n') {
|
||||
feedComment(ch);
|
||||
++ch;
|
||||
++lineNumber;
|
||||
feedContent(ch);
|
||||
} else {
|
||||
if (currentChar == '\n') {
|
||||
++lineNumber;
|
||||
}
|
||||
++ch;
|
||||
}
|
||||
}
|
||||
singleLineComments_.resize(lineNumber + 1);
|
||||
|
||||
if (insideComment == InsideComment::MultiLine) {
|
||||
common::logError(kErrorUnexpectedEndOfFile, filepath_);
|
||||
@@ -156,6 +174,10 @@ bool CleanFile::read() {
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<QByteArray> CleanFile::singleLineComments() const {
|
||||
return singleLineComments_;
|
||||
}
|
||||
|
||||
LogStream CleanFile::logError(int code, int line) const {
|
||||
return common::logError(code, filepath_, line);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
CleanFile &operator=(const CleanFile &other) = delete;
|
||||
|
||||
bool read();
|
||||
QVector<QByteArray> singleLineComments() const;
|
||||
|
||||
const char *data() const {
|
||||
return result_.constData();
|
||||
@@ -55,11 +56,8 @@ private:
|
||||
QString filepath_;
|
||||
QByteArray content_, result_;
|
||||
bool read_;
|
||||
//struct Comment {
|
||||
// int offset;
|
||||
// QByteArray content;
|
||||
//};
|
||||
//QVector<Comment> comments_;
|
||||
|
||||
QVector<QByteArray> singleLineComments_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ public:
|
||||
return (end_ - pos_);
|
||||
}
|
||||
|
||||
QVector<QByteArray> singleLineComments() const {
|
||||
return file_.singleLineComments();
|
||||
}
|
||||
|
||||
// Log error to std::cerr with 'code' at line number 'line' in data().
|
||||
LogStream logError(int code, int line) const {
|
||||
return std::forward<LogStream>(file_.logError(code, line));
|
||||
|
||||
@@ -106,12 +106,13 @@ char hexFirstChar(char ch) {
|
||||
return hexChar((*reinterpret_cast<uchar*>(&ch)) >> 4);
|
||||
}
|
||||
|
||||
QString stringToEncodedString(const std::string &str) {
|
||||
QString stringToEncodedString(const QString &str) {
|
||||
QString result, lineBreak = "\\\n";
|
||||
result.reserve(str.size() * 8);
|
||||
bool writingHexEscapedCharacters = false, startOnNewLine = false;
|
||||
int lastCutSize = 0;
|
||||
for (uchar ch : str) {
|
||||
auto utf = str.toUtf8();
|
||||
for (auto ch : utf) {
|
||||
if (result.size() - lastCutSize > 80) {
|
||||
startOnNewLine = true;
|
||||
result.append(lineBreak);
|
||||
@@ -140,6 +141,10 @@ QString stringToEncodedString(const std::string &str) {
|
||||
return '"' + (startOnNewLine ? lineBreak : QString()) + result + '"';
|
||||
}
|
||||
|
||||
QString stringToEncodedString(const std::string &str) {
|
||||
return stringToEncodedString(QString::fromStdString(str));
|
||||
}
|
||||
|
||||
QString stringToBinaryArray(const std::string &str) {
|
||||
QStringList rows, chars;
|
||||
chars.reserve(13);
|
||||
@@ -334,7 +339,7 @@ QString Generator::valueAssignmentCode(structure::Value value) const {
|
||||
case Tag::Int: return QString("%1").arg(value.Int());
|
||||
case Tag::Double: return QString("%1").arg(value.Double());
|
||||
case Tag::Pixels: return pxValueName(value.Int());
|
||||
case Tag::String: return QString("qsl(%1)").arg(stringToEncodedString(value.String()));
|
||||
case Tag::String: return QString("QString::fromUtf8(%1)").arg(stringToEncodedString(value.String()));
|
||||
case Tag::Color: {
|
||||
auto v(value.Color());
|
||||
if (v.red == v.green && v.red == v.blue && v.red == 0 && v.alpha == 255) {
|
||||
@@ -441,8 +446,15 @@ public:\n\
|
||||
\n\
|
||||
QByteArray save() const;\n\
|
||||
bool load(const QByteArray &cache);\n\
|
||||
bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
|
||||
bool setColor(QLatin1String name, QLatin1String from);\n\
|
||||
\n\
|
||||
enum class SetResult {\n\
|
||||
Ok,\n\
|
||||
KeyNotFound,\n\
|
||||
ValueNotFound,\n\
|
||||
Duplicate,\n\
|
||||
};\n\
|
||||
SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
|
||||
SetResult setColor(QLatin1String name, QLatin1String from);\n\
|
||||
void reset() {\n\
|
||||
clear();\n\
|
||||
finalize();\n\
|
||||
@@ -564,12 +576,20 @@ namespace main_palette {\n\
|
||||
\n\
|
||||
QByteArray save();\n\
|
||||
bool load(const QByteArray &cache);\n\
|
||||
bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
|
||||
bool setColor(QLatin1String name, QLatin1String from);\n\
|
||||
palette::SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
|
||||
palette::SetResult setColor(QLatin1String name, QLatin1String from);\n\
|
||||
void apply(const palette &other);\n\
|
||||
void reset();\n\
|
||||
int indexOfColor(color c);\n\
|
||||
\n\
|
||||
struct row {\n\
|
||||
\tQLatin1String name;\n\
|
||||
\tQLatin1String value;\n\
|
||||
\tQLatin1String fallback;\n\
|
||||
\tQLatin1String description;\n\
|
||||
};\n\
|
||||
QList<row> data();\n\
|
||||
\n\
|
||||
} // namespace main_palette\n";
|
||||
|
||||
return true;
|
||||
@@ -739,10 +759,17 @@ void palette::finalize() {\n\
|
||||
\n\
|
||||
compute(0, -1, { 255, 255, 255, 0}); // special color\n";
|
||||
|
||||
QList<structure::FullName> names;
|
||||
module_.enumVariables([this, &names](const Variable &variable) -> bool {
|
||||
names.push_back(variable.name);
|
||||
return true;
|
||||
});
|
||||
|
||||
QString dataRows;
|
||||
int indexInPalette = 1;
|
||||
QByteArray checksumString;
|
||||
checksumString.append("&transparent:{ 255, 255, 255, 0 }");
|
||||
bool result = module_.enumVariables([this, &indexInPalette, &checksumString](const Variable &variable) -> bool {
|
||||
auto result = module_.enumVariables([this, &indexInPalette, &checksumString, &dataRows, &names](const Variable &variable) -> bool {
|
||||
auto name = variable.name.back();
|
||||
auto index = indexInPalette++;
|
||||
paletteIndices_[name] = index;
|
||||
@@ -754,8 +781,27 @@ void palette::finalize() {\n\
|
||||
auto assignment = QString("{ %1, %2, %3, %4 }").arg(color.red).arg(color.green).arg(color.blue).arg(color.alpha);
|
||||
source_->stream() << "\tcompute(" << index << ", " << fallbackIndex << ", " << assignment << ");\n";
|
||||
checksumString.append('&' + name + ':' + assignment);
|
||||
|
||||
auto isCopy = !variable.value.copyOf().isEmpty();
|
||||
auto colorString = paletteColorValue(color);
|
||||
auto fallbackName = QString();
|
||||
if (fallbackIndex > 0) {
|
||||
auto fallbackVariable = module_.findVariableInModule(names[fallbackIndex - 1], module_);
|
||||
if (fallbackVariable && fallbackVariable->value.type().tag == structure::TypeTag::Color) {
|
||||
fallbackName = fallbackVariable->name.back();
|
||||
}
|
||||
}
|
||||
auto value = isCopy ? fallbackName : '#' + colorString;
|
||||
if (value.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dataRows.append("\tresult.push_back({ qstr(\"" + name + "\"), qstr(\"" + value + "\"), qstr(\"" + (isCopy ? QString() : fallbackName) + "\"), qstr(" + stringToEncodedString(variable.description.toStdString()) + ") });\n");
|
||||
return true;
|
||||
});
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
auto count = indexInPalette;
|
||||
auto checksum = hashCrc32(checksumString.constData(), checksumString.size());
|
||||
|
||||
@@ -854,23 +900,25 @@ bool palette::load(const QByteArray &cache) {\n\
|
||||
return true;\n\
|
||||
}\n\
|
||||
\n\
|
||||
bool palette::setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\
|
||||
auto index = getPaletteIndex(name);\n\
|
||||
if (index >= 0) {\n\
|
||||
setData(index, { r, g, b, a });\n\
|
||||
return true;\n\
|
||||
}\n\
|
||||
return false;\n\
|
||||
palette::SetResult palette::setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\
|
||||
auto nameIndex = getPaletteIndex(name);\n\
|
||||
if (nameIndex < 0) return SetResult::KeyNotFound;\n\
|
||||
auto duplicate = (_status[nameIndex] != Status::Initial);\n\
|
||||
\n\
|
||||
setData(nameIndex, { r, g, b, a });\n\
|
||||
return duplicate ? SetResult::Duplicate : SetResult::Ok;\n\
|
||||
}\n\
|
||||
\n\
|
||||
bool palette::setColor(QLatin1String name, QLatin1String from) {\n\
|
||||
palette::SetResult palette::setColor(QLatin1String name, QLatin1String from) {\n\
|
||||
auto nameIndex = getPaletteIndex(name);\n\
|
||||
if (nameIndex < 0) return SetResult::KeyNotFound;\n\
|
||||
auto duplicate = (_status[nameIndex] != Status::Initial);\n\
|
||||
\n\
|
||||
auto fromIndex = getPaletteIndex(from);\n\
|
||||
if (nameIndex >= 0 && fromIndex >= 0 && _status[fromIndex] == Status::Loaded) {\n\
|
||||
setData(nameIndex, *data(fromIndex));\n\
|
||||
return true;\n\
|
||||
}\n\
|
||||
return false;\n\
|
||||
if (fromIndex < 0 || _status[fromIndex] != Status::Loaded) return SetResult::ValueNotFound;\n\
|
||||
\n\
|
||||
setData(nameIndex, *data(fromIndex));\n\
|
||||
return duplicate ? SetResult::Duplicate : SetResult::Ok;\n\
|
||||
}\n\
|
||||
\n\
|
||||
namespace main_palette {\n\
|
||||
@@ -887,11 +935,11 @@ bool load(const QByteArray &cache) {\n\
|
||||
return false;\n\
|
||||
}\n\
|
||||
\n\
|
||||
bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\
|
||||
palette::SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\
|
||||
return _palette.setColor(name, r, g, b, a);\n\
|
||||
}\n\
|
||||
\n\
|
||||
bool setColor(QLatin1String name, QLatin1String from) {\n\
|
||||
palette::SetResult setColor(QLatin1String name, QLatin1String from) {\n\
|
||||
return _palette.setColor(name, from);\n\
|
||||
}\n\
|
||||
\n\
|
||||
@@ -909,6 +957,14 @@ int indexOfColor(color c) {\n\
|
||||
return _palette.indexOfColor(c);\n\
|
||||
}\n\
|
||||
\n\
|
||||
QList<row> data() {\n\
|
||||
auto result = QList<row>();\n\
|
||||
result.reserve(" << count << ");\n\
|
||||
\n\
|
||||
" << dataRows << "\n\
|
||||
return result;\n\
|
||||
}\n\
|
||||
\n\
|
||||
} // namespace main_palette\n\
|
||||
\n";
|
||||
|
||||
@@ -1208,91 +1264,5 @@ bool Generator::collectUniqueValues() {
|
||||
return module_.enumVariables(collector);
|
||||
}
|
||||
|
||||
bool Generator::writeSampleTheme(const QString &filepath) {
|
||||
QByteArray content;
|
||||
QTextStream stream(&content);
|
||||
|
||||
stream << "\
|
||||
//\n\
|
||||
// This is a sample Telegram Desktop theme file.\n\
|
||||
// It was generated from the 'colors.palette' style file.\n\
|
||||
//\n\
|
||||
// To create a theme with a background image included you should\n\
|
||||
// put two files in a .zip archive:\n\
|
||||
//\n\
|
||||
// First one is the color scheme like the one you're viewing\n\
|
||||
// right now, this file should be named 'colors.tdesktop-theme'.\n\
|
||||
//\n\
|
||||
// Second one should be the background image and it can be named\n\
|
||||
// 'background.jpg', 'background.png', 'tiled.jpg' or 'tiled.png'.\n\
|
||||
// You should name it 'background' (if you'd like it not to be tiled),\n\
|
||||
// or it can be named 'tiled' (if you'd like it to be tiled).\n\
|
||||
//\n\
|
||||
// After that you need to change the extension of your .zip archive\n\
|
||||
// to 'tdesktop-theme', so you'll have:\n\
|
||||
//\n\
|
||||
// mytheme.tdesktop-theme\n\
|
||||
// |-colors.tdesktop-theme\n\
|
||||
// |-background.jpg (or tiled.jpg, background.png, tiled.png)\n\
|
||||
//\n\n";
|
||||
|
||||
QList<structure::FullName> names;
|
||||
module_.enumVariables([this, &names](const Variable &variable) -> bool {
|
||||
names.push_back(variable.name);
|
||||
return true;
|
||||
});
|
||||
bool result = module_.enumVariables([this, &names, &stream](const Variable &variable) -> bool {
|
||||
auto name = variable.name.back();
|
||||
if (variable.value.type().tag != structure::TypeTag::Color) {
|
||||
return false;
|
||||
}
|
||||
auto color = variable.value.Color();
|
||||
//color.red = uchar(rand() % 256);
|
||||
//color.green = uchar(rand() % 256);
|
||||
//color.blue = uchar(rand() % 256);
|
||||
//auto fallbackIndex = -1;
|
||||
auto fallbackIndex = paletteIndices_.value(colorFallbackName(variable.value), -1);
|
||||
auto colorString = paletteColorValue(color);
|
||||
if (fallbackIndex >= 0) {
|
||||
auto fallbackVariable = module_.findVariableInModule(names[fallbackIndex - 1], module_);
|
||||
if (!fallbackVariable || fallbackVariable->value.type().tag != structure::TypeTag::Color) {
|
||||
return false;
|
||||
}
|
||||
auto fallbackName = fallbackVariable->name.back();
|
||||
auto fallbackColor = fallbackVariable->value.Color();
|
||||
if (colorString == paletteColorValue(fallbackColor)) {
|
||||
stream << name << ": " << fallbackName << ";\n";
|
||||
} else {
|
||||
stream << name << ": #" << colorString << "; // " << fallbackName << ";\n";
|
||||
}
|
||||
} else {
|
||||
stream << name << ": #" << colorString << ";\n";
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
stream.flush();
|
||||
|
||||
QFile file(filepath);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
if (file.readAll() == content) {
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
return false;
|
||||
}
|
||||
if (file.write(content) != content.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
} // namespace codegen
|
||||
|
||||
@@ -40,7 +40,6 @@ public:
|
||||
|
||||
bool writeHeader();
|
||||
bool writeSource();
|
||||
bool writeSampleTheme(const QString &filepath);
|
||||
|
||||
private:
|
||||
QString typeToString(structure::Type type) const;
|
||||
|
||||
@@ -261,6 +261,7 @@ structure::Variable ParsedFile::readVariable(const QString &name) {
|
||||
}
|
||||
if (value.type().tag != structure::TypeTag::Struct || !value.copyOf().empty()) {
|
||||
assertNextToken(BasicType::Semicolon);
|
||||
result.description = file_.getCurrentLineComment();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -81,10 +81,6 @@ bool Processor::write(const structure::Module &module) const {
|
||||
if (!generator.writeSource()) {
|
||||
return false;
|
||||
}
|
||||
auto themePath = srcFile.absoluteDir().absolutePath() + "/default.tdesktop-theme";
|
||||
if (options_.isPalette && !generator.writeSampleTheme(themePath)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -198,6 +198,7 @@ private:
|
||||
struct Variable {
|
||||
FullName name;
|
||||
Value value;
|
||||
QString description;
|
||||
|
||||
explicit operator bool() const {
|
||||
return !name.isEmpty();
|
||||
|
||||
@@ -97,23 +97,11 @@ enum {
|
||||
MediaOverviewStartPerPage = 5,
|
||||
MediaOverviewPreloadCount = 4,
|
||||
|
||||
AudioSimultaneousLimit = 4,
|
||||
AudioCheckPositionTimeout = 100, // 100ms per check audio pos
|
||||
AudioCheckPositionDelta = 2400, // update position called each 2400 samples
|
||||
AudioFadeTimeout = 7, // 7ms
|
||||
AudioFadeDuration = 500,
|
||||
AudioVoiceMsgSkip = 400, // 200ms
|
||||
AudioVoiceMsgFade = 300, // 300ms
|
||||
AudioPreloadSamples = 2 * 48000, // preload next part if less than 5 seconds remains
|
||||
AudioVoiceMsgFrequency = 48000, // 48 kHz
|
||||
AudioVoiceMsgMaxLength = 100 * 60, // 100 minutes
|
||||
AudioVoiceMsgUpdateView = 100, // 100ms
|
||||
AudioVoiceMsgChannels = 2, // stereo
|
||||
AudioVoiceMsgBufferSize = 256 * 1024, // 256 Kb buffers (1.3 - 3.0 secs)
|
||||
AudioVoiceMsgInMemory = 2 * 1024 * 1024, // 2 Mb audio is hold in memory and auto loaded
|
||||
AudioPauseDeviceTimeout = 3000, // pause in 3 secs after playing is over
|
||||
|
||||
WaveformSamplesCount = 100,
|
||||
|
||||
StickerInMemory = 2 * 1024 * 1024, // 2 Mb stickers hold in memory, auto loaded and displayed inline
|
||||
StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker
|
||||
|
||||
@@ -39,8 +39,8 @@ bool ClickHandler::setActive(const ClickHandlerPtr &p, ClickHandlerHost *host) {
|
||||
// other pressed click handler currently, if there is
|
||||
// this method will be called when it is unpressed
|
||||
if (_active && *_active) {
|
||||
bool emitClickHandlerActiveChanged = (!_pressed || !*_pressed || *_pressed == *_active);
|
||||
ClickHandlerPtr wasactive = *_active;
|
||||
auto emitClickHandlerActiveChanged = (!_pressed || !*_pressed || *_pressed == *_active);
|
||||
auto wasactive = *_active;
|
||||
(*_active).clear();
|
||||
if (_activeHost) {
|
||||
if (emitClickHandlerActiveChanged) {
|
||||
|
||||
@@ -32,7 +32,6 @@ enum ExpandLinksMode {
|
||||
|
||||
class ClickHandlerHost {
|
||||
protected:
|
||||
|
||||
virtual void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||
}
|
||||
virtual void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
|
||||
|
||||
@@ -940,6 +940,7 @@ QStringList MimeType::globPatterns() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return QStringList(qsl("*.webp"));
|
||||
case Known::TDesktopTheme: return QStringList(qsl("*.tdesktop-theme"));
|
||||
case Known::TDesktopPalette: return QStringList(qsl("*.tdesktop-palette"));
|
||||
default: break;
|
||||
}
|
||||
return _typeStruct.globPatterns();
|
||||
@@ -948,6 +949,7 @@ QString MimeType::filterString() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return qsl("WebP image (*.webp)");
|
||||
case Known::TDesktopTheme: return qsl("Theme files (*.tdesktop-theme)");
|
||||
case Known::TDesktopPalette: return qsl("Palette files (*.tdesktop-palette)");
|
||||
default: break;
|
||||
}
|
||||
return _typeStruct.filterString();
|
||||
@@ -956,6 +958,7 @@ QString MimeType::name() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return qsl("image/webp");
|
||||
case Known::TDesktopTheme: return qsl("application/x-tdesktop-theme");
|
||||
case Known::TDesktopPalette: return qsl("application/x-tdesktop-palette");
|
||||
default: break;
|
||||
}
|
||||
return _typeStruct.name();
|
||||
@@ -966,17 +969,22 @@ MimeType mimeTypeForName(const QString &mime) {
|
||||
return MimeType(MimeType::Known::WebP);
|
||||
} else if (mime == qsl("application/x-tdesktop-theme")) {
|
||||
return MimeType(MimeType::Known::TDesktopTheme);
|
||||
} else if (mime == qsl("application/x-tdesktop-palette")) {
|
||||
return MimeType(MimeType::Known::TDesktopPalette);
|
||||
}
|
||||
return MimeType(QMimeDatabase().mimeTypeForName(mime));
|
||||
}
|
||||
|
||||
MimeType mimeTypeForFile(const QFileInfo &file) {
|
||||
QString path = file.absoluteFilePath();
|
||||
if (path.endsWith(qsl(".webp"), Qt::CaseInsensitive)) {
|
||||
if (path.endsWith(qstr(".webp"), Qt::CaseInsensitive)) {
|
||||
return MimeType(MimeType::Known::WebP);
|
||||
} else if (path.endsWith(qsl(".tdesktop-theme"), Qt::CaseInsensitive)) {
|
||||
} else if (path.endsWith(qstr(".tdesktop-theme"), Qt::CaseInsensitive)) {
|
||||
return MimeType(MimeType::Known::TDesktopTheme);
|
||||
} else if (path.endsWith(qstr(".tdesktop-palette"), Qt::CaseInsensitive)) {
|
||||
return MimeType(MimeType::Known::TDesktopPalette);
|
||||
}
|
||||
|
||||
{
|
||||
QFile f(path);
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
|
||||
@@ -432,6 +432,7 @@ public:
|
||||
enum class Known {
|
||||
Unknown,
|
||||
TDesktopTheme,
|
||||
TDesktopPalette,
|
||||
WebP,
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#define BETA_VERSION_MACRO (0ULL)
|
||||
|
||||
constexpr int AppVersion = 1000002;
|
||||
constexpr str_const AppVersionStr = "1.0.2";
|
||||
constexpr bool AppAlphaVersion = false;
|
||||
constexpr int AppVersion = 1000008;
|
||||
constexpr str_const AppVersionStr = "1.0.8";
|
||||
constexpr bool AppAlphaVersion = true;
|
||||
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;
|
||||
|
||||
@@ -81,6 +81,25 @@ void IndexedList::moveToTop(PeerData *peer) {
|
||||
}
|
||||
}
|
||||
|
||||
void IndexedList::movePinned(Row *row, int deltaSign) {
|
||||
auto swapPinnedIndexWith = find(row);
|
||||
t_assert(swapPinnedIndexWith != cend());
|
||||
if (deltaSign > 0) {
|
||||
++swapPinnedIndexWith;
|
||||
} else {
|
||||
t_assert(swapPinnedIndexWith != cbegin());
|
||||
--swapPinnedIndexWith;
|
||||
}
|
||||
auto history1 = row->history();
|
||||
auto history2 = (*swapPinnedIndexWith)->history();
|
||||
t_assert(history1->isPinnedDialog());
|
||||
t_assert(history2->isPinnedDialog());
|
||||
auto index1 = history1->getPinnedIndex();
|
||||
auto index2 = history2->getPinnedIndex();
|
||||
history1->setPinnedIndex(index2);
|
||||
history2->setPinnedIndex(index1);
|
||||
}
|
||||
|
||||
void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||
t_assert(_sortMode != SortMode::Date);
|
||||
if (_sortMode == SortMode::Name) {
|
||||
|
||||
@@ -36,6 +36,9 @@ public:
|
||||
void adjustByPos(const RowsByLetter &links);
|
||||
void moveToTop(PeerData *peer);
|
||||
|
||||
// row must belong to this indexed list all().
|
||||
void movePinned(Row *row, int deltaSign);
|
||||
|
||||
// For sortMode != SortMode::Date
|
||||
void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
|
||||
|
||||
|
||||