diff --git a/Display.xcodeproj/project.pbxproj b/Display.xcodeproj/project.pbxproj index 94fec9abf4..4b8df465e5 100644 --- a/Display.xcodeproj/project.pbxproj +++ b/Display.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ D0078A681C92B21400DF6D92 /* StatusBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0078A671C92B21400DF6D92 /* StatusBar.swift */; }; D00C7CD21E3657570080C3D5 /* TextFieldNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00C7CD11E3657570080C3D5 /* TextFieldNode.swift */; }; + D01159BB1F40E96C0039383E /* DisplayMac.h in Headers */ = {isa = PBXBuildFile; fileRef = D01159B91F40E96C0039383E /* DisplayMac.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D01159C21F40EA120039383E /* ListViewScrollerAppkit.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01159C11F40EA120039383E /* ListViewScrollerAppkit.swift */; }; D015F7521D1AE08D00E269B5 /* ContainableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015F7511D1AE08D00E269B5 /* ContainableController.swift */; }; D015F7541D1B0F6C00E269B5 /* SystemContainedControllerTransitionCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015F7531D1B0F6C00E269B5 /* SystemContainedControllerTransitionCoordinator.swift */; }; D015F7581D1B467200E269B5 /* ActionSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015F7571D1B467200E269B5 /* ActionSheetController.swift */; }; @@ -93,6 +95,7 @@ D0C0B59D1EE022CC000F4D2C /* NavigationBarContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B59C1EE022CC000F4D2C /* NavigationBarContentNode.swift */; }; D0C0D28F1C997110001D2851 /* FBAnimationPerformanceTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = D0C0D28D1C997110001D2851 /* FBAnimationPerformanceTracker.h */; settings = {ATTRIBUTES = (Public, ); }; }; D0C0D2901C997110001D2851 /* FBAnimationPerformanceTracker.mm in Sources */ = {isa = PBXBuildFile; fileRef = D0C0D28E1C997110001D2851 /* FBAnimationPerformanceTracker.mm */; }; + D0C12A1A1F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C12A191F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift */; }; D0C2DFC61CC4431D0044FF83 /* ASTransformLayerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C2DFBB1CC4431D0044FF83 /* ASTransformLayerNode.swift */; }; D0C2DFC71CC4431D0044FF83 /* ListViewItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C2DFBC1CC4431D0044FF83 /* ListViewItemNode.swift */; }; D0C2DFC81CC4431D0044FF83 /* Spring.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C2DFBD1CC4431D0044FF83 /* Spring.swift */; }; @@ -137,6 +140,10 @@ /* Begin PBXFileReference section */ D0078A671C92B21400DF6D92 /* StatusBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBar.swift; sourceTree = ""; }; D00C7CD11E3657570080C3D5 /* TextFieldNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldNode.swift; sourceTree = ""; }; + D01159B71F40E96B0039383E /* DisplayMac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DisplayMac.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D01159B91F40E96C0039383E /* DisplayMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayMac.h; sourceTree = ""; }; + D01159BA1F40E96C0039383E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D01159C11F40EA120039383E /* ListViewScrollerAppkit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListViewScrollerAppkit.swift; sourceTree = ""; }; D015F7511D1AE08D00E269B5 /* ContainableController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainableController.swift; sourceTree = ""; }; D015F7531D1B0F6C00E269B5 /* SystemContainedControllerTransitionCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemContainedControllerTransitionCoordinator.swift; sourceTree = ""; }; D015F7571D1B467200E269B5 /* ActionSheetController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionSheetController.swift; sourceTree = ""; }; @@ -224,6 +231,7 @@ D0C0B59C1EE022CC000F4D2C /* NavigationBarContentNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBarContentNode.swift; sourceTree = ""; }; D0C0D28D1C997110001D2851 /* FBAnimationPerformanceTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBAnimationPerformanceTracker.h; sourceTree = ""; }; D0C0D28E1C997110001D2851 /* FBAnimationPerformanceTracker.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FBAnimationPerformanceTracker.mm; sourceTree = ""; }; + D0C12A191F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBarTitleTransitionNode.swift; sourceTree = ""; }; D0C2DFBB1CC4431D0044FF83 /* ASTransformLayerNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASTransformLayerNode.swift; sourceTree = ""; }; D0C2DFBC1CC4431D0044FF83 /* ListViewItemNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListViewItemNode.swift; sourceTree = ""; }; D0C2DFBD1CC4431D0044FF83 /* Spring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spring.swift; sourceTree = ""; }; @@ -257,6 +265,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + D01159B31F40E96B0039383E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D05CC25F1B69316F00E235A3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -277,6 +292,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + D01159B81F40E96C0039383E /* DisplayMac */ = { + isa = PBXGroup; + children = ( + D01159B91F40E96C0039383E /* DisplayMac.h */, + D01159BA1F40E96C0039383E /* Info.plist */, + ); + path = DisplayMac; + sourceTree = ""; + }; D015F7501D1ADC6800E269B5 /* Window */ = { isa = PBXGroup; children = ( @@ -381,6 +405,7 @@ D05CC2591B69316F00E235A3 = { isa = PBXGroup; children = ( + D01159B81F40E96C0039383E /* DisplayMac */, D05CC2A31B6932D500E235A3 /* Frameworks */, D05CC2651B69316F00E235A3 /* Display */, D05CC2711B69316F00E235A3 /* DisplayTests */, @@ -393,6 +418,7 @@ children = ( D05CC2631B69316F00E235A3 /* Display.framework */, D05CC26D1B69316F00E235A3 /* DisplayTests.xctest */, + D01159B71F40E96B0039383E /* DisplayMac.framework */, ); name = Products; sourceTree = ""; @@ -493,6 +519,7 @@ D05CC30D1B695A9500E235A3 /* NavigationBackButtonNode.swift */, D05CC30E1B695A9500E235A3 /* NavigationButtonNode.swift */, D05CC30F1B695A9500E235A3 /* NavigationTitleNode.swift */, + D0C12A191F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift */, D05CC3101B695A9600E235A3 /* BarButtonItemWrapper.swift */, D05CC3281B69750D00E235A3 /* InteractiveTransitionGestureRecognizer.swift */, D0AE3D4C1D25C816001CCE13 /* NavigationBarTransitionState.swift */, @@ -561,6 +588,7 @@ D0C2DFC21CC4431D0044FF83 /* ListViewTransactionQueue.swift */, D0C2DFC31CC4431D0044FF83 /* ListViewAccessoryItem.swift */, D0C2DFC41CC4431D0044FF83 /* ListViewScroller.swift */, + D01159C11F40EA120039383E /* ListViewScrollerAppkit.swift */, D0C2DFC51CC4431D0044FF83 /* ListViewAccessoryItemNode.swift */, D0F7AB361DCFF6F8009AD9A1 /* ListViewItemHeader.swift */, ); @@ -605,6 +633,14 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + D01159B41F40E96B0039383E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D01159BB1F40E96C0039383E /* DisplayMac.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D05CC2601B69316F00E235A3 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -630,6 +666,24 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + D01159B61F40E96B0039383E /* DisplayMac */ = { + isa = PBXNativeTarget; + buildConfigurationList = D01159C01F40E96C0039383E /* Build configuration list for PBXNativeTarget "DisplayMac" */; + buildPhases = ( + D01159B21F40E96B0039383E /* Sources */, + D01159B31F40E96B0039383E /* Frameworks */, + D01159B41F40E96B0039383E /* Headers */, + D01159B51F40E96B0039383E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DisplayMac; + productName = DisplayMac; + productReference = D01159B71F40E96B0039383E /* DisplayMac.framework */; + productType = "com.apple.product-type.framework"; + }; D05CC2621B69316F00E235A3 /* Display */ = { isa = PBXNativeTarget; buildConfigurationList = D05CC2771B69316F00E235A3 /* Build configuration list for PBXNativeTarget "Display" */; @@ -676,6 +730,12 @@ LastUpgradeCheck = 0800; ORGANIZATIONNAME = Telegram; TargetAttributes = { + D01159B61F40E96B0039383E = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = X834Q8SBVP; + LastSwiftMigration = 0830; + ProvisioningStyle = Automatic; + }; D05CC2621B69316F00E235A3 = { CreatedOnToolsVersion = 7.0; ProvisioningStyle = Manual; @@ -699,11 +759,19 @@ targets = ( D05CC2621B69316F00E235A3 /* Display */, D05CC26C1B69316F00E235A3 /* DisplayTests */, + D01159B61F40E96B0039383E /* DisplayMac */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + D01159B51F40E96B0039383E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D05CC2611B69316F00E235A3 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -723,6 +791,14 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + D01159B21F40E96B0039383E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D01159C21F40EA120039383E /* ListViewScrollerAppkit.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D05CC25E1B69316F00E235A3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -779,6 +855,7 @@ D05CC2FA1B6955D000E235A3 /* UINavigationItem+Proxy.m in Sources */, D096A4501EA64F580000A7AE /* ActionSheetCheckboxItem.swift in Sources */, D0C2DFCE1CC4431D0044FF83 /* ListViewAccessoryItem.swift in Sources */, + D0C12A1A1F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift in Sources */, D0A749951E3A9E7B00AD786E /* SwitchNode.swift in Sources */, D03725C51D6DF8B9007FC290 /* ContextMenuController.swift in Sources */, D03725C31D6DF7A6007FC290 /* ContextMenuAction.swift in Sources */, @@ -843,6 +920,254 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + D01159BC1F40E96C0039383E /* Debug Hockeyapp */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = X834Q8SBVP; + 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 = gnu99; + 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 = DisplayMac/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = org.Telegram.DisplayMac; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = "Debug Hockeyapp"; + }; + D01159BD1F40E96C0039383E /* Debug AppStore */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = X834Q8SBVP; + 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 = gnu99; + 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 = DisplayMac/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = org.Telegram.DisplayMac; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = "Debug AppStore"; + }; + D01159BE1F40E96C0039383E /* Release Hockeyapp */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = X834Q8SBVP; + 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 = gnu99; + 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 = DisplayMac/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = org.Telegram.DisplayMac; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = "Release Hockeyapp"; + }; + D01159BF1F40E96C0039383E /* Release AppStore */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = X834Q8SBVP; + 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 = gnu99; + 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 = DisplayMac/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = org.Telegram.DisplayMac; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = "Release AppStore"; + }; D05CC2751B69316F00E235A3 /* Debug Hockeyapp */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1173,6 +1498,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + D01159C01F40E96C0039383E /* Build configuration list for PBXNativeTarget "DisplayMac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D01159BC1F40E96C0039383E /* Debug Hockeyapp */, + D01159BD1F40E96C0039383E /* Debug AppStore */, + D01159BE1F40E96C0039383E /* Release Hockeyapp */, + D01159BF1F40E96C0039383E /* Release AppStore */, + ); + defaultConfigurationIsVisible = 0; + }; D05CC25D1B69316F00E235A3 /* Build configuration list for PBXProject "Display" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Display.xcodeproj/xcuserdata/peter.xcuserdatad/xcschemes/xcschememanagement.plist b/Display.xcodeproj/xcuserdata/peter.xcuserdatad/xcschemes/xcschememanagement.plist index 3cff77364e..7a4a41da85 100644 --- a/Display.xcodeproj/xcuserdata/peter.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Display.xcodeproj/xcuserdata/peter.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,16 +7,26 @@ Display.xcscheme orderHint - 24 + 22 - DisplayTests.xcscheme + DisplayMac.xcscheme orderHint 25 + DisplayTests.xcscheme + + orderHint + 23 + SuppressBuildableAutocreation + D01159B61F40E96B0039383E + + primary + + D05CC2621B69316F00E235A3 primary diff --git a/Display/ASTransformLayerNode.swift b/Display/ASTransformLayerNode.swift index 0e204e8074..6e8fa21298 100644 --- a/Display/ASTransformLayerNode.swift +++ b/Display/ASTransformLayerNode.swift @@ -33,30 +33,36 @@ class ASTransformView: UIView { open class ASTransformLayerNode: ASDisplayNode { public override init() { - super.init(layerBlock: { + super.init() + self.setLayerBlock({ return ASTransformLayer() - }, didLoad: nil) + }) } } open class ASTransformViewNode: ASDisplayNode { public override init() { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return ASTransformView() - }, didLoad: nil) + }) } } open class ASTransformNode: ASDisplayNode { public init(layerBacked: Bool = true) { if layerBacked { - super.init(layerBlock: { + super.init() + self.setLayerBlock({ return ASTransformLayer() - }, didLoad: nil) + }) } else { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return ASTransformView() - }, didLoad: nil) + }) } } } diff --git a/Display/AlertControllerNode.swift b/Display/AlertControllerNode.swift index 02c9719d36..bab1916e40 100644 --- a/Display/AlertControllerNode.swift +++ b/Display/AlertControllerNode.swift @@ -21,7 +21,7 @@ final class AlertControllerNode: ASDisplayNode { self.effectNode = ASDisplayNode(viewBlock: { let view = UIView()//UIVisualEffectView(effect: UIBlurEffect(style: .light)) return view - }, didLoad: nil) + }) self.contentNode = contentNode diff --git a/Display/ContainableController.swift b/Display/ContainableController.swift index a5a02e8400..33c728f4d8 100644 --- a/Display/ContainableController.swift +++ b/Display/ContainableController.swift @@ -15,6 +15,15 @@ public extension ContainedViewLayoutTransitionCurve { return kCAMediaTimingFunctionSpring } } + + var viewAnimationOptions: UIViewAnimationOptions { + switch self { + case .easeInOut: + return [.curveEaseInOut] + case .spring: + return UIViewAnimationOptions(rawValue: 7 << 16) + } + } } public enum ContainedViewLayoutTransition { @@ -251,6 +260,44 @@ public extension ContainedViewLayoutTransition { } } + func updateTransformScale(node: ASDisplayNode, scale: CGFloat, 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) { + if let completion = completion { + completion(true) + } + return + } + + switch self { + case .immediate: + node.layer.transform = CATransform3DMakeScale(scale, scale, 1.0) + if let completion = completion { + completion(true) + } + case let .animated(duration, curve): + node.layer.transform = CATransform3DMakeScale(scale, scale, 1.0) + node.layer.animateScale(from: currentScale, to: scale, duration: duration, timingFunction: curve.timingFunction, completion: { result in + if let completion = completion { + completion(result) + } + }) + } + } +} + +public extension ContainedViewLayoutTransition { + public func animateView(_ f: @escaping () -> Void) { + switch self { + case .immediate: + f() + case let .animated(duration, curve): + UIView.animate(withDuration: duration, delay: 0.0, options: curve.viewAnimationOptions, animations: { + f() + }, completion: nil) + } + } } public protocol ContainableController: class { diff --git a/Display/ContextMenuAction.swift b/Display/ContextMenuAction.swift index 898a8db7c1..1aa73ccc42 100644 --- a/Display/ContextMenuAction.swift +++ b/Display/ContextMenuAction.swift @@ -1,6 +1,7 @@ public enum ContextMenuActionContent { case text(String) + case icon(UIImage) } public struct ContextMenuAction { diff --git a/Display/ContextMenuActionNode.swift b/Display/ContextMenuActionNode.swift index 8e7b91ce68..9325ce0db9 100644 --- a/Display/ContextMenuActionNode.swift +++ b/Display/ContextMenuActionNode.swift @@ -2,17 +2,31 @@ import Foundation import AsyncDisplayKit final class ContextMenuActionNode: ASDisplayNode { - private let textNode: ASTextNode + private let textNode: ASTextNode? + private let iconNode: ASImageNode? private let action: () -> Void private let button: HighlightTrackingButton var dismiss: (() -> Void)? init(action: ContextMenuAction) { - self.textNode = ASTextNode() switch action.content { case let .text(title): - self.textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: UIColor.white) + let textNode = ASTextNode() + textNode.isLayerBacked = true + textNode.displaysAsynchronously = false + textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: UIColor.white) + + self.textNode = textNode + self.iconNode = nil + case let .icon(image): + let iconNode = ASImageNode() + iconNode.displaysAsynchronously = false + iconNode.displayWithoutProcessing = true + iconNode.image = image + + self.iconNode = iconNode + self.textNode = nil } self.action = action.action @@ -21,7 +35,12 @@ final class ContextMenuActionNode: ASDisplayNode { super.init() self.backgroundColor = UIColor(white: 0.0, alpha: 0.8) - self.addSubnode(self.textNode) + if let textNode = self.textNode { + self.addSubnode(textNode) + } + if let iconNode = self.iconNode { + self.addSubnode(iconNode) + } self.button.highligthedChanged = { [weak self] highlighted in self?.backgroundColor = highlighted ? UIColor(white: 0.0, alpha: 0.4) : UIColor(white: 0.0, alpha: 0.8) @@ -45,14 +64,26 @@ final class ContextMenuActionNode: ASDisplayNode { } override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { - let textSize = self.textNode.measure(constrainedSize) - return CGSize(width: textSize.width + 36.0, height: 54.0) + if let textNode = self.textNode { + let textSize = textNode.measure(constrainedSize) + return CGSize(width: textSize.width + 36.0, height: 54.0) + } else if let iconNode = self.iconNode, let image = iconNode.image { + return CGSize(width: image.size.width + 36.0, height: 54.0) + } else { + return CGSize(width: 36.0, height: 54.0) + } } override func layout() { super.layout() self.button.frame = self.bounds - self.textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - self.textNode.calculatedSize.width) / 2.0), y: floor((self.bounds.size.height - self.textNode.calculatedSize.height) / 2.0)), size: self.textNode.calculatedSize) + if let textNode = self.textNode { + textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - textNode.calculatedSize.width) / 2.0), y: floor((self.bounds.size.height - textNode.calculatedSize.height) / 2.0)), size: textNode.calculatedSize) + } + if let iconNode = self.iconNode, let image = iconNode.image { + let iconSize = image.size + iconNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - iconSize.width) / 2.0), y: floor((self.bounds.size.height - iconSize.height) / 2.0)), size: iconSize) + } } } diff --git a/Display/GridNode.swift b/Display/GridNode.swift index e5f0697de3..af791c7628 100644 --- a/Display/GridNode.swift +++ b/Display/GridNode.swift @@ -15,10 +15,12 @@ public struct GridNodeInsertItem { public struct GridNodeUpdateItem { public let index: Int + public let previousIndex: Int public let item: GridItem - public init(index: Int, item: GridItem) { + public init(index: Int, previousIndex: Int, item: GridItem) { self.index = index + self.previousIndex = previousIndex self.item = item } } @@ -139,15 +141,17 @@ public struct GridNodeTransaction { public let updateItems: [GridNodeUpdateItem] public let scrollToItem: GridNodeScrollToItem? public let updateLayout: GridNodeUpdateLayout? + public let itemTransition: ContainedViewLayoutTransition public let stationaryItems: GridNodeStationaryItems public let updateFirstIndexInSectionOffset: Int? - public init(deleteItems: [Int], insertItems: [GridNodeInsertItem], updateItems: [GridNodeUpdateItem], scrollToItem: GridNodeScrollToItem?, updateLayout: GridNodeUpdateLayout?, stationaryItems: GridNodeStationaryItems, updateFirstIndexInSectionOffset: Int?) { + public init(deleteItems: [Int], insertItems: [GridNodeInsertItem], updateItems: [GridNodeUpdateItem], scrollToItem: GridNodeScrollToItem?, updateLayout: GridNodeUpdateLayout?, itemTransition: ContainedViewLayoutTransition, stationaryItems: GridNodeStationaryItems, updateFirstIndexInSectionOffset: Int?) { self.deleteItems = deleteItems self.insertItems = insertItems self.updateItems = updateItems self.scrollToItem = scrollToItem self.updateLayout = updateLayout + self.itemTransition = itemTransition self.stationaryItems = stationaryItems self.updateFirstIndexInSectionOffset = updateFirstIndexInSectionOffset } @@ -300,8 +304,8 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { } for updatedItem in transaction.updateItems { - self.items[updatedItem.index] = updatedItem.item - if let itemNode = self.itemNodes[updatedItem.index] { + self.items[updatedItem.previousIndex] = updatedItem.item + if let itemNode = self.itemNodes[updatedItem.previousIndex] { updatedItem.item.update(node: itemNode) } } @@ -377,7 +381,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { generatedScrollToItem = nil } - self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(stationaryItems: transaction.stationaryItems, layoutTransactionOffset: layoutTransactionOffset, scrollToItem: generatedScrollToItem), removedNodes: removedNodes, updateLayoutTransition: transaction.updateLayout?.transition, completion: completion) + self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(stationaryItems: transaction.stationaryItems, layoutTransactionOffset: layoutTransactionOffset, scrollToItem: generatedScrollToItem), removedNodes: removedNodes, updateLayoutTransition: transaction.updateLayout?.transition, itemTransition: transaction.itemTransition, completion: completion) } public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { @@ -396,7 +400,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { public func scrollViewDidScroll(_ scrollView: UIScrollView) { if !self.applyingContentOffset { - self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(layoutTransactionOffset: 0.0), removedNodes: [], updateLayoutTransition: nil, completion: { _ in }) + self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(layoutTransactionOffset: 0.0), removedNodes: [], updateLayoutTransition: nil, itemTransition: .immediate, completion: { _ in }) } } @@ -736,25 +740,33 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { return lowestHeaderNode } - private func applyPresentaionLayoutTransition(_ presentationLayoutTransition: GridNodePresentationLayoutTransition, removedNodes: [GridItemNode], updateLayoutTransition: ContainedViewLayoutTransition?, completion: (GridNodeDisplayedItemRange) -> Void) { - var previousItemFrames: ([WrappedGridItemNode: CGRect])? + private func applyPresentaionLayoutTransition(_ presentationLayoutTransition: GridNodePresentationLayoutTransition, removedNodes: [GridItemNode], updateLayoutTransition: ContainedViewLayoutTransition?, itemTransition: ContainedViewLayoutTransition, completion: (GridNodeDisplayedItemRange) -> Void) { + var previousItemFrames: [WrappedGridItemNode: CGRect]? + var saveItemFrames = false switch presentationLayoutTransition.transition { case .animated: - var itemFrames: [WrappedGridItemNode: CGRect] = [:] - let contentOffset = self.scrollView.contentOffset - for (_, itemNode) in self.itemNodes { - itemFrames[WrappedGridItemNode(node: itemNode)] = itemNode.frame.offsetBy(dx: 0.0, dy: -contentOffset.y) - } - for (_, sectionNode) in self.sectionNodes { - itemFrames[WrappedGridItemNode(node: sectionNode)] = sectionNode.frame.offsetBy(dx: 0.0, dy: -contentOffset.y) - } - for itemNode in removedNodes { - itemFrames[WrappedGridItemNode(node: itemNode)] = itemNode.frame.offsetBy(dx: 0.0, dy: -contentOffset.y) - } - previousItemFrames = itemFrames + saveItemFrames = true case .immediate: break } + if case .animated = itemTransition { + saveItemFrames = true + } + + if saveItemFrames { + var itemFrames: [WrappedGridItemNode: CGRect] = [:] + let contentOffset = self.scrollView.contentOffset + for (_, itemNode) in self.itemNodes { + itemFrames[WrappedGridItemNode(node: itemNode)] = itemNode.frame.offsetBy(dx: 0.0, dy: -contentOffset.y) + } + for (_, sectionNode) in self.sectionNodes { + itemFrames[WrappedGridItemNode(node: sectionNode)] = sectionNode.frame.offsetBy(dx: 0.0, dy: -contentOffset.y) + } + for itemNode in removedNodes { + itemFrames[WrappedGridItemNode(node: itemNode)] = itemNode.frame.offsetBy(dx: 0.0, dy: -contentOffset.y) + } + previousItemFrames = itemFrames + } applyingContentOffset = true @@ -941,6 +953,63 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { itemNode.removeFromSupernode() } } + } else if let previousItemFrames = previousItemFrames, case let .animated(duration, curve) = itemTransition { + let timingFunction: String + switch curve { + case .easeInOut: + timingFunction = kCAMediaTimingFunctionEaseInEaseOut + case .spring: + timingFunction = kCAMediaTimingFunctionSpring + } + + for index in self.itemNodes.keys { + let itemNode = self.itemNodes[index]! + if !existingItemIndices.contains(index) { + if let _ = previousItemFrames[WrappedGridItemNode(node: itemNode)] { + self.removeItemNodeWithIndex(index, removeNode: false) + itemNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionEaseIn, removeOnCompletion: false) + itemNode.layer.animateScale(from: 1.0, to: 0.1, duration: 0.2, timingFunction: kCAMediaTimingFunctionEaseIn, removeOnCompletion: false, completion: { [weak itemNode] _ in + itemNode?.removeFromSupernode() + }) + } else { + self.removeItemNodeWithIndex(index, removeNode: true) + } + } else if let previousFrame = previousItemFrames[WrappedGridItemNode(node: itemNode)] { + itemNode.layer.animatePosition(from: CGPoint(x: previousFrame.midX, y: previousFrame.midY), to: itemNode.layer.position, duration: duration, timingFunction: timingFunction) + } else { + itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.12, timingFunction: kCAMediaTimingFunctionEaseIn) + itemNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5) + } + } + + for itemNode in removedNodes { + if let _ = previousItemFrames[WrappedGridItemNode(node: itemNode)] { + itemNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, timingFunction: kCAMediaTimingFunctionEaseIn, removeOnCompletion: false) + itemNode.layer.animateScale(from: 1.0, to: 0.1, duration: 0.18, timingFunction: kCAMediaTimingFunctionEaseIn, removeOnCompletion: false, completion: { [weak itemNode] _ in + itemNode?.removeFromSupernode() + }) + } else { + itemNode.removeFromSupernode() + } + } + + for wrappedSection in self.sectionNodes.keys { + let sectionNode = self.sectionNodes[wrappedSection]! + if !existingSections.contains(wrappedSection) { + if let _ = previousItemFrames[WrappedGridItemNode(node: sectionNode)] { + self.removeSectionNodeWithSection(wrappedSection, removeNode: false) + sectionNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, timingFunction: timingFunction, removeOnCompletion: false, completion: { [weak sectionNode] _ in + sectionNode?.removeFromSupernode() + }) + } else { + self.removeSectionNodeWithSection(wrappedSection, removeNode: true) + } + } else if let previousFrame = previousItemFrames[WrappedGridItemNode(node: sectionNode)] { + sectionNode.layer.animatePosition(from: CGPoint(x: previousFrame.midX, y: previousFrame.midY), to: sectionNode.layer.position, duration: duration, timingFunction: timingFunction) + } else { + sectionNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionEaseIn) + } + } } else { for index in self.itemNodes.keys { if !existingItemIndices.contains(index) { diff --git a/Display/GridNodeScroller.swift b/Display/GridNodeScroller.swift index b4a8c5e6fb..e4fe809f60 100644 --- a/Display/GridNodeScroller.swift +++ b/Display/GridNodeScroller.swift @@ -25,9 +25,11 @@ open class GridNodeScroller: ASDisplayNode, UIGestureRecognizerDelegate { } override init() { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return GridNodeScrollerView() - }, didLoad: nil) + }) self.scrollView.scrollsToTop = false } diff --git a/Display/LegacyPresentedControllerNode.swift b/Display/LegacyPresentedControllerNode.swift index 3a35e282fc..129f33670c 100644 --- a/Display/LegacyPresentedControllerNode.swift +++ b/Display/LegacyPresentedControllerNode.swift @@ -13,9 +13,11 @@ final class LegacyPresentedControllerNode: ASDisplayNode { } override init() { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return UITracingLayerView() - }, didLoad: nil) + }) } func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { diff --git a/Display/ListView.swift b/Display/ListView.swift index 15c1045da7..2762a7de34 100644 --- a/Display/ListView.swift +++ b/Display/ListView.swift @@ -4,6 +4,7 @@ import SwiftSignalKit private let usePerformanceTracker = false private let useDynamicTuning = false +private let useBackgroundDeallocation = false private let infiniteScrollSize: CGFloat = 10000.0 private let insertionAnimationDuration: Double = 0.4 @@ -29,7 +30,13 @@ private final class ListViewBackingLayer: CALayer { } } -final class ListViewBackingView: UIView { +#if os(iOS) +typealias ListBaseView = UIView +#else +typealias ListBaseView = NSView +#endif + +final class ListViewBackingView: ListBaseView { weak var target: ListView? override class var layerClass: AnyClass { @@ -193,9 +200,11 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel performanceTrackerConfig.reportStackTraces = true self.performanceTracker = FBAnimationPerformanceTracker(config: performanceTrackerConfig)*/ - super.init(viewBlock: { Void -> UIView in + super.init() + + self.setViewBlock({ Void -> UIView in return ListViewBackingView() - }, didLoad: nil) + }) self.clipsToBounds = true @@ -261,11 +270,20 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel self.pauseAnimations() self.displayLink.invalidate() - for itemNode in self.itemNodes { - ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode) - } - for itemHeaderNode in self.itemHeaderNodes { - ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemHeaderNode) + if useBackgroundDeallocation { + for itemNode in self.itemNodes { + ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode) + } + for itemHeaderNode in self.itemHeaderNodes { + ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemHeaderNode) + } + } else { + for itemNode in self.itemNodes { + ASPerformMainThreadDeallocation(itemNode) + } + for itemHeaderNode in self.itemHeaderNodes { + ASPerformMainThreadDeallocation(itemHeaderNode) + } } self.waitingForNodesDisposable.dispose() @@ -2089,17 +2107,31 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel animation.completion = { _ in for itemNode in temporaryPreviousNodes { itemNode.removeFromSupernode() - ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode) + if useBackgroundDeallocation { + ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode) + } else { + ASPerformMainThreadDeallocation(itemNode) + } } for headerNode in temporaryHeaderNodes { headerNode.removeFromSupernode() - ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: headerNode) + if useBackgroundDeallocation { + ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: headerNode) + } else { + ASPerformMainThreadDeallocation(headerNode) + } } } self.layer.add(animation, forKey: nil) } else { - for itemNode in temporaryPreviousNodes { - ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode) + if useBackgroundDeallocation { + for itemNode in temporaryPreviousNodes { + ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode) + } + } else { + for itemNode in temporaryPreviousNodes { + ASPerformMainThreadDeallocation(itemNode) + } } } } @@ -2135,7 +2167,11 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel for (previousNode, _) in previousApparentFrames { if previousNode.supernode == nil { - ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: previousNode) + if useBackgroundDeallocation { + ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: previousNode) + } else { + ASPerformMainThreadDeallocation(previousNode) + } } } @@ -2469,7 +2505,11 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel let node = self.itemNodes[i] if node.index == nil && node.apparentHeight <= CGFloat.ulpOfOne { self.removeItemNodeAtIndex(i) - ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: node) + if useBackgroundDeallocation { + ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: node) + } else { + ASPerformMainThreadDeallocation(node) + } } else { i += 1 } diff --git a/Display/ListViewItemHeader.swift b/Display/ListViewItemHeader.swift index 100df12c96..01458552e7 100644 --- a/Display/ListViewItemHeader.swift +++ b/Display/ListViewItemHeader.swift @@ -62,13 +62,16 @@ open class ListViewItemHeaderNode: ASDisplayNode { if seeThrough { if (layerBacked) { - super.init(layerBlock: { + super.init() + self.setLayerBlock({ return CASeeThroughTracingLayer() - }, didLoad: nil) + }) } else { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return CASeeThroughTracingView() - }, didLoad: nil) + }) } } else { super.init() diff --git a/Display/ListViewItemNode.swift b/Display/ListViewItemNode.swift index cbe3e79bf5..ebc762c643 100644 --- a/Display/ListViewItemNode.swift +++ b/Display/ListViewItemNode.swift @@ -174,22 +174,27 @@ open class ListViewItemNode: ASDisplayNode { /*if layerBacked { super.init(layerBlock: { return ASTransformLayer() - }, didLoad: nil) + }) } else { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return ListViewItemView() - }, didLoad: nil) + }) }*/ if seeThrough { if (layerBacked) { - super.init(layerBlock: { + super.init() + self.setLayerBlock({ return CASeeThroughTracingLayer() - }, didLoad: nil) + }) } else { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return CASeeThroughTracingView() - }, didLoad: nil) + }) } } else { super.init() diff --git a/Display/ListViewScrollerAppkit.swift b/Display/ListViewScrollerAppkit.swift new file mode 100644 index 0000000000..95e31a3df5 --- /dev/null +++ b/Display/ListViewScrollerAppkit.swift @@ -0,0 +1,5 @@ +import Foundation +import AppKit + +class ListViewScroller: CALayer { +} diff --git a/Display/NavigationBar.swift b/Display/NavigationBar.swift index 0497aa89ee..bf57a0e019 100644 --- a/Display/NavigationBar.swift +++ b/Display/NavigationBar.swift @@ -23,6 +23,10 @@ public final class NavigationBarTheme { self.backgroundColor = backgroundColor self.separatorColor = separatorColor } + + public func withUpdatedSeparatorColor(_ color: UIColor) -> NavigationBarTheme { + return NavigationBarTheme(buttonColor: self.buttonColor, primaryTextColor: self.primaryTextColor, backgroundColor: self.backgroundColor, separatorColor: color) + } } private func backArrowImage(color: UIColor) -> UIImage? { @@ -478,7 +482,7 @@ open class NavigationBar: ASDisplayNode { let finalX: CGFloat = floor((size.width - backButtonSize.width) / 2.0) - size.width self.backButtonNode.frame = CGRect(origin: CGPoint(x: initialX * (1.0 - progress) + finalX * progress, y: contentVerticalOrigin + floor((nominalHeight - backButtonSize.height) / 2.0)), size: backButtonSize) - self.backButtonNode.alpha = 1.0 - progress + self.backButtonNode.alpha = (1.0 - progress) * (1.0 - progress) if let transitionTitleNode = self.transitionTitleNode { let transitionTitleSize = transitionTitleNode.measure(CGSize(width: size.width, height: nominalHeight)) @@ -487,7 +491,7 @@ open class NavigationBar: ASDisplayNode { let finalX: CGFloat = floor((size.width - transitionTitleSize.width) / 2.0) - size.width transitionTitleNode.frame = CGRect(origin: CGPoint(x: initialX * (1.0 - progress) + finalX * progress, y: contentVerticalOrigin + floor((nominalHeight - transitionTitleSize.height) / 2.0)), size: transitionTitleSize) - transitionTitleNode.alpha = progress + transitionTitleNode.alpha = progress * progress } self.backButtonArrow.frame = CGRect(origin: CGPoint(x: 8.0 - progress * size.width, y: contentVerticalOrigin + floor((nominalHeight - 22.0) / 2.0)), size: CGSize(width: 13.0, height: 22.0)) @@ -532,7 +536,7 @@ open class NavigationBar: ASDisplayNode { let finalX: CGFloat = floor((size.width - transitionBackButtonSize.width) / 2.0) transitionBackButtonNode.frame = CGRect(origin: CGPoint(x: initialX * (1.0 - progress) + finalX * progress, y: contentVerticalOrigin + floor((nominalHeight - transitionBackButtonSize.height) / 2.0)), size: transitionBackButtonSize) - transitionBackButtonNode.alpha = 1.0 - progress + transitionBackButtonNode.alpha = (1.0 - progress) * (1.0 - progress) } if let transitionBackArrowNode = self.transitionBackArrowNode { @@ -562,7 +566,7 @@ open class NavigationBar: ASDisplayNode { let finalX: CGFloat = leftButtonInset self.titleNode.frame = CGRect(origin: CGPoint(x: initialX * (1.0 - progress) + finalX * progress, y: contentVerticalOrigin + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize) - self.titleNode.alpha = 1.0 - progress + self.titleNode.alpha = (1.0 - progress) * (1.0 - progress) case .bottom: var initialX: CGFloat = backButtonInset if otherNavigationBar.backButtonNode.supernode != nil { @@ -572,7 +576,7 @@ open class NavigationBar: ASDisplayNode { let finalX: CGFloat = floor((size.width - titleSize.width) / 2.0) self.titleNode.frame = CGRect(origin: CGPoint(x: initialX * (1.0 - progress) + finalX * progress, y: contentVerticalOrigin + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize) - self.titleNode.alpha = progress + self.titleNode.alpha = progress * progress } } else { self.titleNode.alpha = 1.0 @@ -581,15 +585,45 @@ open class NavigationBar: ASDisplayNode { } if let titleView = self.titleView { - let titleViewSize = CGSize(width: max(1.0, size.width - leftTitleInset - leftTitleInset), height: nominalHeight) - titleView.frame = CGRect(origin: CGPoint(x: leftTitleInset, y: contentVerticalOrigin), size: titleViewSize) + let titleSize = CGSize(width: max(1.0, size.width - leftTitleInset - leftTitleInset), height: nominalHeight) + titleView.frame = CGRect(origin: CGPoint(x: leftTitleInset, y: contentVerticalOrigin), size: titleSize) + + if let transitionState = self.transitionState, let otherNavigationBar = transitionState.navigationBar { + let progress = transitionState.progress + + switch transitionState.role { + case .top: + let initialX = floor((size.width - titleSize.width) / 2.0) + let finalX: CGFloat = leftButtonInset + + titleView.frame = CGRect(origin: CGPoint(x: initialX * (1.0 - progress) + finalX * progress, y: contentVerticalOrigin + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize) + titleView.alpha = (1.0 - progress) * (1.0 - progress) + case .bottom: + var initialX: CGFloat = backButtonInset + if otherNavigationBar.backButtonNode.supernode != nil { + initialX += floor((otherNavigationBar.backButtonNode.frame.size.width - titleSize.width) / 2.0) + } + initialX += size.width * 0.3 + let finalX: CGFloat = floor((size.width - titleSize.width) / 2.0) + + titleView.frame = CGRect(origin: CGPoint(x: initialX * (1.0 - progress) + finalX * progress, y: contentVerticalOrigin + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize) + titleView.alpha = progress * progress + } + } else { + titleView.alpha = 1.0 + titleView.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: contentVerticalOrigin + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize) + } } - - //self.effectView.frame = self.bounds } public func makeTransitionTitleNode(foregroundColor: UIColor) -> ASDisplayNode? { - if let title = self.title { + if let titleView = self.titleView { + if let transitionView = titleView as? NavigationBarTitleTransitionNode { + return transitionView.makeTransitionMirrorNode() + } else { + return nil + } + } else if let title = self.title { let node = ASTextNode() node.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: foregroundColor) return node diff --git a/Display/NavigationBarTitleTransitionNode.swift b/Display/NavigationBarTitleTransitionNode.swift new file mode 100644 index 0000000000..1121280999 --- /dev/null +++ b/Display/NavigationBarTitleTransitionNode.swift @@ -0,0 +1,6 @@ +import Foundation +import AsyncDisplayKit + +public protocol NavigationBarTitleTransitionNode { + func makeTransitionMirrorNode() -> ASDisplayNode +} diff --git a/Display/StatusBar.swift b/Display/StatusBar.swift index 4904eac7f2..894114ab9d 100644 --- a/Display/StatusBar.swift +++ b/Display/StatusBar.swift @@ -78,23 +78,39 @@ public final class StatusBar: ASDisplayNode { private var proxyNode: StatusBarProxyNode? private var removeProxyNodeScheduled = false + let offsetNode = ASDisplayNode() private let inCallBackgroundNode = ASDisplayNode() private let inCallLabel: StatusBarLabelNode private var inCallText: String? = nil + public var verticalOffset: CGFloat = 0.0 { + didSet { + if !self.verticalOffset.isEqual(to: oldValue) { + self.offsetNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -self.verticalOffset), size: CGSize()) + self.layer.invalidateUpTheTree() + } + } + } + public override init() { self.inCallLabel = StatusBarLabelNode() self.inCallLabel.isLayerBacked = true + self.offsetNode.isLayerBacked = true + let labelSize = self.inCallLabel.measure(CGSize(width: 300.0, height: 300.0)) self.inCallLabel.frame = CGRect(origin: CGPoint(x: 10.0, y: 20.0 + 4.0), size: labelSize) - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return StatusBarView() - }, didLoad: nil) + }) + (self.view as! StatusBarView).node = self + self.addSubnode(self.offsetNode) self.addSubnode(self.inCallBackgroundNode) self.layer.setTraceableInfo(CATracingLayerInfo(shouldBeAdjustedToInverseTransform: true, userData: self, tracingTag: WindowTracingTags.statusBar)) diff --git a/Display/StatusBarManager.swift b/Display/StatusBarManager.swift index 3141c9341e..b2cd7a8542 100644 --- a/Display/StatusBarManager.swift +++ b/Display/StatusBarManager.swift @@ -159,19 +159,21 @@ class StatusBarManager { var visibleStatusBars: [StatusBar] = [] - var globalStatusBar: (StatusBarStyle, CGFloat)? + var globalStatusBar: (StatusBarStyle, CGFloat, CGFloat)? var coveredIdentity = false var statusBarIndex = 0 for i in 0 ..< mappedSurfaces.count { for mappedStatusBar in mappedSurfaces[i].statusBars { if let statusBar = mappedStatusBar.statusBar { - if mappedStatusBar.frame.origin.equalTo(CGPoint()) && !statusBar.layer.hasPositionOrOpacityAnimations() { + if mappedStatusBar.frame.origin.equalTo(CGPoint()) && !statusBar.layer.hasPositionOrOpacityAnimations() && !statusBar.offsetNode.layer.hasPositionAnimations() { if !coveredIdentity { if statusBar.statusBarStyle != .Hide { - coveredIdentity = CGFloat(1.0).isLessThanOrEqualTo(statusBar.alpha) + if statusBar.offsetNode.frame.origin.equalTo(CGPoint()) { + coveredIdentity = CGFloat(1.0).isLessThanOrEqualTo(statusBar.alpha) + } if statusBarIndex == 0 && globalStatusBar == nil { - globalStatusBar = (mappedStatusBar.style, statusBar.alpha) + globalStatusBar = (mappedStatusBar.style, statusBar.alpha, statusBar.offsetNode.frame.origin.y) } else { visibleStatusBars.append(statusBar) } @@ -184,7 +186,7 @@ class StatusBarManager { if !coveredIdentity { coveredIdentity = true if statusBarIndex == 0 && globalStatusBar == nil { - globalStatusBar = (mappedStatusBar.style, 1.0) + globalStatusBar = (mappedStatusBar.style, 1.0, 0.0) } } } @@ -223,7 +225,14 @@ class StatusBarManager { if self.host.statusBarStyle != statusBarStyle { self.host.statusBarStyle = statusBarStyle } - self.host.statusBarWindow?.alpha = globalStatusBar.1 + if let statusBarWindow = self.host.statusBarWindow { + statusBarWindow.alpha = globalStatusBar.1 + var statusBarBounds = statusBarWindow.bounds + if !statusBarBounds.origin.y.isEqual(to: globalStatusBar.2) { + statusBarBounds.origin.y = globalStatusBar.2 + statusBarWindow.bounds = statusBarBounds + } + } } else { self.host.statusBarWindow?.alpha = 0.0 } diff --git a/Display/StatusBarProxyNode.swift b/Display/StatusBarProxyNode.swift index 296e7a2fac..e9c5177706 100644 --- a/Display/StatusBarProxyNode.swift +++ b/Display/StatusBarProxyNode.swift @@ -115,7 +115,7 @@ private func tintStatusBarItem(_ context: DrawingContext, type: StatusBarItemTyp targetX += 1 } - let batteryColor = (baseMidRow + baseX).pointee + let batteryColor = (baseMidRow + baseX + 2).pointee let batteryR = (batteryColor >> 16) & 0xff let batteryG = (batteryColor >> 8) & 0xff let batteryB = batteryColor & 0xff diff --git a/Display/SwitchNode.swift b/Display/SwitchNode.swift index a50cdfbe06..8d920ef87a 100644 --- a/Display/SwitchNode.swift +++ b/Display/SwitchNode.swift @@ -52,9 +52,11 @@ open class SwitchNode: ASDisplayNode { } override public init() { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return SwitchNodeView() - }, didLoad: nil) + }) } override open func didLoad() { diff --git a/Display/TabBarContollerNode.swift b/Display/TabBarContollerNode.swift index ee2c33e6e6..baf4d120db 100644 --- a/Display/TabBarContollerNode.swift +++ b/Display/TabBarContollerNode.swift @@ -17,9 +17,11 @@ final class TabBarControllerNode: ASDisplayNode { init(theme: TabBarControllerTheme, itemSelected: @escaping (Int) -> Void) { self.tabBarNode = TabBarNode(theme: theme, itemSelected: itemSelected) - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return UITracingLayerView() - }, didLoad: nil) + }) self.backgroundColor = theme.backgroundColor diff --git a/Display/TextFieldNode.swift b/Display/TextFieldNode.swift index 8522926cc3..4cd28d20b5 100644 --- a/Display/TextFieldNode.swift +++ b/Display/TextFieldNode.swift @@ -26,8 +26,10 @@ public class TextFieldNode: ASDisplayNode { } override public init() { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return TextFieldNodeView() - }, didLoad: nil) + }) } } diff --git a/Display/UIKitUtils.swift b/Display/UIKitUtils.swift index bdf88d7b10..e979fd59c1 100644 --- a/Display/UIKitUtils.swift +++ b/Display/UIKitUtils.swift @@ -182,6 +182,10 @@ public extension CGRect { public var bottomRight: CGPoint { return CGPoint(x: self.maxX, y: self.maxY) } + + public var center: CGPoint { + return CGPoint(x: self.midX, y: self.midY) + } } public extension CGPoint { diff --git a/Display/ViewControllerTracingNode.swift b/Display/ViewControllerTracingNode.swift index 6124180039..1367ad831e 100644 --- a/Display/ViewControllerTracingNode.swift +++ b/Display/ViewControllerTracingNode.swift @@ -19,9 +19,11 @@ private final class ViewControllerTracingNodeView: UITracingLayerView { open class ViewControllerTracingNode: ASDisplayNode { override public init() { - super.init(viewBlock: { + super.init() + + self.setViewBlock({ return ViewControllerTracingNodeView() - }, didLoad: nil) + }) } override open func didLoad() { diff --git a/DisplayMac/DisplayMac.h b/DisplayMac/DisplayMac.h new file mode 100644 index 0000000000..09491004ba --- /dev/null +++ b/DisplayMac/DisplayMac.h @@ -0,0 +1,19 @@ +// +// DisplayMac.h +// DisplayMac +// +// Created by Peter on 8/13/17. +// Copyright © 2017 Telegram. All rights reserved. +// + +#import + +//! Project version number for DisplayMac. +FOUNDATION_EXPORT double DisplayMacVersionNumber; + +//! Project version string for DisplayMac. +FOUNDATION_EXPORT const unsigned char DisplayMacVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/DisplayMac/Info.plist b/DisplayMac/Info.plist new file mode 100644 index 0000000000..d35efc62b4 --- /dev/null +++ b/DisplayMac/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Telegram. All rights reserved. + NSPrincipalClass + + +