mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
b7e0c3718e
@ -100,22 +100,21 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
|> mapToSignal { account -> Signal<Account?, NoError> in
|
||||
if let account = account {
|
||||
switch account {
|
||||
case .upgrading:
|
||||
return .complete()
|
||||
case let .authorized(account):
|
||||
account.shouldKeepOnlinePresence.set(.single(false))
|
||||
return applicationSettings(accountManager: accountManager)
|
||||
|> deliverOnMainQueue
|
||||
|> map { settings -> Account in
|
||||
accountCache = account
|
||||
Logger.shared.logToFile = settings.logging.logToFile
|
||||
Logger.shared.logToConsole = settings.logging.logToConsole
|
||||
|
||||
Logger.shared.redactSensitiveData = settings.logging.redactSensitiveData
|
||||
return account
|
||||
}
|
||||
case .unauthorized:
|
||||
return .complete()
|
||||
case .upgrading:
|
||||
return .complete()
|
||||
case let .authorized(account):
|
||||
return applicationSettings(accountManager: accountManager)
|
||||
|> deliverOnMainQueue
|
||||
|> map { settings -> Account in
|
||||
accountCache = account
|
||||
Logger.shared.logToFile = settings.logging.logToFile
|
||||
Logger.shared.logToConsole = settings.logging.logToConsole
|
||||
|
||||
Logger.shared.redactSensitiveData = settings.logging.redactSensitiveData
|
||||
return account
|
||||
}
|
||||
case .unauthorized:
|
||||
return .complete()
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
@ -275,7 +274,9 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
@available(iOSApplicationExtension 11.0, *)
|
||||
func resolveRecipients(for intent: INSendMessageIntent, with completion: @escaping ([INSendMessageRecipientResolutionResult]) -> Void) {
|
||||
if let peerId = intent.conversationIdentifier.flatMap(Int64.init) {
|
||||
let signal = self.accountPromise.get()
|
||||
let account = self.accountPromise.get()
|
||||
|
||||
let signal = account
|
||||
|> introduceError(IntentHandlingError.self)
|
||||
|> mapToSignal { account -> Signal<INPerson?, IntentHandlingError> in
|
||||
if let account = account {
|
||||
@ -402,8 +403,8 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
account.resetStateManagement()
|
||||
|
||||
let completion: Signal<Void, NoError> = account.stateManager.pollStateUpdateCompletion()
|
||||
|> map { _ in
|
||||
return Void()
|
||||
|> map { _ in
|
||||
return Void()
|
||||
}
|
||||
|
||||
return (completion |> timeout(4.0, queue: Queue.mainQueue(), alternate: .single(Void())))
|
||||
@ -482,7 +483,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
|
||||
for (_, messageId) in maxMessageIdsToApply {
|
||||
signals.append(applyMaxReadIndexInteractively(postbox: account.postbox, stateManager: account.stateManager, index: MessageIndex(id: messageId, timestamp: 0))
|
||||
|> introduceError(IntentHandlingError.self))
|
||||
|> introduceError(IntentHandlingError.self))
|
||||
}
|
||||
|
||||
if signals.isEmpty {
|
||||
@ -490,11 +491,11 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
} else {
|
||||
account.shouldBeServiceTaskMaster.set(.single(.now))
|
||||
return combineLatest(signals)
|
||||
|> mapToSignal { _ -> Signal<Void, IntentHandlingError> in
|
||||
return .complete()
|
||||
}
|
||||
|> afterDisposed {
|
||||
account.shouldBeServiceTaskMaster.set(.single(.never))
|
||||
|> mapToSignal { _ -> Signal<Void, IntentHandlingError> in
|
||||
return .complete()
|
||||
}
|
||||
|> afterDisposed {
|
||||
account.shouldBeServiceTaskMaster.set(.single(.never))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -573,34 +574,34 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
|
||||
func handle(intent: INSearchCallHistoryIntent, completion: @escaping (INSearchCallHistoryIntentResponse) -> Void) {
|
||||
self.actionDisposable.set((self.accountPromise.get()
|
||||
|> take(1)
|
||||
|> introduceError(IntentHandlingError.self)
|
||||
|> mapToSignal { account -> Signal<[CallRecord], IntentHandlingError> in
|
||||
guard let account = account else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
account.shouldBeServiceTaskMaster.set(.single(.now))
|
||||
return missedCalls(account: account)
|
||||
|> introduceError(IntentHandlingError.self)
|
||||
|> afterDisposed {
|
||||
account.shouldBeServiceTaskMaster.set(.single(.never))
|
||||
}
|
||||
|> take(1)
|
||||
|> introduceError(IntentHandlingError.self)
|
||||
|> mapToSignal { account -> Signal<[CallRecord], IntentHandlingError> in
|
||||
guard let account = account else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { calls in
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSearchCallHistoryIntent.self))
|
||||
let response: INSearchCallHistoryIntentResponse
|
||||
if #available(iOSApplicationExtension 11.0, *) {
|
||||
response = INSearchCallHistoryIntentResponse(code: .success, userActivity: userActivity)
|
||||
response.callRecords = calls.map { $0.intentCall }
|
||||
} else {
|
||||
response = INSearchCallHistoryIntentResponse(code: .continueInApp, userActivity: userActivity)
|
||||
}
|
||||
completion(response)
|
||||
}, error: { _ in
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSearchCallHistoryIntent.self))
|
||||
let response = INSearchCallHistoryIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity)
|
||||
completion(response)
|
||||
}))
|
||||
|
||||
account.shouldBeServiceTaskMaster.set(.single(.now))
|
||||
return missedCalls(account: account)
|
||||
|> introduceError(IntentHandlingError.self)
|
||||
|> afterDisposed {
|
||||
account.shouldBeServiceTaskMaster.set(.single(.never))
|
||||
}
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { calls in
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSearchCallHistoryIntent.self))
|
||||
let response: INSearchCallHistoryIntentResponse
|
||||
if #available(iOSApplicationExtension 11.0, *) {
|
||||
response = INSearchCallHistoryIntentResponse(code: .success, userActivity: userActivity)
|
||||
response.callRecords = calls.map { $0.intentCall }
|
||||
} else {
|
||||
response = INSearchCallHistoryIntentResponse(code: .continueInApp, userActivity: userActivity)
|
||||
}
|
||||
completion(response)
|
||||
}, error: { _ in
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSearchCallHistoryIntent.self))
|
||||
let response = INSearchCallHistoryIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity)
|
||||
completion(response)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -372,6 +372,13 @@
|
||||
location = "group:submodules/AvatarNode/AvatarNode_Xcode.xcodeproj">
|
||||
</FileRef>
|
||||
</Group>
|
||||
<Group
|
||||
location = "container:"
|
||||
name = "Chat">
|
||||
<FileRef
|
||||
location = "group:submodules/ReactionSelectionNode/ReactionSelectionNode_Xcode.xcodeproj">
|
||||
</FileRef>
|
||||
</Group>
|
||||
<FileRef
|
||||
location = "group:submodules/LegacyComponents/LegacyComponents_Xcode.xcodeproj">
|
||||
</FileRef>
|
||||
|
@ -309,6 +309,9 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
private let fetchDisposable = MetaDisposable()
|
||||
private let eventsNode: AnimatedStickerNodeDisplayEvents
|
||||
|
||||
public var automaticallyLoadFirstFrame: Bool = false
|
||||
public var playToCompletionOnStop: Bool = false
|
||||
|
||||
public var started: () -> Void = {}
|
||||
private var reportedStarted = false
|
||||
|
||||
@ -320,6 +323,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
private var renderer: (AnimationRenderer & ASDisplayNode)?
|
||||
|
||||
private var isPlaying: Bool = false
|
||||
private var canDisplayFirstFrame: Bool = false
|
||||
private var playbackMode: AnimatedStickerPlaybackMode = .loop
|
||||
|
||||
private let playbackStatus = Promise<AnimatedStickerStatus>()
|
||||
@ -394,6 +398,8 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
}
|
||||
if strongSelf.isPlaying {
|
||||
strongSelf.play()
|
||||
} else if strongSelf.canDisplayFirstFrame {
|
||||
strongSelf.play(firstFrame: true)
|
||||
}
|
||||
}))
|
||||
case .cached:
|
||||
@ -403,6 +409,8 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
strongSelf.cachedData = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: [.mappedRead])
|
||||
if strongSelf.isPlaying {
|
||||
strongSelf.play()
|
||||
} else if strongSelf.canDisplayFirstFrame {
|
||||
strongSelf.play(firstFrame: true)
|
||||
}
|
||||
}
|
||||
}))
|
||||
@ -424,9 +432,16 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
self.stop()
|
||||
}
|
||||
}
|
||||
let canDisplayFirstFrame = self.automaticallyLoadFirstFrame && self.isDisplaying
|
||||
if self.canDisplayFirstFrame != canDisplayFirstFrame {
|
||||
self.canDisplayFirstFrame = canDisplayFirstFrame
|
||||
if canDisplayFirstFrame {
|
||||
self.play(firstFrame: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func play() {
|
||||
public func play(firstFrame: Bool = false) {
|
||||
let directData = self.directData
|
||||
let cachedData = self.cachedData
|
||||
let queue = self.queue
|
||||
@ -451,7 +466,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
let duration: Double = frameSource.frameRate > 0 ? Double(frameSource.frameCount) / Double(frameSource.frameRate) : 0
|
||||
let frameRate = frameSource.frameRate
|
||||
|
||||
let timer = SwiftSignalKit.Timer(timeout: 1.0 / Double(frameRate), repeat: true, completion: {
|
||||
let timer = SwiftSignalKit.Timer(timeout: 1.0 / Double(frameRate), repeat: !firstFrame, completion: {
|
||||
let maybeFrame = frameQueue.syncWith { frameQueue in
|
||||
return frameQueue.take()
|
||||
}
|
||||
@ -492,6 +507,9 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
public func stop() {
|
||||
self.reportedStarted = false
|
||||
self.timer.swap(nil)?.invalidate()
|
||||
if self.playToCompletionOnStop {
|
||||
self.seekToStart()
|
||||
}
|
||||
}
|
||||
|
||||
public func seekToStart() {
|
||||
|
@ -11,6 +11,8 @@
|
||||
D03E45742305CCD20049C28B /* Crc32.m in Sources */ = {isa = PBXBuildFile; fileRef = D03E45732305CCD20049C28B /* Crc32.m */; };
|
||||
D03E45772305CCEC0049C28B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45762305CCEB0049C28B /* Foundation.framework */; };
|
||||
D03E45792305CCF00049C28B /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45782305CCF00049C28B /* libz.tbd */; };
|
||||
D03E46362306E0BB0049C28B /* crc32mac.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E46342306E0BB0049C28B /* crc32mac.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D03E463E2306E22E0049C28B /* Crc32.m in Sources */ = {isa = PBXBuildFile; fileRef = D03E45732305CCD20049C28B /* Crc32.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -20,6 +22,9 @@
|
||||
D03E45732305CCD20049C28B /* Crc32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Crc32.m; sourceTree = "<group>"; };
|
||||
D03E45762305CCEB0049C28B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
D03E45782305CCF00049C28B /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
D03E46322306E0BB0049C28B /* crc32mac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = crc32mac.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E46342306E0BB0049C28B /* crc32mac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32mac.h; sourceTree = "<group>"; };
|
||||
D03E46352306E0BB0049C28B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -32,6 +37,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E462F2306E0BB0049C28B /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@ -40,6 +52,7 @@
|
||||
children = (
|
||||
D03E45682305CC310049C28B /* Info.plist */,
|
||||
D03E45662305CC310049C28B /* Sources */,
|
||||
D03E46332306E0BB0049C28B /* crc32mac */,
|
||||
D03E45652305CC310049C28B /* Products */,
|
||||
D03E45752305CCEB0049C28B /* Frameworks */,
|
||||
);
|
||||
@ -49,6 +62,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E45642305CC310049C28B /* Crc32.framework */,
|
||||
D03E46322306E0BB0049C28B /* crc32mac.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -71,6 +85,15 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D03E46332306E0BB0049C28B /* crc32mac */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E46342306E0BB0049C28B /* crc32mac.h */,
|
||||
D03E46352306E0BB0049C28B /* Info.plist */,
|
||||
);
|
||||
path = crc32mac;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@ -82,6 +105,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E462D2306E0BB0049C28B /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E46362306E0BB0049C28B /* crc32mac.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -103,6 +134,24 @@
|
||||
productReference = D03E45642305CC310049C28B /* Crc32.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
D03E46312306E0BB0049C28B /* crc32mac */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D03E463B2306E0BB0049C28B /* Build configuration list for PBXNativeTarget "crc32mac" */;
|
||||
buildPhases = (
|
||||
D03E462D2306E0BB0049C28B /* Headers */,
|
||||
D03E462E2306E0BB0049C28B /* Sources */,
|
||||
D03E462F2306E0BB0049C28B /* Frameworks */,
|
||||
D03E46302306E0BB0049C28B /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = crc32mac;
|
||||
productName = crc32mac;
|
||||
productReference = D03E46322306E0BB0049C28B /* crc32mac.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@ -116,6 +165,9 @@
|
||||
D03E45632305CC310049C28B = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
};
|
||||
D03E46312306E0BB0049C28B = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D03E455E2305CC310049C28B /* Build configuration list for PBXProject "Crc32_Xcode" */;
|
||||
@ -131,6 +183,7 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
D03E45632305CC310049C28B /* Crc32 */,
|
||||
D03E46312306E0BB0049C28B /* crc32mac */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -143,6 +196,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E46302306E0BB0049C28B /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@ -154,6 +214,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E462E2306E0BB0049C28B /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E463E2306E22E0049C28B /* Crc32.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
@ -210,6 +278,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@ -266,6 +335,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -380,6 +450,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@ -462,6 +533,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -497,6 +569,316 @@
|
||||
};
|
||||
name = ReleaseHockeyappInternal;
|
||||
};
|
||||
D03E46372306E0BB0049C28B /* DebugAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = crc32mac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.crc32mac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = DebugAppStoreLLC;
|
||||
};
|
||||
D03E46382306E0BB0049C28B /* DebugHockeyapp */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = crc32mac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.crc32mac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = DebugHockeyapp;
|
||||
};
|
||||
D03E46392306E0BB0049C28B /* ReleaseAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = crc32mac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.crc32mac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = ReleaseAppStoreLLC;
|
||||
};
|
||||
D03E463A2306E0BB0049C28B /* ReleaseHockeyappInternal */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = crc32mac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.crc32mac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = ReleaseHockeyappInternal;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@ -522,6 +904,17 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = ReleaseAppStoreLLC;
|
||||
};
|
||||
D03E463B2306E0BB0049C28B /* Build configuration list for PBXNativeTarget "crc32mac" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D03E46372306E0BB0049C28B /* DebugAppStoreLLC */,
|
||||
D03E46382306E0BB0049C28B /* DebugHockeyapp */,
|
||||
D03E46392306E0BB0049C28B /* ReleaseAppStoreLLC */,
|
||||
D03E463A2306E0BB0049C28B /* ReleaseHockeyappInternal */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = ReleaseAppStoreLLC;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = D03E455B2305CC310049C28B /* Project object */;
|
||||
|
24
submodules/Crc32/crc32mac/Info.plist
Normal file
24
submodules/Crc32/crc32mac/Info.plist
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2019 Telegram Messenger LLP. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
9
submodules/Crc32/crc32mac/crc32mac.h
Normal file
9
submodules/Crc32/crc32mac/crc32mac.h
Normal file
@ -0,0 +1,9 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
//! Project version number for crc32mac.
|
||||
FOUNDATION_EXPORT double crc32macVersionNumber;
|
||||
|
||||
//! Project version string for crc32mac.
|
||||
FOUNDATION_EXPORT const unsigned char crc32macVersionString[];
|
||||
|
||||
uint32_t Crc32(const void *bytes, int length);
|
@ -130,7 +130,7 @@ public extension CALayer {
|
||||
self.add(animationGroup, forKey: key)
|
||||
}
|
||||
|
||||
public func animateKeyframes(values: [AnyObject], duration: Double, keyPath: String, removeOnCompletion: Bool = true, completion: ((Bool) -> Void)? = nil) {
|
||||
public func animateKeyframes(values: [AnyObject], duration: Double, keyPath: String, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
let k = Float(UIView.animationDurationFactor())
|
||||
var speed: Float = 1.0
|
||||
if k != 0 && k != 1 {
|
||||
@ -152,6 +152,7 @@ public extension CALayer {
|
||||
animation.keyTimes = keyTimes
|
||||
animation.speed = speed
|
||||
animation.duration = duration
|
||||
animation.isAdditive = additive
|
||||
if let completion = completion {
|
||||
animation.delegate = CALayerAnimationDelegate(animation: animation, completion: completion)
|
||||
}
|
||||
|
@ -63,24 +63,29 @@ public enum ContainedViewLayoutTransition {
|
||||
}
|
||||
|
||||
public extension ContainedViewLayoutTransition {
|
||||
func updateFrame(node: ASDisplayNode, frame: CGRect, force: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
func updateFrame(node: ASDisplayNode, frame: CGRect, force: Bool = false, beginWithCurrentState: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
if node.frame.equalTo(frame) && !force {
|
||||
completion?(true)
|
||||
} else {
|
||||
switch self {
|
||||
case .immediate:
|
||||
node.frame = frame
|
||||
case .immediate:
|
||||
node.frame = frame
|
||||
if let completion = completion {
|
||||
completion(true)
|
||||
}
|
||||
case let .animated(duration, curve):
|
||||
let previousFrame: CGRect
|
||||
if beginWithCurrentState, let presentation = node.layer.presentation() {
|
||||
previousFrame = presentation.frame
|
||||
} else {
|
||||
previousFrame = node.frame
|
||||
}
|
||||
node.frame = frame
|
||||
node.layer.animateFrame(from: previousFrame, to: frame, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, force: force, completion: { result in
|
||||
if let completion = completion {
|
||||
completion(true)
|
||||
completion(result)
|
||||
}
|
||||
case let .animated(duration, curve):
|
||||
let previousFrame = node.frame
|
||||
node.frame = frame
|
||||
node.layer.animateFrame(from: previousFrame, to: frame, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, force: force, completion: { result in
|
||||
if let completion = completion {
|
||||
completion(result)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,7 +152,7 @@ public extension ContainedViewLayoutTransition {
|
||||
}
|
||||
}
|
||||
|
||||
func updatePosition(node: ASDisplayNode, position: CGPoint, completion: ((Bool) -> Void)? = nil) {
|
||||
func updatePosition(node: ASDisplayNode, position: CGPoint, beginWithCurrentState: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
if node.position.equalTo(position) {
|
||||
completion?(true)
|
||||
} else {
|
||||
@ -158,7 +163,12 @@ public extension ContainedViewLayoutTransition {
|
||||
completion(true)
|
||||
}
|
||||
case let .animated(duration, curve):
|
||||
let previousPosition = node.position
|
||||
let previousPosition: CGPoint
|
||||
if beginWithCurrentState {
|
||||
previousPosition = node.layer.presentation()?.position ?? node.position
|
||||
} else {
|
||||
previousPosition = node.position
|
||||
}
|
||||
node.position = position
|
||||
node.layer.animatePosition(from: previousPosition, to: position, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, completion: { result in
|
||||
if let completion = completion {
|
||||
@ -498,7 +508,7 @@ public extension ContainedViewLayoutTransition {
|
||||
}
|
||||
}
|
||||
|
||||
func updateTransformScale(node: ASDisplayNode, scale: CGFloat, completion: ((Bool) -> Void)? = nil) {
|
||||
func updateTransformScale(node: ASDisplayNode, scale: CGFloat, beginWithCurrentState: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
let t = node.layer.transform
|
||||
let currentScale = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13))
|
||||
if currentScale.isEqual(to: scale) {
|
||||
@ -515,8 +525,15 @@ public extension ContainedViewLayoutTransition {
|
||||
completion(true)
|
||||
}
|
||||
case let .animated(duration, curve):
|
||||
let previousScale: CGFloat
|
||||
if beginWithCurrentState, let presentation = node.layer.presentation() {
|
||||
let t = presentation.transform
|
||||
previousScale = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13))
|
||||
} else {
|
||||
previousScale = currentScale
|
||||
}
|
||||
node.layer.transform = CATransform3DMakeScale(scale, scale, 1.0)
|
||||
node.layer.animateScale(from: currentScale, to: scale, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, completion: { result in
|
||||
node.layer.animateScale(from: previousScale, to: scale, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, completion: { result in
|
||||
if let completion = completion {
|
||||
completion(result)
|
||||
}
|
||||
@ -581,6 +598,47 @@ public extension ContainedViewLayoutTransition {
|
||||
}
|
||||
}
|
||||
|
||||
func updateSublayerTransformScaleAndOffset(node: ASDisplayNode, scale: CGFloat, offset: CGPoint, beginWithCurrentState: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
if !node.isNodeLoaded {
|
||||
node.subnodeTransform = CATransform3DMakeScale(scale, scale, 1.0)
|
||||
return
|
||||
}
|
||||
let t = node.layer.sublayerTransform
|
||||
let currentScale = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13))
|
||||
let currentOffset = CGPoint(x: t.m41, y: t.m42)
|
||||
if currentScale.isEqual(to: scale) && currentOffset == offset {
|
||||
if let completion = completion {
|
||||
completion(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let transform = CATransform3DTranslate(CATransform3DMakeScale(scale, scale, 1.0), offset.x, offset.y, 0.0)
|
||||
|
||||
switch self {
|
||||
case .immediate:
|
||||
node.layer.sublayerTransform = transform
|
||||
if let completion = completion {
|
||||
completion(true)
|
||||
}
|
||||
case let .animated(duration, curve):
|
||||
let initialTransform: CATransform3D
|
||||
if beginWithCurrentState, node.isNodeLoaded {
|
||||
initialTransform = node.layer.presentation()?.sublayerTransform ?? t
|
||||
} else {
|
||||
initialTransform = t
|
||||
}
|
||||
|
||||
node.layer.sublayerTransform = transform
|
||||
node.layer.animate(from: NSValue(caTransform3D: initialTransform), to: NSValue(caTransform3D: node.layer.sublayerTransform), keyPath: "sublayerTransform", timingFunction: curve.timingFunction, duration: duration, delay: 0.0, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: true, additive: false, completion: {
|
||||
result in
|
||||
if let completion = completion {
|
||||
completion(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func updateSublayerTransformScale(node: ASDisplayNode, scale: CGPoint, completion: ((Bool) -> Void)? = nil) {
|
||||
if !node.isNodeLoaded {
|
||||
node.subnodeTransform = CATransform3DMakeScale(scale.x, scale.y, 1.0)
|
||||
|
@ -5131,7 +5131,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -5211,7 +5211,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -5257,7 +5257,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -5365,7 +5365,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -5439,7 +5439,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -5513,7 +5513,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -5588,7 +5588,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -5662,7 +5662,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -5742,7 +5742,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -5816,7 +5816,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -5890,7 +5890,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -1,5 +1,9 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import sqlciphermac
|
||||
#else
|
||||
import sqlcipher
|
||||
#endif
|
||||
|
||||
public protocol PostboxCoding {
|
||||
init(decoder: PostboxDecoder)
|
||||
|
@ -22,7 +22,11 @@
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#if os(macOS)
|
||||
import sqlciphermac
|
||||
#else
|
||||
import sqlcipher
|
||||
#endif
|
||||
|
||||
public final class Database {
|
||||
internal var handle: OpaquePointer? = nil
|
||||
|
@ -1,5 +1,9 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import sqlciphermac
|
||||
#else
|
||||
import sqlcipher
|
||||
#endif
|
||||
|
||||
public enum HashFunctions {
|
||||
public static func murMurHash32(_ s: String) -> Int32 {
|
||||
|
@ -5,7 +5,11 @@ import SwiftSignalKit
|
||||
import SwiftSignalKitMac
|
||||
#endif
|
||||
|
||||
#if os(iOS)
|
||||
import Crc32
|
||||
#else
|
||||
import crc32mac
|
||||
#endif
|
||||
|
||||
private final class MediaBoxFileMap {
|
||||
fileprivate(set) var sum: Int32
|
||||
|
@ -1,5 +1,9 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import sqlciphermac
|
||||
#else
|
||||
import sqlcipher
|
||||
#endif
|
||||
|
||||
private final class SqliteInterfaceStatement {
|
||||
let statement: OpaquePointer?
|
||||
|
@ -1,5 +1,9 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import sqlciphermac
|
||||
#else
|
||||
import sqlcipher
|
||||
#endif
|
||||
#if os(macOS)
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
|
@ -1,5 +1,9 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import sqlciphermac
|
||||
#else
|
||||
import sqlcipher
|
||||
#endif
|
||||
|
||||
public enum StringIndexTokenTransliteration {
|
||||
case none
|
||||
|
@ -77,9 +77,10 @@
|
||||
D039FB1C21714D9800BD1BAD /* PeerPresencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D039FB1A21714D9800BD1BAD /* PeerPresencesView.swift */; };
|
||||
D03BCCF81C73561C0097A291 /* Table.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03BCCF71C73561C0097A291 /* Table.swift */; };
|
||||
D03E45572305C7C90049C28B /* sqlcipher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45562305C7C90049C28B /* sqlcipher.framework */; };
|
||||
D03E457B2305CD000049C28B /* Crc32.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E457A2305CD000049C28B /* Crc32.framework */; };
|
||||
D03E457D2305CD090049C28B /* Crc32.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E457C2305CD090049C28B /* Crc32.framework */; };
|
||||
D03E457F2305CD130049C28B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E457E2305CD130049C28B /* Foundation.framework */; };
|
||||
D03E462C2306E01C0049C28B /* sqlciphermac.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E462B2306E01C0049C28B /* sqlciphermac.framework */; };
|
||||
D03E463D2306E0F60049C28B /* crc32mac.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E463C2306E0F60049C28B /* crc32mac.framework */; };
|
||||
D040CA6422665370007123CE /* PostboxUpgrade_23to24.swift in Sources */ = {isa = PBXBuildFile; fileRef = D040CA6322665370007123CE /* PostboxUpgrade_23to24.swift */; };
|
||||
D040CA6522665370007123CE /* PostboxUpgrade_23to24.swift in Sources */ = {isa = PBXBuildFile; fileRef = D040CA6322665370007123CE /* PostboxUpgrade_23to24.swift */; };
|
||||
D0439B3F2289F6300067E026 /* AccountManagerAtomicState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0439B3E2289F6300067E026 /* AccountManagerAtomicState.swift */; };
|
||||
@ -444,6 +445,8 @@
|
||||
D03E457A2305CD000049C28B /* Crc32.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Crc32.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E457C2305CD090049C28B /* Crc32.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Crc32.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E457E2305CD130049C28B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
D03E462B2306E01C0049C28B /* sqlciphermac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = sqlciphermac.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E463C2306E0F60049C28B /* crc32mac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = crc32mac.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D040CA6322665370007123CE /* PostboxUpgrade_23to24.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostboxUpgrade_23to24.swift; sourceTree = "<group>"; };
|
||||
D0439B3E2289F6300067E026 /* AccountManagerAtomicState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountManagerAtomicState.swift; sourceTree = "<group>"; };
|
||||
D044CA291C617D39002160FF /* SeedConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeedConfiguration.swift; sourceTree = "<group>"; };
|
||||
@ -613,7 +616,8 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E457B2305CD000049C28B /* Crc32.framework in Frameworks */,
|
||||
D03E463D2306E0F60049C28B /* crc32mac.framework in Frameworks */,
|
||||
D03E462C2306E01C0049C28B /* sqlciphermac.framework in Frameworks */,
|
||||
D0B418611D7DFE95004562A4 /* SwiftSignalKitMac.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -692,6 +696,8 @@
|
||||
D0B4185F1D7DFE95004562A4 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E463C2306E0F60049C28B /* crc32mac.framework */,
|
||||
D03E462B2306E01C0049C28B /* sqlciphermac.framework */,
|
||||
D03E457E2305CD130049C28B /* Foundation.framework */,
|
||||
D03E457C2305CD090049C28B /* Crc32.framework */,
|
||||
D03E457A2305CD000049C28B /* Crc32.framework */,
|
||||
|
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1030"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D0B418121D7DFAF2004562A4"
|
||||
BuildableName = "PostboxMac.framework"
|
||||
BlueprintName = "PostboxMac"
|
||||
ReferencedContainer = "container:Postbox_Xcode.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "DebugHockeyapp"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "DebugHockeyapp"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D0B418121D7DFAF2004562A4"
|
||||
BuildableName = "PostboxMac.framework"
|
||||
BlueprintName = "PostboxMac"
|
||||
ReferencedContainer = "container:Postbox_Xcode.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "ReleaseHockeyapp"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D0B418121D7DFAF2004562A4"
|
||||
BuildableName = "PostboxMac.framework"
|
||||
BlueprintName = "PostboxMac"
|
||||
ReferencedContainer = "container:Postbox_Xcode.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "DebugHockeyapp">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "ReleaseHockeyapp"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
22
submodules/ReactionSelectionNode/Info.plist
Normal file
22
submodules/ReactionSelectionNode/Info.plist
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,579 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D03E45EA2305E3F30049C28B /* ReactionSelectionNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E45E82305E3F30049C28B /* ReactionSelectionNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D03E45F52305EB7C0049C28B /* ReactionSelectionNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E45F42305EB7C0049C28B /* ReactionSelectionNode.swift */; };
|
||||
D03E45F82305EB880049C28B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45F72305EB880049C28B /* Foundation.framework */; };
|
||||
D03E45FA2305EB8B0049C28B /* AsyncDisplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45F92305EB8B0049C28B /* AsyncDisplayKit.framework */; };
|
||||
D03E45FC2305EB8E0049C28B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45FB2305EB8E0049C28B /* UIKit.framework */; };
|
||||
D03E45FE2305EB910049C28B /* Display.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45FD2305EB910049C28B /* Display.framework */; };
|
||||
D03E46002305EE710049C28B /* AnimationUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45FF2305EE710049C28B /* AnimationUI.framework */; };
|
||||
D03E46022305EE750049C28B /* Postbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E46012305EE750049C28B /* Postbox.framework */; };
|
||||
D03E46042305EE790049C28B /* TelegramCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E46032305EE790049C28B /* TelegramCore.framework */; };
|
||||
D03E46082305EEDD0049C28B /* ReactionSelectionParentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E46072305EEDD0049C28B /* ReactionSelectionParentNode.swift */; };
|
||||
D03E460A2305EF900049C28B /* ReactionSwipeGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E46092305EF900049C28B /* ReactionSwipeGestureRecognizer.swift */; };
|
||||
D03E460C2305EFD80049C28B /* ReactionGestureItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E460B2305EFD80049C28B /* ReactionGestureItem.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D03E45E52305E3F30049C28B /* ReactionSelectionNode.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactionSelectionNode.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E45E82305E3F30049C28B /* ReactionSelectionNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactionSelectionNode.h; sourceTree = "<group>"; };
|
||||
D03E45E92305E3F30049C28B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D03E45F42305EB7C0049C28B /* ReactionSelectionNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionSelectionNode.swift; sourceTree = "<group>"; };
|
||||
D03E45F72305EB880049C28B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
D03E45F92305EB8B0049C28B /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E45FB2305EB8E0049C28B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
D03E45FD2305EB910049C28B /* Display.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Display.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E45FF2305EE710049C28B /* AnimationUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AnimationUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E46012305EE750049C28B /* Postbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Postbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E46032305EE790049C28B /* TelegramCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = TelegramCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E46072305EEDD0049C28B /* ReactionSelectionParentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionSelectionParentNode.swift; sourceTree = "<group>"; };
|
||||
D03E46092305EF900049C28B /* ReactionSwipeGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionSwipeGestureRecognizer.swift; sourceTree = "<group>"; };
|
||||
D03E460B2305EFD80049C28B /* ReactionGestureItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionGestureItem.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
D03E45E22305E3F30049C28B /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E46042305EE790049C28B /* TelegramCore.framework in Frameworks */,
|
||||
D03E46022305EE750049C28B /* Postbox.framework in Frameworks */,
|
||||
D03E46002305EE710049C28B /* AnimationUI.framework in Frameworks */,
|
||||
D03E45FE2305EB910049C28B /* Display.framework in Frameworks */,
|
||||
D03E45FC2305EB8E0049C28B /* UIKit.framework in Frameworks */,
|
||||
D03E45FA2305EB8B0049C28B /* AsyncDisplayKit.framework in Frameworks */,
|
||||
D03E45F82305EB880049C28B /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
D03E45DB2305E3F30049C28B = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E45E92305E3F30049C28B /* Info.plist */,
|
||||
D03E45E72305E3F30049C28B /* Sources */,
|
||||
D03E45E62305E3F30049C28B /* Products */,
|
||||
D03E45F62305EB870049C28B /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D03E45E62305E3F30049C28B /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E45E52305E3F30049C28B /* ReactionSelectionNode.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D03E45E72305E3F30049C28B /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E45F42305EB7C0049C28B /* ReactionSelectionNode.swift */,
|
||||
D03E45E82305E3F30049C28B /* ReactionSelectionNode.h */,
|
||||
D03E46072305EEDD0049C28B /* ReactionSelectionParentNode.swift */,
|
||||
D03E46092305EF900049C28B /* ReactionSwipeGestureRecognizer.swift */,
|
||||
D03E460B2305EFD80049C28B /* ReactionGestureItem.swift */,
|
||||
);
|
||||
path = Sources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D03E45F62305EB870049C28B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E46032305EE790049C28B /* TelegramCore.framework */,
|
||||
D03E46012305EE750049C28B /* Postbox.framework */,
|
||||
D03E45FF2305EE710049C28B /* AnimationUI.framework */,
|
||||
D03E45FD2305EB910049C28B /* Display.framework */,
|
||||
D03E45FB2305EB8E0049C28B /* UIKit.framework */,
|
||||
D03E45F92305EB8B0049C28B /* AsyncDisplayKit.framework */,
|
||||
D03E45F72305EB880049C28B /* Foundation.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
D03E45E02305E3F30049C28B /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E45EA2305E3F30049C28B /* ReactionSelectionNode.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
D03E45E42305E3F30049C28B /* ReactionSelectionNode */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D03E45ED2305E3F30049C28B /* Build configuration list for PBXNativeTarget "ReactionSelectionNode" */;
|
||||
buildPhases = (
|
||||
D03E45E02305E3F30049C28B /* Headers */,
|
||||
D03E45E12305E3F30049C28B /* Sources */,
|
||||
D03E45E22305E3F30049C28B /* Frameworks */,
|
||||
D03E45E32305E3F30049C28B /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = ReactionSelectionNode;
|
||||
productName = ReactionSelectionNode;
|
||||
productReference = D03E45E52305E3F30049C28B /* ReactionSelectionNode.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
D03E45DC2305E3F30049C28B /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
DefaultBuildSystemTypeForWorkspace = Latest;
|
||||
LastUpgradeCheck = 1030;
|
||||
ORGANIZATIONNAME = "Telegram Messenger LLP";
|
||||
TargetAttributes = {
|
||||
D03E45E42305E3F30049C28B = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
LastSwiftMigration = 1030;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D03E45DF2305E3F30049C28B /* Build configuration list for PBXProject "ReactionSelectionNode_Xcode" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = D03E45DB2305E3F30049C28B;
|
||||
productRefGroup = D03E45E62305E3F30049C28B /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
D03E45E42305E3F30049C28B /* ReactionSelectionNode */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
D03E45E32305E3F30049C28B /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
D03E45E12305E3F30049C28B /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E460A2305EF900049C28B /* ReactionSwipeGestureRecognizer.swift in Sources */,
|
||||
D03E46082305EEDD0049C28B /* ReactionSelectionParentNode.swift in Sources */,
|
||||
D03E460C2305EFD80049C28B /* ReactionGestureItem.swift in Sources */,
|
||||
D03E45F52305EB7C0049C28B /* ReactionSelectionNode.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D03E45EB2305E3F30049C28B /* DebugAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = DebugAppStoreLLC;
|
||||
};
|
||||
D03E45EC2305E3F30049C28B /* ReleaseAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = ReleaseAppStoreLLC;
|
||||
};
|
||||
D03E45EE2305E3F30049C28B /* DebugAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.ReactionSelectionNode;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = DebugAppStoreLLC;
|
||||
};
|
||||
D03E45EF2305E3F30049C28B /* ReleaseAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.ReactionSelectionNode;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = ReleaseAppStoreLLC;
|
||||
};
|
||||
D03E45F02305E4200049C28B /* DebugHockeyapp */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = DebugHockeyapp;
|
||||
};
|
||||
D03E45F12305E4200049C28B /* DebugHockeyapp */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.ReactionSelectionNode;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = DebugHockeyapp;
|
||||
};
|
||||
D03E45F22305E4290049C28B /* ReleaseHockeyappInternal */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = ReleaseHockeyappInternal;
|
||||
};
|
||||
D03E45F32305E4290049C28B /* ReleaseHockeyappInternal */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.ReactionSelectionNode;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = ReleaseHockeyappInternal;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
D03E45DF2305E3F30049C28B /* Build configuration list for PBXProject "ReactionSelectionNode_Xcode" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D03E45EB2305E3F30049C28B /* DebugAppStoreLLC */,
|
||||
D03E45F02305E4200049C28B /* DebugHockeyapp */,
|
||||
D03E45EC2305E3F30049C28B /* ReleaseAppStoreLLC */,
|
||||
D03E45F22305E4290049C28B /* ReleaseHockeyappInternal */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = ReleaseAppStoreLLC;
|
||||
};
|
||||
D03E45ED2305E3F30049C28B /* Build configuration list for PBXNativeTarget "ReactionSelectionNode" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D03E45EE2305E3F30049C28B /* DebugAppStoreLLC */,
|
||||
D03E45F12305E4200049C28B /* DebugHockeyapp */,
|
||||
D03E45EF2305E3F30049C28B /* ReleaseAppStoreLLC */,
|
||||
D03E45F32305E4290049C28B /* ReleaseHockeyappInternal */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = ReleaseAppStoreLLC;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = D03E45DC2305E3F30049C28B /* Project object */;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
public struct ReactionGestureItemValue {
|
||||
public var value: String
|
||||
public var text: String
|
||||
public var file: TelegramMediaFile
|
||||
|
||||
public init(value: String, text: String, file: TelegramMediaFile) {
|
||||
self.value = value
|
||||
self.text = text
|
||||
self.file = file
|
||||
}
|
||||
}
|
||||
|
||||
public final class ReactionGestureItem {
|
||||
public let value: ReactionGestureItemValue
|
||||
|
||||
public init(value: ReactionGestureItemValue) {
|
||||
self.value = value
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// ReactionSelectionNode.h
|
||||
// ReactionSelectionNode
|
||||
//
|
||||
// Created by Peter on 8/15/19.
|
||||
// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
//! Project version number for ReactionSelectionNode.
|
||||
FOUNDATION_EXPORT double ReactionSelectionNodeVersionNumber;
|
||||
|
||||
//! Project version string for ReactionSelectionNode.
|
||||
FOUNDATION_EXPORT const unsigned char ReactionSelectionNodeVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <ReactionSelectionNode/PublicHeader.h>
|
||||
|
||||
|
@ -0,0 +1,344 @@
|
||||
import Foundation
|
||||
import AsyncDisplayKit
|
||||
import AnimationUI
|
||||
import Display
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
private let shadowBlur: CGFloat = 8.0
|
||||
private let minimizedReactionSize: CGFloat = 30.0
|
||||
private let maximizedReactionSize: CGFloat = 60.0
|
||||
|
||||
private func generateBubbleImage(foreground: UIColor, diameter: CGFloat) -> UIImage? {
|
||||
return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setFillColor(foreground.cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter)))
|
||||
})?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0))
|
||||
}
|
||||
|
||||
private func generateBubbleShadowImage(shadow: UIColor, diameter: CGFloat) -> UIImage? {
|
||||
return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setFillColor(UIColor.white.cgColor)
|
||||
context.setShadow(offset: CGSize(), blur: shadowBlur, color: shadow.cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter)))
|
||||
context.setShadow(offset: CGSize(), blur: 1.0, color: shadow.cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter)))
|
||||
context.setFillColor(UIColor.clear.cgColor)
|
||||
context.setBlendMode(.copy)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter)))
|
||||
})?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0))
|
||||
}
|
||||
|
||||
private final class ReactionNode: ASDisplayNode {
|
||||
let reaction: ReactionGestureItem
|
||||
private let animationNode: AnimatedStickerNode
|
||||
var isMaximized: Bool?
|
||||
private let intrinsicSize: CGSize
|
||||
private let intrinsicOffset: CGPoint
|
||||
|
||||
init(account: Account, reaction: ReactionGestureItem) {
|
||||
self.reaction = reaction
|
||||
|
||||
self.animationNode = AnimatedStickerNode()
|
||||
self.animationNode.automaticallyLoadFirstFrame = true
|
||||
self.animationNode.playToCompletionOnStop = true
|
||||
//self.animationNode.backgroundColor = .lightGray
|
||||
|
||||
var intrinsicSize = CGSize(width: maximizedReactionSize + 18.0, height: maximizedReactionSize + 18.0)
|
||||
switch reaction.value.value {
|
||||
case "😳":
|
||||
intrinsicSize.width += 8.0
|
||||
intrinsicSize.height += 8.0
|
||||
self.intrinsicOffset = CGPoint(x: 0.0, y: -4.0)
|
||||
case "👍":
|
||||
intrinsicSize.width += 20.0
|
||||
intrinsicSize.height += 20.0
|
||||
self.intrinsicOffset = CGPoint(x: 0.0, y: 4.0)
|
||||
default:
|
||||
self.intrinsicOffset = CGPoint(x: 0.0, y: 0.0)
|
||||
}
|
||||
self.intrinsicSize = intrinsicSize
|
||||
|
||||
super.init()
|
||||
|
||||
//self.backgroundColor = .green
|
||||
|
||||
self.addSubnode(self.animationNode)
|
||||
self.animationNode.visibility = true
|
||||
self.animationNode.setup(account: account, resource: reaction.value.file.resource, width: Int(self.intrinsicSize.width) * 2, height: Int(self.intrinsicSize.height) * 2, mode: .direct)
|
||||
self.animationNode.updateLayout(size: self.intrinsicSize)
|
||||
self.animationNode.frame = CGRect(origin: CGPoint(), size: self.intrinsicSize)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, scale: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
transition.updatePosition(node: self.animationNode, position: CGPoint(x: size.width / 2.0 + self.intrinsicOffset.x * scale, y: size.height / 2.0 + self.intrinsicOffset.y * scale), beginWithCurrentState: true)
|
||||
transition.updateTransformScale(node: self.animationNode, scale: scale, beginWithCurrentState: true)
|
||||
}
|
||||
|
||||
func updateIsAnimating(_ isAnimating: Bool, animated: Bool) {
|
||||
if isAnimating {
|
||||
self.animationNode.visibility = true
|
||||
} else {
|
||||
self.animationNode.visibility = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ReactionSelectionNode: ASDisplayNode {
|
||||
private let backgroundNode: ASImageNode
|
||||
private let backgroundShadowNode: ASImageNode
|
||||
private let bubbleNodes: [(ASImageNode, ASImageNode)]
|
||||
private let reactionNodes: [ReactionNode]
|
||||
private var hasSelectedNode = false
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
public init(account: Account, reactions: [ReactionGestureItem]) {
|
||||
self.backgroundNode = ASImageNode()
|
||||
self.backgroundNode.displaysAsynchronously = false
|
||||
self.backgroundNode.displayWithoutProcessing = true
|
||||
self.backgroundNode.image = generateBubbleImage(foreground: .white, diameter: 42.0)
|
||||
|
||||
self.backgroundShadowNode = ASImageNode()
|
||||
self.backgroundShadowNode.displaysAsynchronously = false
|
||||
self.backgroundShadowNode.displayWithoutProcessing = true
|
||||
self.backgroundShadowNode.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: 42.0)
|
||||
|
||||
self.bubbleNodes = (0 ..< 2).map { i -> (ASImageNode, ASImageNode) in
|
||||
let imageNode = ASImageNode()
|
||||
imageNode.image = generateBubbleImage(foreground: .white, diameter: CGFloat(i + 1) * 8.0)
|
||||
imageNode.displaysAsynchronously = false
|
||||
imageNode.displayWithoutProcessing = true
|
||||
|
||||
let shadowNode = ASImageNode()
|
||||
shadowNode.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: CGFloat(i + 1) * 8.0)
|
||||
shadowNode.displaysAsynchronously = false
|
||||
shadowNode.displayWithoutProcessing = true
|
||||
|
||||
return (imageNode, shadowNode)
|
||||
}
|
||||
|
||||
self.reactionNodes = reactions.map { reaction -> ReactionNode in
|
||||
return ReactionNode(account: account, reaction: reaction)
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
||||
self.bubbleNodes.forEach { _, shadow in
|
||||
self.addSubnode(shadow)
|
||||
}
|
||||
self.addSubnode(self.backgroundShadowNode)
|
||||
self.bubbleNodes.forEach { foreground, _ in
|
||||
self.addSubnode(foreground)
|
||||
}
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.reactionNodes.forEach(self.addSubnode(_:))
|
||||
}
|
||||
|
||||
func updateLayout(constrainedSize: CGSize, startingPoint: CGPoint, offsetFromStart: CGFloat, isInitial: Bool) {
|
||||
let backgroundHeight: CGFloat = 42.0
|
||||
let reactionSpacing: CGFloat = 6.0
|
||||
let minimizedReactionVerticalInset: CGFloat = floor((backgroundHeight - minimizedReactionSize) / 2.0)
|
||||
|
||||
let contentWidth: CGFloat = CGFloat(self.reactionNodes.count - 1) * (minimizedReactionSize) + maximizedReactionSize + CGFloat(self.reactionNodes.count + 1) * reactionSpacing
|
||||
|
||||
var backgroundFrame = CGRect(origin: CGPoint(x: -shadowBlur, y: -shadowBlur), size: CGSize(width: contentWidth + shadowBlur * 2.0, height: backgroundHeight + shadowBlur * 2.0))
|
||||
backgroundFrame = backgroundFrame.offsetBy(dx: startingPoint.x - contentWidth + backgroundHeight / 2.0 - 52.0, dy: startingPoint.y - backgroundHeight - 16.0)
|
||||
|
||||
self.backgroundNode.frame = backgroundFrame
|
||||
self.backgroundShadowNode.frame = backgroundFrame
|
||||
|
||||
let anchorMinX = backgroundFrame.minX + shadowBlur + backgroundHeight / 2.0
|
||||
let anchorMaxX = backgroundFrame.maxX - shadowBlur - backgroundHeight / 2.0
|
||||
let anchorX = max(anchorMinX, min(anchorMaxX, offsetFromStart))
|
||||
|
||||
var reactionX: CGFloat = backgroundFrame.minX + shadowBlur + reactionSpacing
|
||||
if offsetFromStart > backgroundFrame.maxX - shadowBlur {
|
||||
self.hasSelectedNode = false
|
||||
} else {
|
||||
self.hasSelectedNode = true
|
||||
}
|
||||
|
||||
var maximizedIndex = Int(((anchorX - anchorMinX) / (anchorMaxX - anchorMinX)) * CGFloat(self.reactionNodes.count))
|
||||
maximizedIndex = max(0, min(self.reactionNodes.count - 1, maximizedIndex))
|
||||
|
||||
for i in 0 ..< self.reactionNodes.count {
|
||||
let isMaximized = i == maximizedIndex
|
||||
|
||||
let reactionSize: CGFloat
|
||||
if isMaximized {
|
||||
reactionSize = maximizedReactionSize
|
||||
} else {
|
||||
reactionSize = minimizedReactionSize
|
||||
}
|
||||
|
||||
let transition: ContainedViewLayoutTransition
|
||||
if isInitial {
|
||||
transition = .immediate
|
||||
} else {
|
||||
transition = .animated(duration: 0.18, curve: .easeInOut)
|
||||
}
|
||||
|
||||
if self.reactionNodes[i].isMaximized != isMaximized {
|
||||
self.reactionNodes[i].isMaximized = isMaximized
|
||||
self.reactionNodes[i].updateIsAnimating(isMaximized, animated: !isInitial)
|
||||
if isMaximized && !isInitial {
|
||||
self.hapticFeedback.tap()
|
||||
}
|
||||
}
|
||||
|
||||
var reactionFrame = CGRect(origin: CGPoint(x: reactionX, y: backgroundFrame.maxY - shadowBlur - minimizedReactionVerticalInset - reactionSize), size: CGSize(width: reactionSize, height: reactionSize))
|
||||
if isMaximized {
|
||||
reactionFrame.origin.x -= 9.0
|
||||
reactionFrame.size.width += 18.0
|
||||
}
|
||||
self.reactionNodes[i].updateLayout(size: reactionFrame.size, scale: reactionFrame.size.width / (maximizedReactionSize + 18.0), transition: transition)
|
||||
|
||||
transition.updateFrame(node: self.reactionNodes[i], frame: reactionFrame, beginWithCurrentState: true)
|
||||
|
||||
reactionX += reactionSize + reactionSpacing
|
||||
}
|
||||
|
||||
let mainBubbleFrame = CGRect(origin: CGPoint(x: anchorX - 8.0 - shadowBlur, y: backgroundFrame.maxY - shadowBlur - 8.0 - shadowBlur), size: CGSize(width: 16.0 + shadowBlur * 2.0, height: 16.0 + shadowBlur * 2.0))
|
||||
self.bubbleNodes[1].0.frame = mainBubbleFrame
|
||||
self.bubbleNodes[1].1.frame = mainBubbleFrame
|
||||
|
||||
let secondaryBubbleFrame = CGRect(origin: CGPoint(x: mainBubbleFrame.midX - 9.0 - (8.0 + shadowBlur * 2.0) / 2.0, y: mainBubbleFrame.midY + 12.0 - (8.0 + shadowBlur * 2.0) / 2.0), size: CGSize(width: 8.0 + shadowBlur * 2.0, height: 8.0 + shadowBlur * 2.0))
|
||||
self.bubbleNodes[0].0.frame = secondaryBubbleFrame
|
||||
self.bubbleNodes[0].1.frame = secondaryBubbleFrame
|
||||
}
|
||||
|
||||
func animateIn() {
|
||||
self.bubbleNodes[1].0.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
|
||||
self.bubbleNodes[1].1.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
|
||||
|
||||
self.bubbleNodes[0].0.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.05, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
|
||||
self.bubbleNodes[0].1.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.05, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
|
||||
|
||||
let backgroundOffset = CGPoint(x: (self.backgroundNode.frame.width - shadowBlur) / 2.0 - 42.0, y: (self.backgroundNode.frame.height - shadowBlur) / 2.0)
|
||||
let damping: CGFloat = 100.0
|
||||
|
||||
for i in 0 ..< self.reactionNodes.count {
|
||||
let animationOffset: Double = 1.0 - Double(i) / Double(self.reactionNodes.count - 1)
|
||||
var nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.maxX - shadowBlur) / 2.0 - 42.0, y: self.reactionNodes[i].frame.minY - self.backgroundNode.frame.maxY - shadowBlur)
|
||||
nodeOffset.x = -nodeOffset.x
|
||||
nodeOffset.y = 30.0
|
||||
self.reactionNodes[i].layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5 + animationOffset * 0.08, initialVelocity: 0.0, damping: damping)
|
||||
self.reactionNodes[i].layer.animateSpring(from: NSValue(cgPoint: nodeOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true)
|
||||
}
|
||||
|
||||
self.backgroundNode.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, damping: damping)
|
||||
self.backgroundNode.layer.animateSpring(from: NSValue(cgPoint: backgroundOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true)
|
||||
self.backgroundShadowNode.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, damping: damping)
|
||||
self.backgroundShadowNode.layer.animateSpring(from: NSValue(cgPoint: backgroundOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true)
|
||||
}
|
||||
|
||||
func animateOut(into targetNode: ASImageNode?, hideTarget: Bool, completion: @escaping () -> Void) {
|
||||
self.hapticFeedback.prepareTap()
|
||||
|
||||
var completedContainer = false
|
||||
var completedTarget = true
|
||||
|
||||
let intermediateCompletion: () -> Void = {
|
||||
if completedContainer && completedTarget {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
if let targetNode = targetNode {
|
||||
for i in 0 ..< self.reactionNodes.count {
|
||||
if let isMaximized = self.reactionNodes[i].isMaximized, isMaximized {
|
||||
if let snapshotView = self.reactionNodes[i].view.snapshotContentTree() {
|
||||
let targetSnapshotView = UIImageView()
|
||||
targetSnapshotView.image = targetNode.image
|
||||
targetSnapshotView.frame = self.view.convert(targetNode.bounds, from: targetNode.view)
|
||||
self.reactionNodes[i].isHidden = true
|
||||
self.view.addSubview(targetSnapshotView)
|
||||
self.view.addSubview(snapshotView)
|
||||
completedTarget = false
|
||||
let targetPosition = self.view.convert(targetNode.bounds.center, from: targetNode.view)
|
||||
let duration: Double = 0.3
|
||||
if hideTarget {
|
||||
targetNode.isHidden = true
|
||||
}
|
||||
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
|
||||
targetSnapshotView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
targetSnapshotView.layer.animateScale(from: snapshotView.bounds.width / targetSnapshotView.bounds.width, to: 0.5, duration: 0.3, removeOnCompletion: false)
|
||||
|
||||
|
||||
let sourcePoint = snapshotView.center
|
||||
let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y - 30.0)
|
||||
|
||||
let x1 = sourcePoint.x
|
||||
let y1 = sourcePoint.y
|
||||
let x2 = midPoint.x
|
||||
let y2 = midPoint.y
|
||||
let x3 = targetPosition.x
|
||||
let y3 = targetPosition.y
|
||||
|
||||
let a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
let b = (x1 * x1 * (y2 - y3) + x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1)) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
let c = (x2 * x2 * (x3 * y1 - x1 * y3) + x2 * (x1 * x1 * y3 - x3 * x3 * y1) + x1 * x3 * (x3 - x1) * y2) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
|
||||
var keyframes: [AnyObject] = []
|
||||
for i in 0 ..< 10 {
|
||||
let k = CGFloat(i) / CGFloat(10 - 1)
|
||||
let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k
|
||||
let y = a * x * x + b * x + c
|
||||
keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y)))
|
||||
}
|
||||
|
||||
snapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false, completion: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.hapticFeedback.tap()
|
||||
}
|
||||
completedTarget = true
|
||||
if hideTarget {
|
||||
targetNode.isHidden = false
|
||||
targetNode.layer.animateSpring(from: 0.5 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: duration, initialVelocity: 0.0, damping: 90.0)
|
||||
}
|
||||
intermediateCompletion()
|
||||
})
|
||||
targetSnapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false)
|
||||
|
||||
snapshotView.layer.animateScale(from: 1.0, to: (targetSnapshotView.bounds.width * 0.5) / snapshotView.bounds.width, duration: 0.3, removeOnCompletion: false)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.backgroundNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
self.backgroundShadowNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
self.backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
self.backgroundShadowNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
|
||||
completedContainer = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
for (node, shadow) in self.bubbleNodes {
|
||||
node.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
node.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
shadow.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
shadow.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
for i in 0 ..< self.reactionNodes.count {
|
||||
self.reactionNodes[i].layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
self.reactionNodes[i].layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
}
|
||||
|
||||
func selectedReaction() -> ReactionGestureItem? {
|
||||
if !self.hasSelectedNode {
|
||||
return nil
|
||||
}
|
||||
for i in 0 ..< self.reactionNodes.count {
|
||||
if let isMaximized = self.reactionNodes[i].isMaximized, isMaximized {
|
||||
return self.reactionNodes[i].reaction
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
import Foundation
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
public final class ReactionSelectionParentNode: ASDisplayNode {
|
||||
private let account: Account
|
||||
|
||||
private var currentNode: ReactionSelectionNode?
|
||||
private var currentLocation: (CGPoint, CGFloat)?
|
||||
|
||||
private var validLayout: (size: CGSize, insets: UIEdgeInsets)?
|
||||
|
||||
public init(account: Account) {
|
||||
self.account = account
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
func displayReactions(_ reactions: [ReactionGestureItem], at point: CGPoint) {
|
||||
if let currentNode = self.currentNode {
|
||||
currentNode.removeFromSupernode()
|
||||
self.currentNode = nil
|
||||
}
|
||||
|
||||
let reactionNode = ReactionSelectionNode(account: self.account, reactions: reactions)
|
||||
self.addSubnode(reactionNode)
|
||||
self.currentNode = reactionNode
|
||||
self.currentLocation = (point, point.x)
|
||||
|
||||
if let (size, insets) = self.validLayout {
|
||||
self.update(size: size, insets: insets, isInitial: true)
|
||||
|
||||
reactionNode.animateIn()
|
||||
}
|
||||
}
|
||||
|
||||
func selectedReaction() -> ReactionGestureItem? {
|
||||
if let currentNode = self.currentNode {
|
||||
return currentNode.selectedReaction()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func dismissReactions(into targetNode: ASImageNode?, hideTarget: Bool) {
|
||||
if let currentNode = self.currentNode {
|
||||
currentNode.animateOut(into: targetNode, hideTarget: hideTarget, completion: { [weak currentNode] in
|
||||
currentNode?.removeFromSupernode()
|
||||
})
|
||||
self.currentNode = nil
|
||||
}
|
||||
}
|
||||
|
||||
func updateReactionsAnchor(point: CGPoint) {
|
||||
if let (currentPoint, _) = self.currentLocation {
|
||||
self.currentLocation = (currentPoint, point.x)
|
||||
|
||||
if let (size, insets) = self.validLayout {
|
||||
self.update(size: size, insets: insets, isInitial: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, insets)
|
||||
|
||||
self.update(size: size, insets: insets, isInitial: false)
|
||||
}
|
||||
|
||||
private func update(size: CGSize, insets: UIEdgeInsets, isInitial: Bool) {
|
||||
if let currentNode = self.currentNode, let (point, offset) = currentLocation {
|
||||
currentNode.updateLayout(constrainedSize: size, startingPoint: point, offsetFromStart: offset, isInitial: isInitial)
|
||||
currentNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
}
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
return nil
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
|
||||
public final class ReactionSwipeGestureRecognizer: UIPanGestureRecognizer {
|
||||
private var validatedGesture = false
|
||||
|
||||
private var firstLocation: CGPoint = CGPoint()
|
||||
private var currentReactions: [ReactionGestureItem] = []
|
||||
private var isActivated = false
|
||||
private var isAwaitingCompletion = false
|
||||
private weak var currentContainer: ReactionSelectionParentNode?
|
||||
|
||||
public var availableReactions: (() -> [ReactionGestureItem])?
|
||||
public var getReactionContainer: (() -> ReactionSelectionParentNode?)?
|
||||
public var updateOffset: ((CGFloat, Bool) -> Void)?
|
||||
public var completed: ((ReactionGestureItem?) -> Void)?
|
||||
public var displayReply: ((CGFloat) -> Void)?
|
||||
public var activateReply: (() -> Void)?
|
||||
|
||||
override public init(target: Any?, action: Selector?) {
|
||||
super.init(target: target, action: action)
|
||||
|
||||
self.maximumNumberOfTouches = 1
|
||||
}
|
||||
|
||||
override public func reset() {
|
||||
super.reset()
|
||||
|
||||
self.validatedGesture = false
|
||||
self.currentReactions = []
|
||||
self.isActivated = false
|
||||
self.isAwaitingCompletion = false
|
||||
}
|
||||
|
||||
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
super.touchesBegan(touches, with: event)
|
||||
|
||||
if let availableReactions = self.availableReactions?(), !availableReactions.isEmpty {
|
||||
self.currentReactions = availableReactions
|
||||
let touch = touches.first!
|
||||
self.firstLocation = touch.location(in: nil)
|
||||
} else {
|
||||
self.state = .failed
|
||||
}
|
||||
}
|
||||
|
||||
override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
if self.isAwaitingCompletion {
|
||||
return
|
||||
}
|
||||
guard let _ = self.view else {
|
||||
return
|
||||
}
|
||||
guard let location = touches.first?.location(in: nil) else {
|
||||
return
|
||||
}
|
||||
|
||||
var translation = CGPoint(x: location.x - self.firstLocation.x, y: location.y - self.firstLocation.y)
|
||||
|
||||
let absTranslationX: CGFloat = abs(translation.x)
|
||||
let absTranslationY: CGFloat = abs(translation.y)
|
||||
|
||||
var updatedOffset = false
|
||||
|
||||
if !self.validatedGesture {
|
||||
if translation.x > 0.0 {
|
||||
self.state = .failed
|
||||
} else if absTranslationY > 2.0 && absTranslationY > absTranslationX * 2.0 {
|
||||
self.state = .failed
|
||||
} else if absTranslationX > 2.0 && absTranslationY * 2.0 < absTranslationX {
|
||||
self.validatedGesture = true
|
||||
self.firstLocation = location
|
||||
translation = CGPoint()
|
||||
self.updateOffset?(0.0, false)
|
||||
updatedOffset = true
|
||||
}
|
||||
}
|
||||
|
||||
if self.validatedGesture {
|
||||
if !updatedOffset {
|
||||
self.updateOffset?(-min(0.0, translation.x), false)
|
||||
}
|
||||
if !self.isActivated {
|
||||
if absTranslationX > 40.0 {
|
||||
self.isActivated = true
|
||||
self.displayReply?(-min(0.0, translation.x))
|
||||
if !self.currentReactions.isEmpty, let reactionContainer = self.getReactionContainer?() {
|
||||
self.currentContainer = reactionContainer
|
||||
let reactionContainerLocation = reactionContainer.view.convert(location, from: nil)
|
||||
reactionContainer.displayReactions(self.currentReactions, at: reactionContainerLocation)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let reactionContainer = self.currentContainer {
|
||||
let reactionContainerLocation = reactionContainer.view.convert(location, from: nil)
|
||||
reactionContainer.updateReactionsAnchor(point: reactionContainerLocation)
|
||||
}
|
||||
}
|
||||
super.touchesMoved(touches, with: event)
|
||||
}
|
||||
}
|
||||
|
||||
override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
if self.isAwaitingCompletion {
|
||||
return
|
||||
}
|
||||
guard let location = touches.first?.location(in: nil) else {
|
||||
return
|
||||
}
|
||||
if self.validatedGesture {
|
||||
let translation = CGPoint(x: location.x - self.firstLocation.x, y: location.y - self.firstLocation.y)
|
||||
if let reaction = self.currentContainer?.selectedReaction() {
|
||||
self.completed?(reaction)
|
||||
self.isAwaitingCompletion = true
|
||||
} else {
|
||||
if translation.x < -40.0 {
|
||||
self.currentContainer?.dismissReactions(into: nil, hideTarget: false)
|
||||
self.activateReply?()
|
||||
self.state = .ended
|
||||
} else {
|
||||
self.currentContainer?.dismissReactions(into: nil, hideTarget: false)
|
||||
self.completed?(nil)
|
||||
self.state = .cancelled
|
||||
super.touchesEnded(touches, with: event)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.currentContainer?.dismissReactions(into: nil, hideTarget: false)
|
||||
self.state = .cancelled
|
||||
super.touchesEnded(touches, with: event)
|
||||
}
|
||||
}
|
||||
|
||||
public func complete(into targetNode: ASImageNode?, hideTarget: Bool) {
|
||||
if self.isAwaitingCompletion {
|
||||
self.currentContainer?.dismissReactions(into: targetNode, hideTarget: hideTarget)
|
||||
self.state = .ended
|
||||
}
|
||||
}
|
||||
}
|
@ -1017,6 +1017,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return self?.navigationController as? NavigationController
|
||||
}, chatControllerNode: { [weak self] in
|
||||
return self?.chatDisplayNode
|
||||
}, reactionContainerNode: { [weak self] in
|
||||
return self?.chatDisplayNode.reactionContainerNode
|
||||
}, presentGlobalOverlayController: { [weak self] controller, arguments in
|
||||
self?.presentInGlobalOverlay(controller, with: arguments)
|
||||
}, callPeer: { [weak self] peerId in
|
||||
@ -1523,6 +1525,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
window.rootViewController?.present(controller, animated: true)
|
||||
}
|
||||
}
|
||||
}, updateMessageReaction: { [weak self] messageId, reaction in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = updateMessageReactionsInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, reactions: [reaction]).start()
|
||||
}, requestMessageUpdate: { [weak self] id in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
||||
|
@ -7,6 +7,7 @@ import Display
|
||||
import TelegramUIPreferences
|
||||
import AccountContext
|
||||
import TextSelectionNode
|
||||
import ReactionSelectionNode
|
||||
|
||||
struct ChatInterfaceHighlightedState: Equatable {
|
||||
let messageStableId: UInt32
|
||||
@ -73,6 +74,7 @@ public final class ChatControllerInteraction {
|
||||
let presentController: (ViewController, Any?) -> Void
|
||||
let navigationController: () -> NavigationController?
|
||||
let chatControllerNode: () -> ASDisplayNode?
|
||||
let reactionContainerNode: () -> ReactionSelectionParentNode?
|
||||
let presentGlobalOverlayController: (ViewController, Any?) -> Void
|
||||
let callPeer: (PeerId) -> Void
|
||||
let longTap: (ChatControllerInteractionLongTapAction, Message?) -> Void
|
||||
@ -92,6 +94,7 @@ public final class ChatControllerInteraction {
|
||||
let sendScheduledMessagesNow: ([MessageId]) -> Void
|
||||
let editScheduledMessagesTime: ([MessageId]) -> Void
|
||||
let performTextSelectionAction: (UInt32, String, TextSelectionAction) -> Void
|
||||
let updateMessageReaction: (MessageId, String) -> Void
|
||||
|
||||
let requestMessageUpdate: (MessageId) -> Void
|
||||
let cancelInteractiveKeyboardGestures: () -> Void
|
||||
@ -106,7 +109,7 @@ public final class ChatControllerInteraction {
|
||||
var searchTextHighightState: String?
|
||||
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
||||
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
self.openMessage = openMessage
|
||||
self.openPeer = openPeer
|
||||
self.openPeerMention = openPeerMention
|
||||
@ -134,6 +137,7 @@ public final class ChatControllerInteraction {
|
||||
self.presentController = presentController
|
||||
self.navigationController = navigationController
|
||||
self.chatControllerNode = chatControllerNode
|
||||
self.reactionContainerNode = reactionContainerNode
|
||||
self.presentGlobalOverlayController = presentGlobalOverlayController
|
||||
self.callPeer = callPeer
|
||||
self.longTap = longTap
|
||||
@ -153,6 +157,7 @@ public final class ChatControllerInteraction {
|
||||
self.sendScheduledMessagesNow = sendScheduledMessagesNow
|
||||
self.editScheduledMessagesTime = editScheduledMessagesTime
|
||||
self.performTextSelectionAction = performTextSelectionAction
|
||||
self.updateMessageReaction = updateMessageReaction
|
||||
|
||||
self.requestMessageUpdate = requestMessageUpdate
|
||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||
@ -170,6 +175,8 @@ public final class ChatControllerInteraction {
|
||||
return nil
|
||||
}, chatControllerNode: {
|
||||
return nil
|
||||
}, reactionContainerNode: {
|
||||
return nil
|
||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
||||
}, canSetupReply: { _ in
|
||||
return false
|
||||
@ -185,6 +192,7 @@ public final class ChatControllerInteraction {
|
||||
}, sendScheduledMessagesNow: { _ in
|
||||
}, editScheduledMessagesTime: { _ in
|
||||
}, performTextSelectionAction: { _, _, _ in
|
||||
}, updateMessageReaction: { _, _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -10,6 +10,7 @@ import TelegramUIPreferences
|
||||
import TextFormat
|
||||
import AccountContext
|
||||
import TelegramNotices
|
||||
import ReactionSelectionNode
|
||||
|
||||
private final class ChatControllerNodeView: UITracingLayerView, WindowInputAccessoryHeightProvider, PreviewingHostView {
|
||||
var inputAccessoryHeight: (() -> CGFloat)?
|
||||
@ -76,6 +77,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
let backgroundNode: WallpaperbackgroundNode
|
||||
let historyNode: ChatHistoryListNode
|
||||
let reactionContainerNode: ReactionSelectionParentNode
|
||||
let historyNodeContainer: ASDisplayNode
|
||||
let loadingNode: ChatLoadingNode
|
||||
private var emptyNode: ChatEmptyNode?
|
||||
@ -209,6 +211,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.historyNode.rotated = true
|
||||
self.historyNodeContainer = ASDisplayNode()
|
||||
self.historyNodeContainer.addSubnode(self.historyNode)
|
||||
|
||||
self.reactionContainerNode = ReactionSelectionParentNode(account: context.account)
|
||||
self.historyNodeContainer.addSubnode(self.reactionContainerNode)
|
||||
|
||||
self.loadingNode = ChatLoadingNode(theme: self.chatPresentationInterfaceState.theme, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper)
|
||||
|
||||
self.inputPanelBackgroundNode = ASDisplayNode()
|
||||
@ -839,6 +845,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
transition.updateFrame(node: emptyNode, frame: contentBounds)
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.reactionContainerNode, frame: contentBounds)
|
||||
self.reactionContainerNode.updateLayout(size: contentBounds.size, insets: UIEdgeInsets(), transition: transition)
|
||||
|
||||
var contentBottomInset: CGFloat = inputPanelsHeight + 4.0
|
||||
|
||||
if let scrollContainerNode = self.scrollContainerNode {
|
||||
|
@ -462,9 +462,22 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .minimal)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, false, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude))
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .minimal, reactionCount: dateReactionCount)
|
||||
|
||||
let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, false, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReactions)
|
||||
|
||||
var viaBotApply: (TextNodeLayout, () -> TextNode)?
|
||||
var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)?
|
||||
|
@ -314,7 +314,20 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
var webpageGalleryMediaCount: Int?
|
||||
for media in message.media {
|
||||
@ -534,7 +547,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
statusSizeAndApply = statusLayout(context, presentationData, edited, viewCount, dateText, statusType, textConstrainedSize)
|
||||
statusSizeAndApply = statusLayout(context, presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReactions)
|
||||
}
|
||||
default:
|
||||
break
|
||||
@ -1023,4 +1036,11 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? {
|
||||
return self.contentImageNode?.playMediaWithSound()
|
||||
}
|
||||
|
||||
func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -172,4 +172,8 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
|
||||
|
||||
func updateIsExtractedToContextPreview(_ value: Bool) {
|
||||
}
|
||||
|
||||
func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import MosaicLayout
|
||||
import TextSelectionNode
|
||||
import PlatformRestrictionMatching
|
||||
import Emoji
|
||||
import ReactionSelectionNode
|
||||
|
||||
private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(Message, AnyClass)] {
|
||||
var result: [(Message, AnyClass)] = []
|
||||
@ -178,6 +179,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
private var appliedForwardInfo: (Peer?, String?)?
|
||||
|
||||
private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer?
|
||||
private var reactionRecognizer: ReactionSwipeGestureRecognizer?
|
||||
|
||||
private var awaitingAppliedReaction: String?
|
||||
|
||||
override var visibility: ListViewItemNodeVisibility {
|
||||
didSet {
|
||||
@ -365,7 +369,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
self.tapRecognizer = recognizer
|
||||
self.view.addGestureRecognizer(recognizer)
|
||||
|
||||
let replyRecognizer = ChatSwipeToReplyRecognizer(target: self, action: #selector(self.swipeToReplyGesture(_:)))
|
||||
/*let replyRecognizer = ChatSwipeToReplyRecognizer(target: self, action: #selector(self.swipeToReplyGesture(_:)))
|
||||
replyRecognizer.shouldBegin = { [weak self] in
|
||||
if let strongSelf = self, let item = strongSelf.item {
|
||||
if strongSelf.selectionNode != nil {
|
||||
@ -387,7 +391,128 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
}
|
||||
return false
|
||||
}
|
||||
self.view.addGestureRecognizer(replyRecognizer)
|
||||
self.view.addGestureRecognizer(replyRecognizer)*/
|
||||
|
||||
let reactionRecognizer = ReactionSwipeGestureRecognizer(target: nil, action: nil)
|
||||
self.reactionRecognizer = reactionRecognizer
|
||||
reactionRecognizer.availableReactions = { [weak self] in
|
||||
guard let strongSelf = self, let item = strongSelf.item else {
|
||||
return []
|
||||
}
|
||||
if strongSelf.selectionNode != nil {
|
||||
return []
|
||||
}
|
||||
for media in item.content.firstMessage.media {
|
||||
if let _ = media as? TelegramMediaExpiredContent {
|
||||
return []
|
||||
}
|
||||
else if let media = media as? TelegramMediaAction {
|
||||
if case .phoneCall = media.action {
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
if !item.controllerInteraction.canSetupReply(item.message) {
|
||||
//return []
|
||||
}
|
||||
|
||||
let reactions: [(String, String)] = [
|
||||
("😒", "Sad"),
|
||||
("😳", "Surprised"),
|
||||
//("🥳", "Fun"),
|
||||
("👍", "Like"),
|
||||
("❤", "Love"),
|
||||
]
|
||||
|
||||
var result: [ReactionGestureItem] = []
|
||||
for (value, text) in reactions {
|
||||
if let file = item.associatedData.animatedEmojiStickers[value]?.file {
|
||||
result.append(ReactionGestureItem(value: ReactionGestureItemValue(value: value, text: text, file: file)))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
reactionRecognizer.getReactionContainer = { [weak self] in
|
||||
return self?.item?.controllerInteraction.reactionContainerNode()
|
||||
}
|
||||
reactionRecognizer.updateOffset = { [weak self] offset, animated in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var bounds = strongSelf.bounds
|
||||
bounds.origin.x = offset
|
||||
strongSelf.bounds = bounds
|
||||
if animated {
|
||||
strongSelf.layer.animateBoundsOriginXAdditive(from: -offset, to: 0.0, duration: 0.1, mediaTimingFunction: CAMediaTimingFunction(name: .easeOut))
|
||||
}
|
||||
if let swipeToReplyNode = strongSelf.swipeToReplyNode {
|
||||
swipeToReplyNode.alpha = max(0.0, min(1.0, abs(offset / 40.0)))
|
||||
}
|
||||
}
|
||||
reactionRecognizer.activateReply = { [weak self] in
|
||||
guard let strongSelf = self, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
var bounds = strongSelf.bounds
|
||||
let offset = bounds.origin.x
|
||||
bounds.origin.x = 0.0
|
||||
strongSelf.bounds = bounds
|
||||
if !offset.isZero {
|
||||
strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
if let swipeToReplyNode = strongSelf.swipeToReplyNode {
|
||||
strongSelf.swipeToReplyNode = nil
|
||||
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
||||
swipeToReplyNode?.removeFromSupernode()
|
||||
})
|
||||
swipeToReplyNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
}
|
||||
item.controllerInteraction.setupReply(item.message.id)
|
||||
}
|
||||
reactionRecognizer.displayReply = { [weak self] offset in
|
||||
guard let strongSelf = self, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
if strongSelf.swipeToReplyNode == nil {
|
||||
if strongSelf.swipeToReplyFeedback == nil {
|
||||
strongSelf.swipeToReplyFeedback = HapticFeedback()
|
||||
}
|
||||
strongSelf.swipeToReplyFeedback?.tap()
|
||||
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))
|
||||
strongSelf.swipeToReplyNode = swipeToReplyNode
|
||||
strongSelf.insertSubnode(swipeToReplyNode, belowSubnode: strongSelf.messageAccessibilityArea)
|
||||
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: strongSelf.bounds.size.width, y: floor((strongSelf.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
||||
swipeToReplyNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.12)
|
||||
swipeToReplyNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4)
|
||||
}
|
||||
}
|
||||
reactionRecognizer.completed = { [weak self] reaction in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let item = strongSelf.item, let reaction = reaction {
|
||||
strongSelf.awaitingAppliedReaction = reaction.value.value
|
||||
item.controllerInteraction.updateMessageReaction(item.message.id, reaction.value.value)
|
||||
} else {
|
||||
strongSelf.reactionRecognizer?.complete(into: nil, hideTarget: false)
|
||||
var bounds = strongSelf.bounds
|
||||
let offset = bounds.origin.x
|
||||
bounds.origin.x = 0.0
|
||||
strongSelf.bounds = bounds
|
||||
if !offset.isZero {
|
||||
strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
if let swipeToReplyNode = strongSelf.swipeToReplyNode {
|
||||
strongSelf.swipeToReplyNode = nil
|
||||
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
||||
swipeToReplyNode?.removeFromSupernode()
|
||||
})
|
||||
swipeToReplyNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.view.addGestureRecognizer(reactionRecognizer)
|
||||
}
|
||||
|
||||
override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, Bool) -> Void) {
|
||||
@ -444,7 +569,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, CGSize) -> (CGSize, () -> ChatMessageForwardInfoNode),
|
||||
replyInfoLayout: (ChatPresentationData, PresentationStrings, AccountContext, ChatMessageReplyInfoType, Message, CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode),
|
||||
actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (Bool) -> ChatMessageActionButtonsNode)),
|
||||
mosaicStatusLayout: (AccountContext, ChatPresentationData, Bool, Int?, String, ChatMessageDateAndStatusType, CGSize) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode),
|
||||
mosaicStatusLayout: (AccountContext, ChatPresentationData, Bool, Int?, String, ChatMessageDateAndStatusType, CGSize, [MessageReaction]) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode),
|
||||
currentShareButtonNode: HighlightableButtonNode?,
|
||||
layoutConstants: ChatMessageItemLayoutConstants,
|
||||
currentItem: ChatMessageItem?,
|
||||
@ -888,7 +1013,20 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let statusType: ChatMessageDateAndStatusType
|
||||
if message.effectivelyIncoming(item.context.account.peerId) {
|
||||
@ -903,7 +1041,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
mosaicStatusSizeAndApply = mosaicStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: 200.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
mosaicStatusSizeAndApply = mosaicStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: 200.0, height: CGFloat.greatestFiniteMagnitude), dateReactions)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1775,6 +1913,35 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
}
|
||||
|
||||
strongSelf.updateSearchTextHighlightState()
|
||||
|
||||
if let awaitingAppliedReaction = strongSelf.awaitingAppliedReaction {
|
||||
var bounds = strongSelf.bounds
|
||||
let offset = bounds.origin.x
|
||||
bounds.origin.x = 0.0
|
||||
strongSelf.bounds = bounds
|
||||
if !offset.isZero {
|
||||
strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
if let swipeToReplyNode = strongSelf.swipeToReplyNode {
|
||||
strongSelf.swipeToReplyNode = nil
|
||||
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
||||
swipeToReplyNode?.removeFromSupernode()
|
||||
})
|
||||
swipeToReplyNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
strongSelf.awaitingAppliedReaction = nil
|
||||
var targetNode: ASImageNode?
|
||||
var hideTarget = false
|
||||
for contentNode in strongSelf.contentNodes {
|
||||
if let (reactionNode, count) = contentNode.reactionTargetNode(value: awaitingAppliedReaction) {
|
||||
targetNode = reactionNode
|
||||
hideTarget = count == 1
|
||||
break
|
||||
}
|
||||
}
|
||||
strongSelf.reactionRecognizer?.complete(into: targetNode, hideTarget: hideTarget)
|
||||
}
|
||||
}
|
||||
|
||||
override func updateAccessibilityData(_ accessibilityData: ChatMessageAccessibilityData) {
|
||||
@ -2504,7 +2671,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
}
|
||||
|
||||
@objc func swipeToReplyGesture(_ recognizer: ChatSwipeToReplyRecognizer) {
|
||||
switch recognizer.state {
|
||||
/*switch recognizer.state {
|
||||
case .began:
|
||||
self.currentSwipeToReplyTranslation = 0.0
|
||||
if self.swipeToReplyFeedback == nil {
|
||||
@ -2563,7 +2730,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private var absoluteRect: (CGRect, CGSize)?
|
||||
|
@ -128,7 +128,7 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
buttonImage = PresentationResourcesChat.chatBubbleOutgoingCallButtonImage(item.presentationData.theme.theme)
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: 0)
|
||||
|
||||
let statusText: String
|
||||
if let callDuration = callDuration, callDuration > 1 {
|
||||
@ -214,4 +214,8 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
return .none
|
||||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +149,20 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let statusType: ChatMessageDateAndStatusType?
|
||||
switch position {
|
||||
@ -173,7 +186,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
var statusApply: ((Bool) -> Void)?
|
||||
|
||||
if let statusType = statusType {
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude))
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude), dateReactions)
|
||||
statusSize = size
|
||||
statusApply = apply
|
||||
}
|
||||
@ -330,4 +343,11 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let _ = item.controllerInteraction.openMessage(item.message, .default)
|
||||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
@ -104,6 +105,28 @@ enum ChatMessageDateAndStatusType: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private let reactionSize: CGFloat = 18.0
|
||||
|
||||
private final class StatusReactionNode: ASImageNode {
|
||||
let value: String
|
||||
var count: Int
|
||||
|
||||
init(value: String, count: Int) {
|
||||
self.value = value
|
||||
self.count = count
|
||||
|
||||
super.init()
|
||||
|
||||
self.image = generateImage(CGSize(width: reactionSize, height: reactionSize), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
UIGraphicsPushContext(context)
|
||||
let string = NSAttributedString(string: value, font: Font.regular(11.0), textColor: .black)
|
||||
string.draw(at: CGPoint(x: 1.0, y: 3.0))
|
||||
UIGraphicsPopContext()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
private var backgroundNode: ASImageNode?
|
||||
private var checkSentNode: ASImageNode?
|
||||
@ -112,6 +135,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
private var clockMinNode: ASImageNode?
|
||||
private let dateNode: TextNode
|
||||
private var impressionIcon: ASImageNode?
|
||||
private var reactionNodes: [StatusReactionNode] = []
|
||||
|
||||
private var type: ChatMessageDateAndStatusType?
|
||||
private var theme: ChatPresentationThemeData?
|
||||
@ -128,7 +152,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
self.addSubnode(self.dateNode)
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize) -> (CGSize, (Bool) -> Void) {
|
||||
func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize, _ reactions: [MessageReaction]) -> (CGSize, (Bool) -> Void) {
|
||||
let dateLayout = TextNode.asyncLayout(self.dateNode)
|
||||
|
||||
var checkReadNode = self.checkReadNode
|
||||
@ -142,11 +166,11 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
let currentType = self.type
|
||||
let currentTheme = self.theme
|
||||
|
||||
return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize in
|
||||
return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions in
|
||||
let dateColor: UIColor
|
||||
var backgroundImage: UIImage?
|
||||
var outgoingStatus: ChatMessageDateAndStatusOutgoingType?
|
||||
let leftInset: CGFloat
|
||||
var leftInset: CGFloat
|
||||
|
||||
let loadedCheckFullImage: UIImage?
|
||||
let loadedCheckPartialImage: UIImage?
|
||||
@ -372,6 +396,12 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
backgroundInsets = UIEdgeInsets(top: 2.0, left: 7.0, bottom: 2.0, right: 7.0)
|
||||
}
|
||||
|
||||
var reactionInset: CGFloat = 0.0
|
||||
if !reactions.isEmpty {
|
||||
reactionInset = 1.0 + CGFloat(reactions.count) * reactionSize
|
||||
}
|
||||
leftInset += reactionInset
|
||||
|
||||
let layoutSize = CGSize(width: leftInset + impressionWidth + date.size.width + statusWidth + backgroundInsets.left + backgroundInsets.right, height: date.size.height + backgroundInsets.top + backgroundInsets.bottom)
|
||||
|
||||
return (layoutSize, { [weak self] animated in
|
||||
@ -423,7 +453,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
} else if themeUpdated {
|
||||
clockFrameNode.image = clockFrameImage
|
||||
}
|
||||
clockFrameNode.position = CGPoint(x: backgroundInsets.left + clockPosition.x, y: backgroundInsets.top + clockPosition.y)
|
||||
clockFrameNode.position = CGPoint(x: backgroundInsets.left + clockPosition.x + reactionInset, y: backgroundInsets.top + clockPosition.y)
|
||||
if let clockFrameNode = strongSelf.clockFrameNode {
|
||||
maybeAddRotationAnimation(clockFrameNode.layer, duration: 6.0)
|
||||
}
|
||||
@ -440,7 +470,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
} else if themeUpdated {
|
||||
clockMinNode.image = clockMinImage
|
||||
}
|
||||
clockMinNode.position = CGPoint(x: backgroundInsets.left + clockPosition.x, y: backgroundInsets.top + clockPosition.y)
|
||||
clockMinNode.position = CGPoint(x: backgroundInsets.left + clockPosition.x + reactionInset, y: backgroundInsets.top + clockPosition.y)
|
||||
if let clockMinNode = strongSelf.clockMinNode {
|
||||
maybeAddRotationAnimation(clockMinNode.layer, duration: 1.0)
|
||||
}
|
||||
@ -465,7 +495,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
animateSentNode = animated
|
||||
}
|
||||
checkSentNode.isHidden = false
|
||||
checkSentNode.frame = checkSentFrame.offsetBy(dx: backgroundInsets.left, dy: backgroundInsets.top)
|
||||
checkSentNode.frame = checkSentFrame.offsetBy(dx: backgroundInsets.left + reactionInset, dy: backgroundInsets.top)
|
||||
} else {
|
||||
checkSentNode.isHidden = true
|
||||
}
|
||||
@ -485,7 +515,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
animateReadNode = animated
|
||||
}
|
||||
checkReadNode.isHidden = false
|
||||
checkReadNode.frame = checkReadFrame.offsetBy(dx: backgroundInsets.left, dy: backgroundInsets.top)
|
||||
checkReadNode.frame = checkReadFrame.offsetBy(dx: backgroundInsets.left + reactionInset, dy: backgroundInsets.top)
|
||||
} else {
|
||||
checkReadNode.isHidden = true
|
||||
}
|
||||
@ -502,22 +532,47 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
strongSelf.checkSentNode = nil
|
||||
strongSelf.checkReadNode = nil
|
||||
}
|
||||
|
||||
var reactionOffset: CGFloat = leftInset - reactionInset + backgroundInsets.left
|
||||
for i in 0 ..< reactions.count {
|
||||
let node: StatusReactionNode
|
||||
if strongSelf.reactionNodes.count > i, strongSelf.reactionNodes[i].value == reactions[i].value {
|
||||
node = strongSelf.reactionNodes[i]
|
||||
node.count = Int(reactions[i].count)
|
||||
} else {
|
||||
node = StatusReactionNode(value: reactions[i].value, count: Int(reactions[i].count))
|
||||
if strongSelf.reactionNodes.count > i {
|
||||
strongSelf.reactionNodes[i].removeFromSupernode()
|
||||
strongSelf.reactionNodes[i] = node
|
||||
} else {
|
||||
strongSelf.reactionNodes.append(node)
|
||||
}
|
||||
}
|
||||
if node.supernode == nil {
|
||||
strongSelf.addSubnode(node)
|
||||
}
|
||||
node.frame = CGRect(origin: CGPoint(x: reactionOffset, y: backgroundInsets.top + 1.0 + offset - 3.0), size: CGSize(width: reactionSize, height: reactionSize))
|
||||
reactionOffset += reactionSize
|
||||
}
|
||||
for _ in reactions.count ..< strongSelf.reactionNodes.count {
|
||||
strongSelf.reactionNodes.removeLast().removeFromSupernode()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
static func asyncLayout(_ node: ChatMessageDateAndStatusNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode) {
|
||||
static func asyncLayout(_ node: ChatMessageDateAndStatusNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize, _ reactions: [MessageReaction]) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode) {
|
||||
let currentLayout = node?.asyncLayout()
|
||||
return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize in
|
||||
return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions in
|
||||
let resultNode: ChatMessageDateAndStatusNode
|
||||
let resultSizeAndApply: (CGSize, (Bool) -> Void)
|
||||
if let node = node, let currentLayout = currentLayout {
|
||||
resultNode = node
|
||||
resultSizeAndApply = currentLayout(context, presentationData, edited, impressionCount, dateText, type, constrainedSize)
|
||||
resultSizeAndApply = currentLayout(context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions)
|
||||
} else {
|
||||
resultNode = ChatMessageDateAndStatusNode()
|
||||
resultSizeAndApply = resultNode.asyncLayout()(context, presentationData, edited, impressionCount, dateText, type, constrainedSize)
|
||||
resultSizeAndApply = resultNode.asyncLayout()(context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions)
|
||||
}
|
||||
|
||||
return (resultSizeAndApply.0, { animated in
|
||||
@ -526,4 +581,13 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func reactionNode(value: String) -> (ASImageNode, Int)? {
|
||||
for node in self.reactionNodes {
|
||||
if node.value == value {
|
||||
return (node, node.count)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -117,4 +117,8 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.interactiveFileNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
return self.interactiveFileNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
@ -132,4 +132,8 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
return self.contentNode.transitionNode(media: media)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
return self.contentNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
@ -276,9 +276,22 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let (size, apply) = statusLayout(context, presentationData, edited, viewCount, dateText, statusType, constrainedSize)
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let (size, apply) = statusLayout(context, presentationData, edited, viewCount, dateText, statusType, constrainedSize, dateReactions)
|
||||
statusSize = size
|
||||
statusApply = apply
|
||||
}
|
||||
@ -927,4 +940,11 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
self.playerUpdateTimer?.invalidate()
|
||||
self.playerUpdateTimer = nil
|
||||
}
|
||||
|
||||
func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -246,23 +246,31 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
let edited = false
|
||||
var edited = false
|
||||
let sentViaBot = false
|
||||
var viewCount: Int? = nil
|
||||
for attribute in item.message.attributes {
|
||||
if let _ = attribute as? EditedMessageAttribute {
|
||||
// edited = true
|
||||
if let attribute = attribute as? EditedMessageAttribute {
|
||||
edited = !attribute.isHidden
|
||||
} else if let attribute = attribute as? ViewCountMessageAttribute {
|
||||
viewCount = attribute.count
|
||||
}// else if let _ = attribute as? InlineBotMessageAttribute {
|
||||
// sentViaBot = true
|
||||
// }
|
||||
}
|
||||
}
|
||||
// if let author = item.message.author as? TelegramUser, author.botInfo != nil {
|
||||
// sentViaBot = true
|
||||
// }
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular, reactionCount: dateReactionCount)
|
||||
|
||||
let maxDateAndStatusWidth: CGFloat
|
||||
if case .bubble = statusDisplayType {
|
||||
@ -270,7 +278,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
} else {
|
||||
maxDateAndStatusWidth = width - videoFrame.midX - 85.0
|
||||
}
|
||||
let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited && !sentViaBot, viewCount, dateText, statusType, CGSize(width: max(1.0, maxDateAndStatusWidth), height: CGFloat.greatestFiniteMagnitude))
|
||||
let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited && !sentViaBot, viewCount, dateText, statusType, CGSize(width: max(1.0, maxDateAndStatusWidth), height: CGFloat.greatestFiniteMagnitude), dateReactions)
|
||||
|
||||
var contentSize = imageSize
|
||||
var dateAndStatusOverflow = false
|
||||
|
@ -135,4 +135,8 @@ final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
return self.contentNode.transitionNode(media: media)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
return self.contentNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
@ -181,13 +181,26 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
if let selectedMedia = selectedMedia {
|
||||
if selectedMedia.liveBroadcastingTimeout != nil {
|
||||
edited = false
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let statusType: ChatMessageDateAndStatusType?
|
||||
switch position {
|
||||
@ -225,7 +238,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
var statusApply: ((Bool) -> Void)?
|
||||
|
||||
if let statusType = statusType {
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude))
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude), dateReactions)
|
||||
statusSize = size
|
||||
statusApply = apply
|
||||
}
|
||||
@ -455,4 +468,11 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,20 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let statusType: ChatMessageDateAndStatusType?
|
||||
switch position {
|
||||
@ -192,7 +205,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
var statusApply: ((Bool) -> Void)?
|
||||
|
||||
if let statusType = statusType {
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: imageSize.width - 30.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: imageSize.width - 30.0, height: CGFloat.greatestFiniteMagnitude), dateReactions)
|
||||
statusSize = size
|
||||
statusApply = apply
|
||||
}
|
||||
@ -359,4 +372,11 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -596,7 +596,20 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let statusType: ChatMessageDateAndStatusType?
|
||||
switch position {
|
||||
@ -620,7 +633,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
var statusApply: ((Bool) -> Void)?
|
||||
|
||||
if let statusType = statusType {
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize)
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReactions)
|
||||
statusSize = size
|
||||
statusApply = apply
|
||||
}
|
||||
@ -942,4 +955,11 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
return .none
|
||||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,20 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let statusType: ChatMessageDateAndStatusType?
|
||||
switch position {
|
||||
@ -83,7 +96,7 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
var statusApply: ((Bool) -> Void)?
|
||||
|
||||
if let statusType = statusType {
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize)
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReactions)
|
||||
statusSize = size
|
||||
statusApply = apply
|
||||
}
|
||||
@ -95,7 +108,7 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let textFont = item.presentationData.messageFont
|
||||
let forceStatusNewline = false
|
||||
|
||||
let attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont)
|
||||
let attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor.withAlphaComponent(0.7), linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont)
|
||||
|
||||
var cutout: TextNodeCutout?
|
||||
if let statusSize = statusSize, !forceStatusNewline {
|
||||
@ -230,4 +243,11 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
self.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
self.statusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -265,9 +265,22 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude))
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular, reactionCount: dateReactionCount)
|
||||
|
||||
let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReactions)
|
||||
|
||||
var viaBotApply: (TextNodeLayout, () -> TextNode)?
|
||||
var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)?
|
||||
|
@ -106,7 +106,20 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings)
|
||||
var dateReactions: [MessageReaction] = []
|
||||
var dateReactionCount = 0
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
if reaction.isSelected {
|
||||
dateReactions.insert(reaction, at: 0)
|
||||
} else {
|
||||
dateReactions.append(reaction)
|
||||
}
|
||||
dateReactionCount += Int(reaction.count)
|
||||
}
|
||||
}
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount)
|
||||
|
||||
let statusType: ChatMessageDateAndStatusType?
|
||||
switch position {
|
||||
@ -130,7 +143,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
var statusApply: ((Bool) -> Void)?
|
||||
|
||||
if let statusType = statusType {
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize)
|
||||
let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReactions)
|
||||
statusSize = size
|
||||
statusApply = apply
|
||||
}
|
||||
@ -158,20 +171,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
rawText = item.presentationData.strings.Conversation_UnsupportedMediaPlaceholder
|
||||
messageEntities = [MessageTextEntity(range: 0..<rawText.count, type: .Italic)]
|
||||
} else {
|
||||
var reactionsString = ""
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty {
|
||||
reactionsString += "\n\nReactions:"
|
||||
|
||||
for reaction in reactionsAttribute.reactions {
|
||||
reactionsString += "\n[\(reaction.value)"
|
||||
if reaction.isSelected {
|
||||
reactionsString += "✓"
|
||||
}
|
||||
reactionsString += "]"
|
||||
}
|
||||
}
|
||||
|
||||
rawText = item.message.text + reactionsString
|
||||
rawText = item.message.text
|
||||
|
||||
for attribute in item.message.attributes {
|
||||
if let attribute = attribute as? TextEntitiesMessageAttribute {
|
||||
@ -540,4 +540,11 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -487,4 +487,8 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let contentNodeFrame = self.contentNode.frame
|
||||
self.contentNode.updateTouchesAtPoint(point.flatMap { $0.offsetBy(dx: -contentNodeFrame.minX, dy: -contentNodeFrame.minY) })
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
return self.contentNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
@ -236,6 +236,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
return self?.getNavigationController()
|
||||
}, chatControllerNode: { [weak self] in
|
||||
return self
|
||||
}, reactionContainerNode: {
|
||||
return nil
|
||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in }, longTap: { [weak self] action, message in
|
||||
if let strongSelf = self {
|
||||
switch action {
|
||||
@ -408,6 +410,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
}, sendScheduledMessagesNow: { _ in
|
||||
}, editScheduledMessagesTime: { _ in
|
||||
}, performTextSelectionAction: { _, _, _ in
|
||||
}, updateMessageReaction: { _, _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||
|
@ -90,6 +90,8 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
||||
return nil
|
||||
}, chatControllerNode: {
|
||||
return nil
|
||||
}, reactionContainerNode: {
|
||||
return nil
|
||||
}, presentGlobalOverlayController: { _, _ in
|
||||
}, callPeer: { _ in
|
||||
}, longTap: { _, _ in
|
||||
@ -110,6 +112,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
||||
}, sendScheduledMessagesNow: { _ in
|
||||
}, editScheduledMessagesTime: { _ in
|
||||
}, performTextSelectionAction: { _, _, _ in
|
||||
}, updateMessageReaction: { _, _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||
|
@ -219,6 +219,8 @@ public class PeerMediaCollectionController: TelegramBaseController {
|
||||
return nil
|
||||
}, chatControllerNode: {
|
||||
return nil
|
||||
}, reactionContainerNode: {
|
||||
return nil
|
||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in
|
||||
}, longTap: { [weak self] content, _ in
|
||||
if let strongSelf = self {
|
||||
@ -284,6 +286,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
|
||||
}, sendScheduledMessagesNow: { _ in
|
||||
}, editScheduledMessagesTime: { _ in
|
||||
}, performTextSelectionAction: { _, _, _ in
|
||||
}, updateMessageReaction: { _, _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -11,7 +11,7 @@ enum MessageTimestampStatusFormat {
|
||||
case minimal
|
||||
}
|
||||
|
||||
func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, strings: PresentationStrings, format: MessageTimestampStatusFormat = .regular) -> String {
|
||||
func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, strings: PresentationStrings, format: MessageTimestampStatusFormat = .regular, reactionCount: Int) -> String {
|
||||
let timestamp: Int32
|
||||
if let scheduleTime = message.scheduleTime {
|
||||
timestamp = scheduleTime
|
||||
|
@ -195,6 +195,7 @@
|
||||
D03E449E2305B6A00049C28B /* WatchBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E449D2305B6A00049C28B /* WatchBridge.framework */; };
|
||||
D03E44E22305BC900049C28B /* LegacyDataImport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E44E12305BC900049C28B /* LegacyDataImport.framework */; };
|
||||
D03E45252305C07A0049C28B /* ShareItems.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E45242305C07A0049C28B /* ShareItems.framework */; };
|
||||
D03E46102305FD360049C28B /* ReactionSelectionNode.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E460F2305FD360049C28B /* ReactionSelectionNode.framework */; };
|
||||
D04203152037162700490EA5 /* MediaInputPaneTrendingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04203142037162700490EA5 /* MediaInputPaneTrendingItem.swift */; };
|
||||
D04281F4200E5AB0009DDE36 /* ChatRecentActionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04281F3200E5AB0009DDE36 /* ChatRecentActionsController.swift */; };
|
||||
D04281F6200E5AC2009DDE36 /* ChatRecentActionsControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04281F5200E5AC2009DDE36 /* ChatRecentActionsControllerNode.swift */; };
|
||||
@ -915,6 +916,7 @@
|
||||
D03E449D2305B6A00049C28B /* WatchBridge.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = WatchBridge.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E44E12305BC900049C28B /* LegacyDataImport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LegacyDataImport.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E45242305C07A0049C28B /* ShareItems.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ShareItems.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E460F2305FD360049C28B /* ReactionSelectionNode.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ReactionSelectionNode.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E5E081E55C49C0029569A /* DebugAccountsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugAccountsController.swift; sourceTree = "<group>"; };
|
||||
D04203142037162700490EA5 /* MediaInputPaneTrendingItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaInputPaneTrendingItem.swift; sourceTree = "<group>"; };
|
||||
D04281F3200E5AB0009DDE36 /* ChatRecentActionsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatRecentActionsController.swift; sourceTree = "<group>"; };
|
||||
@ -1377,6 +1379,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E46102305FD360049C28B /* ReactionSelectionNode.framework in Frameworks */,
|
||||
D03E45252305C07A0049C28B /* ShareItems.framework in Frameworks */,
|
||||
D03E44E22305BC900049C28B /* LegacyDataImport.framework in Frameworks */,
|
||||
D03E449E2305B6A00049C28B /* WatchBridge.framework in Frameworks */,
|
||||
@ -2085,6 +2088,7 @@
|
||||
D08D45281D5E340200A7428A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E460F2305FD360049C28B /* ReactionSelectionNode.framework */,
|
||||
D03E45242305C07A0049C28B /* ShareItems.framework */,
|
||||
D03E44E12305BC900049C28B /* LegacyDataImport.framework */,
|
||||
D03E449D2305B6A00049C28B /* WatchBridge.framework */,
|
||||
|
@ -29,6 +29,7 @@
|
||||
D03E44982305B6810049C28B /* StickerResources.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E44972305B6810049C28B /* StickerResources.framework */; };
|
||||
D03E449A2305B6850049C28B /* PhotoResources.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E44992305B6850049C28B /* PhotoResources.framework */; };
|
||||
D03E449C2305B6910049C28B /* LegacyComponents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E449B2305B6910049C28B /* LegacyComponents.framework */; };
|
||||
D03E4641230750150049C28B /* LegacyUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03E4640230750150049C28B /* LegacyUI.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -56,6 +57,7 @@
|
||||
D03E44972305B6810049C28B /* StickerResources.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = StickerResources.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E44992305B6850049C28B /* PhotoResources.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PhotoResources.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E449B2305B6910049C28B /* LegacyComponents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LegacyComponents.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E4640230750150049C28B /* LegacyUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LegacyUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -63,6 +65,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E4641230750150049C28B /* LegacyUI.framework in Frameworks */,
|
||||
D03E449C2305B6910049C28B /* LegacyComponents.framework in Frameworks */,
|
||||
D03E449A2305B6850049C28B /* PhotoResources.framework in Frameworks */,
|
||||
D03E44982305B6810049C28B /* StickerResources.framework in Frameworks */,
|
||||
@ -119,6 +122,7 @@
|
||||
D03E447C2305B6170049C28B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E4640230750150049C28B /* LegacyUI.framework */,
|
||||
D03E449B2305B6910049C28B /* LegacyComponents.framework */,
|
||||
D03E44992305B6850049C28B /* PhotoResources.framework */,
|
||||
D03E44972305B6810049C28B /* StickerResources.framework */,
|
||||
|
@ -34,7 +34,11 @@
|
||||
#define SQLITE3_H
|
||||
#include <stdarg.h> /* Needed for the definition of va_list */
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
#include <sqlcipher/sqlcipher_config.h>
|
||||
#else
|
||||
#include <sqlciphermac/sqlcipher_config.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Make sure we can call this stuff from C++.
|
||||
|
@ -17,7 +17,12 @@
|
||||
*/
|
||||
#ifndef SQLITE3EXT_H
|
||||
#define SQLITE3EXT_H
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
#include <sqlcipher/sqlite3.h>
|
||||
#else
|
||||
#include <sqlciphermac/sqlite3.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following structure holds pointers to all of the SQLite API
|
||||
|
@ -15,6 +15,13 @@
|
||||
D03E45542305C7600049C28B /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E454E2305C7600049C28B /* SQLite-Bridging.h */; };
|
||||
D03E45552305C7600049C28B /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E454F2305C7600049C28B /* fts3_tokenizer.h */; };
|
||||
D03E45592305C8090049C28B /* sqlcipher_config.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E45582305C8090049C28B /* sqlcipher_config.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D03E461A2306DF740049C28B /* sqlciphermac.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E46182306DF740049C28B /* sqlciphermac.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D03E46202306DF830049C28B /* sqlcipher_config.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E45582305C8090049C28B /* sqlcipher_config.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D03E46212306DF8A0049C28B /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E454F2305C7600049C28B /* fts3_tokenizer.h */; };
|
||||
D03E46222306DF8D0049C28B /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E454E2305C7600049C28B /* SQLite-Bridging.h */; };
|
||||
D03E46232306DF920049C28B /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E454C2305C75F0049C28B /* sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D03E46252306DF9A0049C28B /* sqlite3ext.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E454D2305C7600049C28B /* sqlite3ext.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D03E46262306DFA00049C28B /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = D03E454B2305C75F0049C28B /* sqlite3.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -28,6 +35,9 @@
|
||||
D03E454E2305C7600049C28B /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SQLite-Bridging.h"; sourceTree = "<group>"; };
|
||||
D03E454F2305C7600049C28B /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fts3_tokenizer.h; sourceTree = "<group>"; };
|
||||
D03E45582305C8090049C28B /* sqlcipher_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sqlcipher_config.h; sourceTree = "<group>"; };
|
||||
D03E46162306DF740049C28B /* sqlciphermac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = sqlciphermac.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E46182306DF740049C28B /* sqlciphermac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sqlciphermac.h; sourceTree = "<group>"; };
|
||||
D03E46192306DF740049C28B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -38,6 +48,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E46132306DF740049C28B /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@ -46,6 +63,7 @@
|
||||
children = (
|
||||
D03E453F2305C6E40049C28B /* Info.plist */,
|
||||
D03E453D2305C6E40049C28B /* Sources */,
|
||||
D03E46172306DF740049C28B /* sqlciphermac */,
|
||||
D03E453C2305C6E40049C28B /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
@ -54,6 +72,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E453B2305C6E40049C28B /* sqlcipher.framework */,
|
||||
D03E46162306DF740049C28B /* sqlciphermac.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -73,6 +92,15 @@
|
||||
path = Sources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D03E46172306DF740049C28B /* sqlciphermac */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03E46182306DF740049C28B /* sqlciphermac.h */,
|
||||
D03E46192306DF740049C28B /* Info.plist */,
|
||||
);
|
||||
path = sqlciphermac;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@ -89,6 +117,19 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E46112306DF740049C28B /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E46222306DF8D0049C28B /* SQLite-Bridging.h in Headers */,
|
||||
D03E46252306DF9A0049C28B /* sqlite3ext.h in Headers */,
|
||||
D03E46212306DF8A0049C28B /* fts3_tokenizer.h in Headers */,
|
||||
D03E46202306DF830049C28B /* sqlcipher_config.h in Headers */,
|
||||
D03E461A2306DF740049C28B /* sqlciphermac.h in Headers */,
|
||||
D03E46232306DF920049C28B /* sqlite3.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -110,6 +151,24 @@
|
||||
productReference = D03E453B2305C6E40049C28B /* sqlcipher.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
D03E46152306DF740049C28B /* sqlciphermac */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D03E461F2306DF740049C28B /* Build configuration list for PBXNativeTarget "sqlciphermac" */;
|
||||
buildPhases = (
|
||||
D03E46112306DF740049C28B /* Headers */,
|
||||
D03E46122306DF740049C28B /* Sources */,
|
||||
D03E46132306DF740049C28B /* Frameworks */,
|
||||
D03E46142306DF740049C28B /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = sqlciphermac;
|
||||
productName = sqlciphermac;
|
||||
productReference = D03E46162306DF740049C28B /* sqlciphermac.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@ -123,6 +182,9 @@
|
||||
D03E453A2305C6E40049C28B = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
};
|
||||
D03E46152306DF740049C28B = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D03E45352305C6E40049C28B /* Build configuration list for PBXProject "sqlcipher_Xcode" */;
|
||||
@ -138,6 +200,7 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
D03E453A2305C6E40049C28B /* sqlcipher */,
|
||||
D03E46152306DF740049C28B /* sqlciphermac */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -150,6 +213,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E46142306DF740049C28B /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@ -162,6 +232,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D03E46122306DF740049C28B /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03E46262306DFA00049C28B /* sqlite3.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
@ -218,6 +296,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@ -274,6 +353,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -402,6 +482,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@ -491,6 +572,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -533,6 +615,344 @@
|
||||
};
|
||||
name = ReleaseHockeyappInternal;
|
||||
};
|
||||
D03E461B2306DF740049C28B /* DebugAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = sqlciphermac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = (
|
||||
"-DSQLITE_HAS_CODEC=1",
|
||||
"-DSQLCIPHER_CRYPTO_CC=1",
|
||||
"-DSQLITE_ENABLE_FTS5",
|
||||
"-DSQLITE_DEFAULT_MEMSTATUS=0",
|
||||
"-DNDEBUG",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.sqlciphermac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = DebugAppStoreLLC;
|
||||
};
|
||||
D03E461C2306DF740049C28B /* DebugHockeyapp */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = sqlciphermac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = (
|
||||
"-DSQLITE_HAS_CODEC=1",
|
||||
"-DSQLCIPHER_CRYPTO_CC=1",
|
||||
"-DSQLITE_ENABLE_FTS5",
|
||||
"-DSQLITE_DEFAULT_MEMSTATUS=0",
|
||||
"-DNDEBUG",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.sqlciphermac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = DebugHockeyapp;
|
||||
};
|
||||
D03E461D2306DF740049C28B /* ReleaseAppStoreLLC */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = sqlciphermac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_CFLAGS = (
|
||||
"-DSQLITE_HAS_CODEC=1",
|
||||
"-DSQLCIPHER_CRYPTO_CC=1",
|
||||
"-DSQLITE_ENABLE_FTS5",
|
||||
"-DSQLITE_DEFAULT_MEMSTATUS=0",
|
||||
"-DNDEBUG",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.sqlciphermac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = ReleaseAppStoreLLC;
|
||||
};
|
||||
D03E461E2306DF740049C28B /* ReleaseHockeyappInternal */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = sqlciphermac/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_CFLAGS = (
|
||||
"-DSQLITE_HAS_CODEC=1",
|
||||
"-DSQLCIPHER_CRYPTO_CC=1",
|
||||
"-DSQLITE_ENABLE_FTS5",
|
||||
"-DSQLITE_DEFAULT_MEMSTATUS=0",
|
||||
"-DNDEBUG",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.sqlciphermac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = ReleaseHockeyappInternal;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@ -558,6 +978,17 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = ReleaseAppStoreLLC;
|
||||
};
|
||||
D03E461F2306DF740049C28B /* Build configuration list for PBXNativeTarget "sqlciphermac" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D03E461B2306DF740049C28B /* DebugAppStoreLLC */,
|
||||
D03E461C2306DF740049C28B /* DebugHockeyapp */,
|
||||
D03E461D2306DF740049C28B /* ReleaseAppStoreLLC */,
|
||||
D03E461E2306DF740049C28B /* ReleaseHockeyappInternal */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = ReleaseAppStoreLLC;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = D03E45322305C6E40049C28B /* Project object */;
|
||||
|
24
submodules/sqlcipher/sqlciphermac/Info.plist
Normal file
24
submodules/sqlcipher/sqlciphermac/Info.plist
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2019 Telegram Messenger LLP. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
13
submodules/sqlcipher/sqlciphermac/sqlciphermac.h
Normal file
13
submodules/sqlcipher/sqlciphermac/sqlciphermac.h
Normal file
@ -0,0 +1,13 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
//! Project version number for sqlciphermac.
|
||||
FOUNDATION_EXPORT double sqlciphermacVersionNumber;
|
||||
|
||||
//! Project version string for sqlciphermac.
|
||||
FOUNDATION_EXPORT const unsigned char sqlciphermacVersionString[];
|
||||
|
||||
#import <sqlciphermac/sqlcipher_config.h>
|
||||
#import <sqlciphermac/sqlite3.h>
|
||||
#import <sqlciphermac/sqlite3ext.h>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user