mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-16 08:19:23 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
7f07093eb0
@ -56,3 +56,10 @@ http_file(
|
|||||||
urls = ["https://github.com/Kitware/CMake/releases/download/v3.19.2/cmake-3.19.2-macos-universal.tar.gz"],
|
urls = ["https://github.com/Kitware/CMake/releases/download/v3.19.2/cmake-3.19.2-macos-universal.tar.gz"],
|
||||||
sha256 = "50afa2cb66bea6a0314ef28034f3ff1647325e30cf5940f97906a56fd9640bd8",
|
sha256 = "50afa2cb66bea6a0314ef28034f3ff1647325e30cf5940f97906a56fd9640bd8",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "appcenter_sdk",
|
||||||
|
urls = ["https://github.com/microsoft/appcenter-sdk-apple/releases/download/4.1.1/AppCenter-SDK-Apple-4.1.1.zip"],
|
||||||
|
sha256 = "032907801dc7784744a1ca8fd40d3eecc34a2e27a93a4b3993f617cca204a9f3",
|
||||||
|
build_file = "@//third-party/AppCenter:AppCenter.BUILD",
|
||||||
|
)
|
||||||
|
@ -3,84 +3,11 @@
|
|||||||
set -e
|
set -e
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
API_HOST="https://api.appcenter.ms"
|
|
||||||
IPA_PATH="build/artifacts/Telegram.ipa"
|
IPA_PATH="build/artifacts/Telegram.ipa"
|
||||||
DSYM_PATH="build/artifacts/Telegram.DSYMs.zip"
|
DSYM_PATH="build/artifacts/Telegram.DSYMs.zip"
|
||||||
|
|
||||||
upload_ipa() {
|
|
||||||
GROUP_DATA=$(curl \
|
|
||||||
-X GET \
|
|
||||||
--header "X-API-Token: $API_TOKEN" \
|
|
||||||
"$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/distribution_groups/Internal" \
|
|
||||||
)
|
|
||||||
|
|
||||||
GROUP_ID=$(echo "$GROUP_DATA" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["id"];')
|
|
||||||
|
|
||||||
UPLOAD_TOKEN=$(curl \
|
|
||||||
-X POST \
|
|
||||||
--header "Content-Type: application/json" \
|
|
||||||
--header "Accept: application/json" \
|
|
||||||
--header "X-API-Token: $API_TOKEN" \
|
|
||||||
"$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/release_uploads" \
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
UPLOAD_URL=$(echo "$UPLOAD_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["upload_url"];')
|
|
||||||
UPLOAD_ID=$(echo "$UPLOAD_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["upload_id"];')
|
|
||||||
|
|
||||||
curl --progress-bar -F "ipa=@${IPA_PATH}" "$UPLOAD_URL"
|
|
||||||
|
|
||||||
RELEASE_TOKEN=$(curl \
|
|
||||||
-X PATCH \
|
|
||||||
--header "Content-Type: application/json" \
|
|
||||||
--header "Accept: application/json" \
|
|
||||||
--header "X-API-Token: $API_TOKEN" \
|
|
||||||
-d '{ "status": "committed" }' \
|
|
||||||
"$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/release_uploads/$UPLOAD_ID" \
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
RELEASE_URL=$(echo "$RELEASE_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["release_url"];')
|
|
||||||
RELEASE_ID=$(echo "$RELEASE_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["release_id"];')
|
|
||||||
|
|
||||||
curl \
|
|
||||||
-X POST \
|
|
||||||
--header "Content-Type: application/json" \
|
|
||||||
--header "Accept: application/json" \
|
|
||||||
--header "X-API-Token: $API_TOKEN" \
|
|
||||||
-d "{ \"id\": \"$GROUP_ID\", \"mandatory_update\": false, \"notify_testers\": false }" \
|
|
||||||
"$API_HOST/$RELEASE_URL/groups"
|
|
||||||
}
|
|
||||||
|
|
||||||
upload_dsym() {
|
|
||||||
UPLOAD_DSYM_DATA=$(curl \
|
|
||||||
-X POST \
|
|
||||||
--header "Content-Type: application/json" \
|
|
||||||
--header "Accept: application/json" \
|
|
||||||
--header "X-API-Token: $API_TOKEN" \
|
|
||||||
-d "{ \"symbol_type\": \"Apple\"}" \
|
|
||||||
"$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/symbol_uploads" \
|
|
||||||
)
|
|
||||||
|
|
||||||
DSYM_UPLOAD_URL=$(echo "$UPLOAD_DSYM_DATA" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["upload_url"];')
|
|
||||||
DSYM_UPLOAD_ID=$(echo "$UPLOAD_DSYM_DATA" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["symbol_upload_id"];')
|
|
||||||
|
|
||||||
curl \
|
|
||||||
--progress-bar \
|
|
||||||
--header "x-ms-blob-type: BlockBlob" \
|
|
||||||
--upload-file "${DSYM_PATH}" \
|
|
||||||
"$DSYM_UPLOAD_URL"
|
|
||||||
|
|
||||||
curl \
|
|
||||||
-X PATCH \
|
|
||||||
--header "Content-Type: application/json" \
|
|
||||||
--header "Accept: application/json" \
|
|
||||||
--header "X-API-Token: $API_TOKEN" \
|
|
||||||
-d '{ "status": "committed" }' \
|
|
||||||
"$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/symbol_uploads/$DSYM_UPLOAD_ID"
|
|
||||||
}
|
|
||||||
|
|
||||||
APPCENTER="/usr/local/bin/appcenter"
|
APPCENTER="/usr/local/bin/appcenter"
|
||||||
|
|
||||||
$APPCENTER login --token "$API_TOKEN"
|
$APPCENTER login --token "$API_TOKEN"
|
||||||
$APPCENTER distribute release --app "$API_USER_NAME/$API_APP_NAME" -f "$IPA_PATH" -g Internal
|
$APPCENTER distribute release --app "$API_USER_NAME/$API_APP_NAME" -f "$IPA_PATH" -g Internal
|
||||||
|
$APPCENTER crashes upload-symbols --app "$API_USER_NAME/$API_APP_NAME" --symbol "$DSYM_PATH"
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
- (bool)messageProcessed:(int64_t)messageId;
|
- (bool)messageProcessed:(int64_t)messageId;
|
||||||
- (void)setMessageProcessed:(int64_t)messageId;
|
- (void)setMessageProcessed:(int64_t)messageId;
|
||||||
|
- (bool)wasMessageSentOnce:(int64_t)messageId;
|
||||||
|
- (void)setMessageWasSentOnce:(int64_t)messageId;
|
||||||
- (void)scheduleMessageConfirmation:(int64_t)messageId size:(NSInteger)size;
|
- (void)scheduleMessageConfirmation:(int64_t)messageId size:(NSInteger)size;
|
||||||
- (NSArray *)scheduledMessageConfirmations;
|
- (NSArray *)scheduledMessageConfirmations;
|
||||||
- (bool)scheduledMessageConfirmationsExceedSize:(NSInteger)sizeLimit orCount:(NSUInteger)countLimit;
|
- (bool)scheduledMessageConfirmationsExceedSize:(NSInteger)sizeLimit orCount:(NSUInteger)countLimit;
|
||||||
|
@ -1148,7 +1148,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
|
|||||||
{
|
{
|
||||||
if (!_useUnauthorizedMode)
|
if (!_useUnauthorizedMode)
|
||||||
{
|
{
|
||||||
NSMutableArray *currentContainerMessages = [[NSMutableArray alloc] init];
|
NSMutableArray<MTPreparedMessage *> *currentContainerMessages = [[NSMutableArray alloc] init];
|
||||||
NSUInteger currentContainerSize = 0;
|
NSUInteger currentContainerSize = 0;
|
||||||
|
|
||||||
for (NSUInteger j = i; j < transactionMessageList.count; j++, i++)
|
for (NSUInteger j = i; j < transactionMessageList.count; j++, i++)
|
||||||
@ -1186,8 +1186,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentContainerMessages.count == 1)
|
if (currentContainerMessages.count == 1 && ![transactionSessionInfo wasMessageSentOnce:currentContainerMessages[0].messageId])
|
||||||
{
|
{
|
||||||
|
[transactionSessionInfo setMessageWasSentOnce:currentContainerMessages[0].messageId];
|
||||||
int32_t quickAckId = 0;
|
int32_t quickAckId = 0;
|
||||||
NSData *messageData = [self _dataForEncryptedMessage:currentContainerMessages[0] authKey:authKey sessionInfo:transactionSessionInfo quickAckId:&quickAckId address:scheme.address extendedPadding:extendedPadding];
|
NSData *messageData = [self _dataForEncryptedMessage:currentContainerMessages[0] authKey:authKey sessionInfo:transactionSessionInfo quickAckId:&quickAckId address:scheme.address extendedPadding:extendedPadding];
|
||||||
if (messageData != nil)
|
if (messageData != nil)
|
||||||
@ -2116,17 +2117,12 @@ static bool isDataEqualToDataConstTime(NSData *data1, NSData *data2) {
|
|||||||
if (data1.length != data2.length) {
|
if (data1.length != data2.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t const *bytes1 = data1.bytes;
|
uint8_t const *bytes1 = data1.bytes;
|
||||||
uint8_t const *bytes2 = data2.bytes;
|
uint8_t const *bytes2 = data2.bytes;
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < data1.length; i++) {
|
for (int i = 0; i < data1.length; i++) {
|
||||||
if (bytes1[i] != bytes2[i]) {
|
result |= bytes1[i] != bytes2[i];
|
||||||
result |= i + 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result == 0;
|
return result == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
NSMutableSet *_processedMessageIdsSet;
|
NSMutableSet *_processedMessageIdsSet;
|
||||||
NSMutableArray *_scheduledMessageConfirmations;
|
NSMutableArray *_scheduledMessageConfirmations;
|
||||||
NSMutableDictionary *_containerMessagesMappingDict;
|
NSMutableDictionary *_containerMessagesMappingDict;
|
||||||
|
NSMutableSet *_sentMessageIdsSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@ -76,6 +77,7 @@
|
|||||||
_scheduledMessageConfirmations = [[NSMutableArray alloc] init];
|
_scheduledMessageConfirmations = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
_processedMessageIdsSet = [[NSMutableSet alloc] init];
|
_processedMessageIdsSet = [[NSMutableSet alloc] init];
|
||||||
|
_sentMessageIdsSet = [[NSMutableSet alloc] init];
|
||||||
_containerMessagesMappingDict = [[NSMutableDictionary alloc] init];
|
_containerMessagesMappingDict = [[NSMutableDictionary alloc] init];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@ -138,6 +140,14 @@
|
|||||||
[_processedMessageIdsSet addObject:@(messageId)];
|
[_processedMessageIdsSet addObject:@(messageId)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (bool)wasMessageSentOnce:(int64_t)messageId {
|
||||||
|
return [_sentMessageIdsSet containsObject:@(messageId)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setMessageWasSentOnce:(int64_t)messageId {
|
||||||
|
[_sentMessageIdsSet addObject:@(messageId)];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)scheduleMessageConfirmation:(int64_t)messageId size:(NSInteger)size
|
- (void)scheduleMessageConfirmation:(int64_t)messageId size:(NSInteger)size
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -42,6 +42,11 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
|
|
||||||
var pressed: (() -> Void)?
|
var pressed: (() -> Void)?
|
||||||
|
|
||||||
|
private var isSelected: Bool = false
|
||||||
|
private var isLoaded: Bool = false
|
||||||
|
|
||||||
|
private let isLoadedDisposable = MetaDisposable()
|
||||||
|
|
||||||
init(overlayBackgroundColor: UIColor = UIColor(white: 0.0, alpha: 0.3)) {
|
init(overlayBackgroundColor: UIColor = UIColor(white: 0.0, alpha: 0.3)) {
|
||||||
self.imageNode.contentAnimations = [.subsequentUpdates]
|
self.imageNode.contentAnimations = [.subsequentUpdates]
|
||||||
|
|
||||||
@ -60,9 +65,35 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.isLoadedDisposable.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
func setSelected(_ selected: Bool, animated: Bool = false) {
|
func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||||
let state: RadialStatusNodeState = selected ? .check(.white) : .none
|
if self.isSelected != selected {
|
||||||
self.statusNode.transitionToState(state, animated: animated, completion: {})
|
self.isSelected = selected
|
||||||
|
|
||||||
|
self.updateStatus(animated: animated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateIsLoaded(isLoaded: Bool, animated: Bool) {
|
||||||
|
if self.isLoaded != isLoaded {
|
||||||
|
self.isLoaded = isLoaded
|
||||||
|
self.updateStatus(animated: animated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateStatus(animated: Bool) {
|
||||||
|
if self.isSelected {
|
||||||
|
if self.isLoaded {
|
||||||
|
self.statusNode.transitionToState(.check(.white), animated: animated, completion: {})
|
||||||
|
} else {
|
||||||
|
self.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false, animateRotation: true), animated: animated, completion: {})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.statusNode.transitionToState(.none, animated: animated, completion: {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setOverlayBackgroundColor(_ color: UIColor) {
|
func setOverlayBackgroundColor(_ color: UIColor) {
|
||||||
@ -127,9 +158,6 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
gradientNode.updateLayout(size: size, transition: .immediate)
|
gradientNode.updateLayout(size: size, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
let state: RadialStatusNodeState = selected ? .check(.white) : .none
|
|
||||||
self.statusNode.transitionToState(state, animated: false, completion: {})
|
|
||||||
|
|
||||||
let progressDiameter: CGFloat = 50.0
|
let progressDiameter: CGFloat = 50.0
|
||||||
self.statusNode.frame = CGRect(x: floorToScreenPixels((size.width - progressDiameter) / 2.0), y: floorToScreenPixels((size.height - progressDiameter) / 2.0), width: progressDiameter, height: progressDiameter)
|
self.statusNode.frame = CGRect(x: floorToScreenPixels((size.width - progressDiameter) / 2.0), y: floorToScreenPixels((size.height - progressDiameter) / 2.0), width: progressDiameter, height: progressDiameter)
|
||||||
|
|
||||||
@ -143,6 +171,8 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
self.imageNode.setSignal(settingsBuiltinWallpaperImage(account: context.account))
|
self.imageNode.setSignal(settingsBuiltinWallpaperImage(account: context.account))
|
||||||
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: corners, imageSize: CGSize(), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
|
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: corners, imageSize: CGSize(), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
|
||||||
apply()
|
apply()
|
||||||
|
self.isLoadedDisposable.set(nil)
|
||||||
|
self.updateIsLoaded(isLoaded: true, animated: false)
|
||||||
case let .image(representations, _):
|
case let .image(representations, _):
|
||||||
let convertedRepresentations: [ImageRepresentationWithReference] = representations.map({ ImageRepresentationWithReference(representation: $0, reference: .wallpaper(wallpaper: nil, resource: $0.resource)) })
|
let convertedRepresentations: [ImageRepresentationWithReference] = representations.map({ ImageRepresentationWithReference(representation: $0, reference: .wallpaper(wallpaper: nil, resource: $0.resource)) })
|
||||||
self.imageNode.alpha = 1.0
|
self.imageNode.alpha = 1.0
|
||||||
@ -150,11 +180,16 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
|
|
||||||
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: corners, imageSize: largestImageRepresentation(representations)!.dimensions.cgSize.aspectFilled(size), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
|
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: corners, imageSize: largestImageRepresentation(representations)!.dimensions.cgSize.aspectFilled(size), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
|
||||||
apply()
|
apply()
|
||||||
|
self.isLoadedDisposable.set(nil)
|
||||||
|
self.updateIsLoaded(isLoaded: true, animated: false)
|
||||||
case let .file(file):
|
case let .file(file):
|
||||||
let convertedRepresentations : [ImageRepresentationWithReference] = file.file.previewRepresentations.map {
|
let convertedRepresentations : [ImageRepresentationWithReference] = file.file.previewRepresentations.map {
|
||||||
ImageRepresentationWithReference(representation: $0, reference: .wallpaper(wallpaper: .slug(file.slug), resource: $0.resource))
|
ImageRepresentationWithReference(representation: $0, reference: .wallpaper(wallpaper: .slug(file.slug), resource: $0.resource))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fullDimensions = file.file.dimensions ?? PixelDimensions(width: 2000, height: 4000)
|
||||||
|
let convertedFullRepresentations = [ImageRepresentationWithReference(representation: .init(dimensions: fullDimensions, resource: file.file.resource, progressiveSizes: [], immediateThumbnailData: nil), reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource))]
|
||||||
|
|
||||||
let imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
let imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
||||||
if wallpaper.isPattern {
|
if wallpaper.isPattern {
|
||||||
var patternIntensity: CGFloat = 0.5
|
var patternIntensity: CGFloat = 0.5
|
||||||
@ -180,10 +215,43 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let anyStatus = combineLatest(queue: .mainQueue(),
|
||||||
|
context.account.postbox.mediaBox.resourceStatus(convertedFullRepresentations[0].reference.resource, approximateSynchronousValue: true),
|
||||||
|
context.sharedContext.accountManager.mediaBox.resourceStatus(convertedFullRepresentations[0].reference.resource, approximateSynchronousValue: true)
|
||||||
|
)
|
||||||
|
|> map { a, b -> Bool in
|
||||||
|
switch a {
|
||||||
|
case .Local:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch b {
|
||||||
|
case .Local:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|> distinctUntilChanged
|
||||||
|
|
||||||
|
self.updateIsLoaded(isLoaded: false, animated: false)
|
||||||
|
self.isLoadedDisposable.set((anyStatus
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.updateIsLoaded(isLoaded: value, animated: true)
|
||||||
|
}))
|
||||||
} else {
|
} else {
|
||||||
self.imageNode.alpha = 1.0
|
self.imageNode.alpha = 1.0
|
||||||
|
|
||||||
imageSignal = wallpaperImage(account: context.account, accountManager: context.sharedContext.accountManager, fileReference: .standalone(media: file.file), representations: convertedRepresentations, thumbnail: true, autoFetchFullSize: true, synchronousLoad: synchronousLoad)
|
imageSignal = wallpaperImage(account: context.account, accountManager: context.sharedContext.accountManager, fileReference: .standalone(media: file.file), representations: convertedRepresentations, thumbnail: true, autoFetchFullSize: true, synchronousLoad: synchronousLoad)
|
||||||
|
|
||||||
|
self.updateIsLoaded(isLoaded: true, animated: false)
|
||||||
|
self.isLoadedDisposable.set(nil)
|
||||||
}
|
}
|
||||||
self.imageNode.setSignal(imageSignal, attemptSynchronously: synchronousLoad)
|
self.imageNode.setSignal(imageSignal, attemptSynchronously: synchronousLoad)
|
||||||
|
|
||||||
@ -207,6 +275,8 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
apply()
|
apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.setSelected(selected, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func buttonPressed() {
|
@objc func buttonPressed() {
|
||||||
|
@ -426,6 +426,7 @@ extension PresentationThemeRootNavigationBar: Codable {
|
|||||||
|
|
||||||
public convenience init(from decoder: Decoder) throws {
|
public convenience init(from decoder: Decoder) throws {
|
||||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let blurredBackgroundColor = try decodeColor(values, .background)
|
||||||
|
|
||||||
self.init(
|
self.init(
|
||||||
buttonColor: try decodeColor(values, .button),
|
buttonColor: try decodeColor(values, .button),
|
||||||
@ -434,8 +435,8 @@ extension PresentationThemeRootNavigationBar: Codable {
|
|||||||
secondaryTextColor: try decodeColor(values, .secondaryText),
|
secondaryTextColor: try decodeColor(values, .secondaryText),
|
||||||
controlColor: try decodeColor(values, .control),
|
controlColor: try decodeColor(values, .control),
|
||||||
accentTextColor: try decodeColor(values, .accentText),
|
accentTextColor: try decodeColor(values, .accentText),
|
||||||
blurredBackgroundColor: try decodeColor(values, .background),
|
blurredBackgroundColor: blurredBackgroundColor,
|
||||||
opaqueBackgroundColor: try decodeColor(values, .opaqueBackground, fallbackKey: "root.navBar.background"),
|
opaqueBackgroundColor: (try? decodeColor(values, .opaqueBackground)) ?? blurredBackgroundColor.withAlphaComponent(1.0),
|
||||||
separatorColor: try decodeColor(values, .separator),
|
separatorColor: try decodeColor(values, .separator),
|
||||||
badgeBackgroundColor: try decodeColor(values, .badgeFill),
|
badgeBackgroundColor: try decodeColor(values, .badgeFill),
|
||||||
badgeStrokeColor: try decodeColor(values, .badgeStroke),
|
badgeStrokeColor: try decodeColor(values, .badgeStroke),
|
||||||
|
@ -532,7 +532,14 @@ public struct PresentationResourcesChat {
|
|||||||
|
|
||||||
public static func chatInputTextFieldTimerImage(_ theme: PresentationTheme) -> UIImage? {
|
public static func chatInputTextFieldTimerImage(_ theme: PresentationTheme) -> UIImage? {
|
||||||
return theme.image(PresentationResourceKey.chatInputTextFieldTimerImage.rawValue, { theme in
|
return theme.image(PresentationResourceKey.chatInputTextFieldTimerImage.rawValue, { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Text/AccessoryIconTimer"), color: theme.chat.inputPanel.inputControlColor)
|
if let image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Text/AccessoryIconTimer"), color: theme.chat.inputPanel.inputControlColor) {
|
||||||
|
return generateImage(CGSize(width: image.size.width, height: image.size.height + 1.0), contextGenerator: { size, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
context.draw(image.cgImage!, in: CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: image.size))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@ filegroup(
|
|||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
appcenter_targets = [
|
||||||
|
"@appcenter_sdk//:AppCenter",
|
||||||
|
"@appcenter_sdk//:AppCenterCrashes",
|
||||||
|
]
|
||||||
|
|
||||||
swift_library(
|
swift_library(
|
||||||
name = "TelegramUI",
|
name = "TelegramUI",
|
||||||
module_name = "TelegramUI",
|
module_name = "TelegramUI",
|
||||||
@ -223,7 +228,12 @@ swift_library(
|
|||||||
"//submodules/ImportStickerPackUI:ImportStickerPackUI",
|
"//submodules/ImportStickerPackUI:ImportStickerPackUI",
|
||||||
"//submodules/GradientBackground:GradientBackground",
|
"//submodules/GradientBackground:GradientBackground",
|
||||||
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
|
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
|
||||||
],
|
] + select({
|
||||||
|
"@build_bazel_rules_apple//apple:ios_armv7": [],
|
||||||
|
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
||||||
|
"//build-system:ios_sim_arm64": [],
|
||||||
|
"@build_bazel_rules_apple//apple:ios_x86_64": [],
|
||||||
|
}),
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
],
|
],
|
||||||
|
@ -34,9 +34,11 @@ import CoreSpotlight
|
|||||||
import LightweightAccountData
|
import LightweightAccountData
|
||||||
import TelegramAudio
|
import TelegramAudio
|
||||||
import DebugSettingsUI
|
import DebugSettingsUI
|
||||||
|
|
||||||
#if canImport(BackgroundTasks)
|
|
||||||
import BackgroundTasks
|
import BackgroundTasks
|
||||||
|
|
||||||
|
#if os(iOS)
|
||||||
|
import AppCenter
|
||||||
|
import AppCenterCrashes
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private let handleVoipNotifications = false
|
private let handleVoipNotifications = false
|
||||||
@ -486,14 +488,7 @@ final class SharedApplicationContext {
|
|||||||
telegramUIDeclareEncodables()
|
telegramUIDeclareEncodables()
|
||||||
|
|
||||||
GlobalExperimentalSettings.isAppStoreBuild = buildConfig.isAppStoreBuild
|
GlobalExperimentalSettings.isAppStoreBuild = buildConfig.isAppStoreBuild
|
||||||
|
|
||||||
GlobalExperimentalSettings.enableFeed = false
|
GlobalExperimentalSettings.enableFeed = false
|
||||||
#if DEBUG
|
|
||||||
//GlobalExperimentalSettings.enableFeed = true
|
|
||||||
#if targetEnvironment(simulator)
|
|
||||||
//GlobalTelegramCoreConfiguration.readMessages = false
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
self.window?.makeKeyAndVisible()
|
self.window?.makeKeyAndVisible()
|
||||||
|
|
||||||
@ -1336,6 +1331,14 @@ final class SharedApplicationContext {
|
|||||||
|
|
||||||
self.maybeCheckForUpdates()
|
self.maybeCheckForUpdates()
|
||||||
|
|
||||||
|
#if os(iOS)
|
||||||
|
if !buildConfig.isAppStoreBuild, let appCenterId = buildConfig.appCenterId, !appCenterId.isEmpty {
|
||||||
|
AppCenter.start(withAppSecret: buildConfig.appCenterId, services: [
|
||||||
|
Crashes.self
|
||||||
|
])
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4856,7 +4856,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { [weak self] messageId, completion in
|
let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { [weak self] messageId, completion in
|
||||||
if let strongSelf = self, strongSelf.isNodeLoaded, canSendMessagesToChat(strongSelf.presentationInterfaceState) {
|
guard let strongSelf = self, strongSelf.isNodeLoaded else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let messageId = messageId {
|
||||||
|
if canSendMessagesToChat(strongSelf.presentationInterfaceState) {
|
||||||
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
|
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
|
||||||
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) {
|
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) {
|
||||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageId(message.id) }).updatedSearch(nil) }, completion: completion)
|
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageId(message.id) }).updatedSearch(nil) }, completion: completion)
|
||||||
@ -4871,6 +4875,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
} else {
|
} else {
|
||||||
completion(.immediate)
|
completion(.immediate)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageId(nil) }) }, completion: completion)
|
||||||
|
}
|
||||||
}, setupEditMessage: { [weak self] messageId, completion in
|
}, setupEditMessage: { [weak self] messageId, completion in
|
||||||
if let strongSelf = self, strongSelf.isNodeLoaded {
|
if let strongSelf = self, strongSelf.isNodeLoaded {
|
||||||
guard let messageId = messageId else {
|
guard let messageId = messageId else {
|
||||||
|
@ -286,7 +286,7 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte
|
|||||||
if !extendedSearchLayout {
|
if !extendedSearchLayout {
|
||||||
if case .scheduledMessages = chatPresentationInterfaceState.subject {
|
if case .scheduledMessages = chatPresentationInterfaceState.subject {
|
||||||
} else if chatPresentationInterfaceState.renderedPeer?.peerId != context.account.peerId {
|
} else if chatPresentationInterfaceState.renderedPeer?.peerId != context.account.peerId {
|
||||||
if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramSecretChat {
|
if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramSecretChat, chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 {
|
||||||
accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout))
|
accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout))
|
||||||
} else if currentAutoremoveTimeout != nil && chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 {
|
} else if currentAutoremoveTimeout != nil && chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 {
|
||||||
accessoryItems.append(.messageAutoremoveTimeout(currentAutoremoveTimeout))
|
accessoryItems.append(.messageAutoremoveTimeout(currentAutoremoveTimeout))
|
||||||
|
@ -1494,7 +1494,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
||||||
self.swipeToReplyFeedback?.impact()
|
self.swipeToReplyFeedback?.impact()
|
||||||
|
|
||||||
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonFillColor, wallpaper: item.presentationData.theme.wallpaper), strokeColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonStrokeColor, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
||||||
self.swipeToReplyNode = swipeToReplyNode
|
self.swipeToReplyNode = swipeToReplyNode
|
||||||
self.addSubnode(swipeToReplyNode)
|
self.addSubnode(swipeToReplyNode)
|
||||||
animateReplyNodeIn = true
|
animateReplyNodeIn = true
|
||||||
|
@ -3647,7 +3647,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
||||||
self.swipeToReplyFeedback?.impact()
|
self.swipeToReplyFeedback?.impact()
|
||||||
|
|
||||||
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonFillColor, wallpaper: item.presentationData.theme.wallpaper), strokeColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonStrokeColor, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
||||||
self.swipeToReplyNode = swipeToReplyNode
|
self.swipeToReplyNode = swipeToReplyNode
|
||||||
self.insertSubnode(swipeToReplyNode, belowSubnode: self.messageAccessibilityArea)
|
self.insertSubnode(swipeToReplyNode, belowSubnode: self.messageAccessibilityArea)
|
||||||
animateReplyNodeIn = true
|
animateReplyNodeIn = true
|
||||||
|
@ -850,7 +850,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
|
|||||||
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
||||||
self.swipeToReplyFeedback?.impact()
|
self.swipeToReplyFeedback?.impact()
|
||||||
|
|
||||||
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonFillColor, wallpaper: item.presentationData.theme.wallpaper), strokeColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonStrokeColor, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
||||||
self.swipeToReplyNode = swipeToReplyNode
|
self.swipeToReplyNode = swipeToReplyNode
|
||||||
self.addSubnode(swipeToReplyNode)
|
self.addSubnode(swipeToReplyNode)
|
||||||
animateReplyNodeIn = true
|
animateReplyNodeIn = true
|
||||||
|
@ -1008,7 +1008,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
if translation.x < -45.0, self.swipeToReplyNode == nil, let item = self.item {
|
||||||
self.swipeToReplyFeedback?.impact()
|
self.swipeToReplyFeedback?.impact()
|
||||||
|
|
||||||
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonFillColor, wallpaper: item.presentationData.theme.wallpaper), strokeColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonStrokeColor, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper), action: ChatMessageSwipeToReplyNode.Action(self.currentSwipeAction))
|
||||||
self.swipeToReplyNode = swipeToReplyNode
|
self.swipeToReplyNode = swipeToReplyNode
|
||||||
self.addSubnode(swipeToReplyNode)
|
self.addSubnode(swipeToReplyNode)
|
||||||
animateReplyNodeIn = true
|
animateReplyNodeIn = true
|
||||||
|
@ -11,25 +11,18 @@ final class ChatMessageSwipeToReplyNode: ASDisplayNode {
|
|||||||
case unlike
|
case unlike
|
||||||
}
|
}
|
||||||
|
|
||||||
private let backgroundNode: ASImageNode
|
private let backgroundNode: NavigationBackgroundNode
|
||||||
|
private let foregroundNode: ASImageNode
|
||||||
|
|
||||||
init(fillColor: UIColor, strokeColor: UIColor, foregroundColor: UIColor, action: ChatMessageSwipeToReplyNode.Action) {
|
init(fillColor: UIColor, enableBlur: Bool, foregroundColor: UIColor, action: ChatMessageSwipeToReplyNode.Action) {
|
||||||
self.backgroundNode = ASImageNode()
|
self.backgroundNode = NavigationBackgroundNode(color: fillColor, enableBlur: enableBlur)
|
||||||
self.backgroundNode.isLayerBacked = true
|
self.backgroundNode.isUserInteractionEnabled = false
|
||||||
self.backgroundNode.image = generateImage(CGSize(width: 33.0, height: 33.0), rotatedContext: { size, context in
|
|
||||||
|
self.foregroundNode = ASImageNode()
|
||||||
|
self.foregroundNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
|
self.foregroundNode.image = generateImage(CGSize(width: 33.0, height: 33.0), rotatedContext: { size, context in
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
context.setFillColor(fillColor.cgColor)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
let lineWidth: CGFloat = 1.0
|
|
||||||
let halfLineWidth = lineWidth / 2.0
|
|
||||||
var strokeAlpha: CGFloat = 0.0
|
|
||||||
strokeColor.getRed(nil, green: nil, blue: nil, alpha: &strokeAlpha)
|
|
||||||
if !strokeAlpha.isZero {
|
|
||||||
context.setStrokeColor(strokeColor.cgColor)
|
|
||||||
context.setLineWidth(lineWidth)
|
|
||||||
context.strokeEllipse(in: CGRect(origin: CGPoint(x: halfLineWidth, y: halfLineWidth), size: CGSize(width: size.width - lineWidth, height: size.width - lineWidth)))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .reply:
|
case .reply:
|
||||||
@ -65,7 +58,10 @@ final class ChatMessageSwipeToReplyNode: ASDisplayNode {
|
|||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.backgroundNode)
|
self.addSubnode(self.backgroundNode)
|
||||||
|
self.addSubnode(self.foregroundNode)
|
||||||
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 33.0, height: 33.0))
|
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 33.0, height: 33.0))
|
||||||
|
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: self.backgroundNode.bounds.height / 2.0, transition: .immediate)
|
||||||
|
self.foregroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 33.0, height: 33.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ enum ChatPanelRestrictionInfoDisplayType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class ChatPanelInterfaceInteraction {
|
final class ChatPanelInterfaceInteraction {
|
||||||
let setupReplyMessage: (MessageId, @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
let setupReplyMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
||||||
let setupEditMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
let setupEditMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
||||||
let beginMessageSelection: ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
let beginMessageSelection: ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
||||||
let deleteSelectedMessages: () -> Void
|
let deleteSelectedMessages: () -> Void
|
||||||
@ -133,7 +133,7 @@ final class ChatPanelInterfaceInteraction {
|
|||||||
let statuses: ChatPanelInterfaceInteractionStatuses?
|
let statuses: ChatPanelInterfaceInteractionStatuses?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
setupReplyMessage: @escaping (MessageId, @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
setupReplyMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
||||||
setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
||||||
beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
||||||
deleteSelectedMessages: @escaping () -> Void,
|
deleteSelectedMessages: @escaping () -> Void,
|
||||||
|
@ -253,7 +253,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|
|||||||
self.playButton.layer.animateScale(from: 0.01, to: 1.0, duration: 0.3, delay: 0.1)
|
self.playButton.layer.animateScale(from: 0.01, to: 1.0, duration: 0.3, delay: 0.1)
|
||||||
self.playButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: 0.1)
|
self.playButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: 0.1)
|
||||||
|
|
||||||
self.durationLabel.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
self.durationLabel.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, delay: 0.1)
|
||||||
|
|
||||||
self.waveformScubberNode.layer.animateScaleY(from: 0.1, to: 1.0, duration: 0.3, delay: 0.1)
|
self.waveformScubberNode.layer.animateScaleY(from: 0.1, to: 1.0, duration: 0.3, delay: 0.1)
|
||||||
self.waveformScubberNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: 0.1)
|
self.waveformScubberNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: 0.1)
|
||||||
|
@ -105,7 +105,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode {
|
|||||||
if let timeout = timeout {
|
if let timeout = timeout {
|
||||||
return (nil, shortTimeIntervalString(strings: strings, value: timeout), strings.VoiceOver_SelfDestructTimerOn(timeIntervalString(strings: strings, value: timeout)).0, 1.0, UIEdgeInsets())
|
return (nil, shortTimeIntervalString(strings: strings, value: timeout), strings.VoiceOver_SelfDestructTimerOn(timeIntervalString(strings: strings, value: timeout)).0, 1.0, UIEdgeInsets())
|
||||||
} else {
|
} else {
|
||||||
return (PresentationResourcesChat.chatInputTextFieldTimerImage(theme), nil, strings.VoiceOver_SelfDestructTimerOff, 1.0, UIEdgeInsets(top: 0.0, left: 0.0, bottom: 1.0, right: 0.0))
|
return (PresentationResourcesChat.chatInputTextFieldTimerImage(theme), nil, strings.VoiceOver_SelfDestructTimerOff, 1.0, UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0))
|
||||||
}
|
}
|
||||||
case .scheduledMessages:
|
case .scheduledMessages:
|
||||||
return (PresentationResourcesChat.chatInputTextFieldScheduleImage(theme), nil, strings.VoiceOver_ScheduledMessages, 1.0, UIEdgeInsets())
|
return (PresentationResourcesChat.chatInputTextFieldScheduleImage(theme), nil, strings.VoiceOver_ScheduledMessages, 1.0, UIEdgeInsets())
|
||||||
@ -128,7 +128,9 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode {
|
|||||||
|
|
||||||
func updateLayout(size: CGSize) {
|
func updateLayout(size: CGSize) {
|
||||||
if let image = self.imageNode.image {
|
if let image = self.imageNode.image {
|
||||||
self.imageNode.frame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0) - self.imageEdgeInsets.bottom), size: image.size)
|
let bottomInset: CGFloat = 0.0
|
||||||
|
let imageFrame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0) - bottomInset), size: image.size)
|
||||||
|
self.imageNode.frame = imageFrame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,15 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
self.messageDisposable.set((context.account.postbox.messageView(messageId)
|
self.messageDisposable.set((context.account.postbox.messageView(messageId)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] messageView in
|
|> deliverOnMainQueue).start(next: { [weak self] messageView in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
if messageView.message == nil {
|
||||||
|
Queue.mainQueue().justDispatch {
|
||||||
|
strongSelf.interfaceInteraction?.setupReplyMessage(nil, { _ in })
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let message = messageView.message
|
let message = messageView.message
|
||||||
|
|
||||||
var authorName = ""
|
var authorName = ""
|
||||||
var text = ""
|
var text = ""
|
||||||
if let forwardInfo = message?.forwardInfo, forwardInfo.flags.contains(.isImported) {
|
if let forwardInfo = message?.forwardInfo, forwardInfo.flags.contains(.isImported) {
|
||||||
|
15
third-party/AppCenter/AppCenter.BUILD
vendored
Normal file
15
third-party/AppCenter/AppCenter.BUILD
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
load("@build_bazel_rules_apple//apple:apple.bzl",
|
||||||
|
"apple_static_framework_import",
|
||||||
|
)
|
||||||
|
|
||||||
|
apple_static_framework_import(
|
||||||
|
name = "AppCenter",
|
||||||
|
framework_imports = glob(["AppCenter-SDK-Apple/iOS/AppCenter.framework/**"]),
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
apple_static_framework_import(
|
||||||
|
name = "AppCenterCrashes",
|
||||||
|
framework_imports = glob(["AppCenter-SDK-Apple/iOS/AppCenterCrashes.framework/**"]),
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
0
third-party/AppCenter/BUILD
vendored
Normal file
0
third-party/AppCenter/BUILD
vendored
Normal file
Loading…
x
Reference in New Issue
Block a user