Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 90d31b75ca | |||
| 9d6d6e3798 | |||
| 81e13530aa | |||
| f11af83808 | |||
| 162f6d29c3 | |||
| cb97450102 | |||
| 9de5f16735 | |||
| 418da11c82 | |||
| 90fe59ffc6 | |||
| 422b23b4c2 | |||
| 08a4c284f4 | |||
| b775f12fe5 | |||
| 9f75ddffdf | |||
| 225fac033a | |||
| fe3229278d | |||
| de0d273258 | |||
| d1231f19ff | |||
| 20f927f338 | |||
| 8144d96129 | |||
| 0d9e3ef7ab | |||
| 888067cae0 | |||
| 0180ca76c7 | |||
| 951b95b0fb | |||
| 1803722b6a | |||
| 4f5ee72f97 | |||
| 9e17ebb58f | |||
| 28acb5a8d6 | |||
| 5c6fa430e0 | |||
| 5108f3651f | |||
| 05ec840ffd | |||
| 5189d880c4 | |||
| 308051a898 | |||
| 56481d5f8a | |||
| 3882befd7b | |||
| cf88115eb6 | |||
| 663bafce52 | |||
| 6911104a98 | |||
| 369252ee7c | |||
| 3322107688 | |||
| 7731adc79c |
@@ -202,7 +202,6 @@
|
||||
"${BUILT_PRODUCTS_DIR}/Hue/Hue.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/Imaginary/Imaginary.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/Lightbox/Lightbox.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftHash/SwiftHash.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
@@ -210,7 +209,6 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Hue.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Imaginary.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lightbox.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftHash.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
|
||||
@@ -13,11 +13,11 @@ class ViewController: UIViewController {
|
||||
button.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin]
|
||||
|
||||
return button
|
||||
}()
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
view.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin]
|
||||
view.backgroundColor = UIColor.white
|
||||
view.addSubview(showButton)
|
||||
@@ -30,16 +30,16 @@ class ViewController: UIViewController {
|
||||
LightboxImage(imageURL: URL(string: "https://cdn.arstechnica.net/2011/10/05/iphone4s_sample_apple-4e8c706-intro.jpg")!),
|
||||
LightboxImage(
|
||||
image: UIImage(named: "photo1")!,
|
||||
text: "Some very long lorem ipsum text. Some very long lorem ipsum text. Some very long lorem ipsum text. Some very long lorem ipsum text"
|
||||
text: "Photography is the science, art, application and practice of creating durable images by recording light or other electromagnetic radiation, either electronically by means of an image sensor, or chemically by means of a light-sensitive material such as photographic film"
|
||||
),
|
||||
LightboxImage(
|
||||
image: UIImage(named: "photo2")!,
|
||||
text: "🌲 🌲 🌲 🌲 🌲 🌲 🌲 🌲 🌲 🌲 🌲 🏃 🌲 🏃♀️ 🌲 🌲 🌲 🌲 🌲 🌲 🌲 🌲\n\nSuspendisse massa massa, maximus et finibus ac, auctor volutpat diam.\n\nPellentesque consequat magna condimentum mauris bibendum, nec ornare nisl hendrerit. Phasellus nec ultrices sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n\nSuspendisse sit amet facilisis ante, ac suscipit sem. Integer feugiat sit amet erat sit amet mattis. Donec tristique, nunc ut varius elementum, nisi elit viverra ipsum, vitae aliquam justo libero in arcu. Quisque tempor et justo at malesuada. Curabitur justo dolor, ornare convallis sollicitudin sed, consectetur eu turpis. \n\nNulla et dui condimentum, laoreet lacus eu, ultrices nisl. Vivamus in ante volutpat, gravida nunc scelerisque, sagittis tellus. Nullam justo purus, sagittis a tincidunt a, maximus nec sem.",
|
||||
text: "Emoji 😍 (/ɪˈmoʊdʒi/; singular emoji, plural emoji or emojis;[4] from the Japanese 絵文字えもじ, pronounced [emodʑi]) are ideograms and smileys used in electronic messages and web pages. Emoji are used much like emoticons and exist in various genres, including facial expressions, common objects, places and types of weather 🌅☔️💦, and animals 🐶🐱",
|
||||
videoURL: URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
|
||||
),
|
||||
LightboxImage(
|
||||
image: UIImage(named: "photo3")!,
|
||||
text: "Some very long lorem ipsum text."
|
||||
text: "A lightbox is a translucent surface illuminated from behind, used for situations where a shape laid upon the surface needs to be seen with high contrast."
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
PODS:
|
||||
- Cache (4.0.2):
|
||||
- SwiftHash (~> 2.0.0)
|
||||
- Hue (3.0.0)
|
||||
- Imaginary (3.0.0):
|
||||
- Cache (4.1.2)
|
||||
- Hue (3.0.1)
|
||||
- Imaginary (3.0.2):
|
||||
- Cache (~> 4.0)
|
||||
- Lightbox (2.0.0):
|
||||
- Lightbox (2.1.1):
|
||||
- Hue (~> 3.0)
|
||||
- Imaginary (~> 3.0)
|
||||
- SwiftHash (2.0.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Lightbox (from `../../`)
|
||||
@@ -17,11 +15,10 @@ EXTERNAL SOURCES:
|
||||
:path: ../../
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Cache: 363b6899cee63c82ccbd291e64a6c202abc17a88
|
||||
Hue: b8fe1e43eef13631331eebecb2198b68e2622f95
|
||||
Imaginary: 2765d293d425cbed3b07fa11642554cbaebe913d
|
||||
Lightbox: f7f1cc942d81e84d85095531208f5fe1bfd9c639
|
||||
SwiftHash: d2e09b13495447178cdfb8e46e54a5c46f15f5a9
|
||||
Cache: bd0233fc688b5e83a27bcd87807db7e6f23adcc5
|
||||
Hue: 93e852fa6211ab35922ad8c293f51c43d6c79eb2
|
||||
Imaginary: d675200546110e305d6a26db6267c0622ffe5e6b
|
||||
Lightbox: ce54044b5004989fbec6832a3a2a5ba59b4376dc
|
||||
|
||||
PODFILE CHECKSUM: 408ae3477507a1d4b7ff06ffb3f162eda443424f
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 290 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 296 KiB |
@@ -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>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,13 @@
|
||||
import XCTest
|
||||
@testable import Lightbox
|
||||
|
||||
class InfoLabelTests: XCTestCase {
|
||||
func testTruncating() {
|
||||
let label = InfoLabel(text: "", expanded: false)
|
||||
label.frame.size = CGSize(width: 10, height: 10)
|
||||
|
||||
let text = Array(repeating: "A", count: 4).joined(separator: "")
|
||||
label.fullText = text
|
||||
_ = label.truncatedText
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "Lightbox"
|
||||
s.summary = "A a convenient and easy to use image viewer for your iOS app, packed with all the features you expect"
|
||||
s.version = "2.0.1"
|
||||
s.version = "2.1.2"
|
||||
s.homepage = "https://github.com/hyperoslo/Lightbox"
|
||||
s.license = 'MIT'
|
||||
s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" }
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D22006741DFB4D9700E92898 /* Lightbox.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D22006731DFB4D9700E92898 /* Lightbox.bundle */; };
|
||||
D229B5E61FC3123F00F04123 /* Lightbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D523B0A91C43AA2A001AD1EC /* Lightbox.framework */; };
|
||||
D229B5ED1FC3125D00F04123 /* InfoLabelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D229B5EC1FC3125D00F04123 /* InfoLabelTests.swift */; };
|
||||
D2A58F5E1F7943A30064F14E /* Imaginary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2A58F5D1F7943A30064F14E /* Imaginary.framework */; };
|
||||
D2D71BBC1D54DA77006AB907 /* AssetManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D71BBB1D54DA77006AB907 /* AssetManager.swift */; };
|
||||
D5026B3C1C5BF3FD003BC1A3 /* LightboxImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5026B3B1C5BF3FD003BC1A3 /* LightboxImage.swift */; };
|
||||
@@ -24,8 +26,21 @@
|
||||
D58A18CB1C5ABF8F000024BB /* FooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58A18CA1C5ABF8F000024BB /* FooterView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
D229B5E71FC3123F00F04123 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D523B0A01C43AA2A001AD1EC /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D523B0A81C43AA2A001AD1EC;
|
||||
remoteInfo = "Lightbox-iOS";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D22006731DFB4D9700E92898 /* Lightbox.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Lightbox.bundle; sourceTree = "<group>"; };
|
||||
D229B5E11FC3123F00F04123 /* Lightbox-iOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Lightbox-iOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D229B5E51FC3123F00F04123 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D229B5EC1FC3125D00F04123 /* InfoLabelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoLabelTests.swift; sourceTree = "<group>"; };
|
||||
D2A58F5D1F7943A30064F14E /* Imaginary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Imaginary.framework; path = Carthage/Build/iOS/Imaginary.framework; sourceTree = "<group>"; };
|
||||
D2D71BBB1D54DA77006AB907 /* AssetManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManager.swift; sourceTree = "<group>"; };
|
||||
D5026B3B1C5BF3FD003BC1A3 /* LightboxImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LightboxImage.swift; sourceTree = "<group>"; };
|
||||
@@ -45,6 +60,14 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
D229B5DE1FC3123F00F04123 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D229B5E61FC3123F00F04123 /* Lightbox.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D523B0A51C43AA2A001AD1EC /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -65,6 +88,15 @@
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D229B5E21FC3123F00F04123 /* Lightbox-iOS-Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D229B5E51FC3123F00F04123 /* Info.plist */,
|
||||
D229B5EC1FC3125D00F04123 /* InfoLabelTests.swift */,
|
||||
);
|
||||
path = "Lightbox-iOS-Tests";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D2A58F5C1F7943A30064F14E /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -80,6 +112,7 @@
|
||||
D54DFCC01C5AAAF100ADEA0E /* Hue.framework */,
|
||||
D523B0B41C43AA8A001AD1EC /* Source */,
|
||||
D523B0AB1C43AA2A001AD1EC /* Lightbox */,
|
||||
D229B5E21FC3123F00F04123 /* Lightbox-iOS-Tests */,
|
||||
D523B0AA1C43AA2A001AD1EC /* Products */,
|
||||
D2A58F5C1F7943A30064F14E /* Frameworks */,
|
||||
);
|
||||
@@ -89,6 +122,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D523B0A91C43AA2A001AD1EC /* Lightbox.framework */,
|
||||
D229B5E11FC3123F00F04123 /* Lightbox-iOS-Tests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -149,6 +183,24 @@
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
D229B5E01FC3123F00F04123 /* Lightbox-iOS-Tests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D229B5E91FC3123F00F04123 /* Build configuration list for PBXNativeTarget "Lightbox-iOS-Tests" */;
|
||||
buildPhases = (
|
||||
D229B5DD1FC3123F00F04123 /* Sources */,
|
||||
D229B5DE1FC3123F00F04123 /* Frameworks */,
|
||||
D229B5DF1FC3123F00F04123 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D229B5E81FC3123F00F04123 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "Lightbox-iOS-Tests";
|
||||
productName = "Lightbox-iOS-Tests";
|
||||
productReference = D229B5E11FC3123F00F04123 /* Lightbox-iOS-Tests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
D523B0A81C43AA2A001AD1EC /* Lightbox-iOS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D523B0B11C43AA2A001AD1EC /* Build configuration list for PBXNativeTarget "Lightbox-iOS" */;
|
||||
@@ -157,7 +209,6 @@
|
||||
D523B0A51C43AA2A001AD1EC /* Frameworks */,
|
||||
D523B0A61C43AA2A001AD1EC /* Headers */,
|
||||
D523B0A71C43AA2A001AD1EC /* Resources */,
|
||||
D54DFCC41C5AAAF600ADEA0E /* Copy frameworks with Carthage */,
|
||||
5CF8A88D1F50B4EA00C28475 /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
@@ -175,9 +226,14 @@
|
||||
D523B0A01C43AA2A001AD1EC /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0910;
|
||||
LastUpgradeCheck = 0900;
|
||||
ORGANIZATIONNAME = "Hyper Interaktiv AS";
|
||||
TargetAttributes = {
|
||||
D229B5E01FC3123F00F04123 = {
|
||||
CreatedOnToolsVersion = 9.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
D523B0A81C43AA2A001AD1EC = {
|
||||
CreatedOnToolsVersion = 7.2;
|
||||
LastSwiftMigration = 0900;
|
||||
@@ -197,11 +253,19 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
D523B0A81C43AA2A001AD1EC /* Lightbox-iOS */,
|
||||
D229B5E01FC3123F00F04123 /* Lightbox-iOS-Tests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
D229B5DF1FC3123F00F04123 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D523B0A71C43AA2A001AD1EC /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -226,26 +290,17 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
|
||||
};
|
||||
D54DFCC41C5AAAF600ADEA0E /* Copy frameworks with Carthage */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/Carthage/Build/iOS/Hue.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/Imaginary.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/Cache.framework",
|
||||
);
|
||||
name = "Copy frameworks with Carthage";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/usr/local/bin/carthage copy-frameworks";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
D229B5DD1FC3123F00F04123 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D229B5ED1FC3125D00F04123 /* InfoLabelTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D523B0A41C43AA2A001AD1EC /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -267,7 +322,58 @@
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
D229B5E81FC3123F00F04123 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D523B0A81C43AA2A001AD1EC /* Lightbox-iOS */;
|
||||
targetProxy = D229B5E71FC3123F00F04123 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D229B5EA1FC3123F00F04123 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = "Lightbox-iOS-Tests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.fantageek.Lightbox-iOS-Tests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D229B5EB1FC3123F00F04123 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = "Lightbox-iOS-Tests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.fantageek.Lightbox-iOS-Tests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D523B0AF1C43AA2A001AD1EC /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -423,6 +529,15 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
D229B5E91FC3123F00F04123 /* Build configuration list for PBXNativeTarget "Lightbox-iOS-Tests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D229B5EA1FC3123F00F04123 /* Debug */,
|
||||
D229B5EB1FC3123F00F04123 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D523B0A31C43AA2A001AD1EC /* Build configuration list for PBXProject "Lightbox" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -29,7 +29,26 @@
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D229B5E01FC3123F00F04123"
|
||||
BuildableName = "Lightbox-iOS-Tests.xctest"
|
||||
BlueprintName = "Lightbox-iOS-Tests"
|
||||
ReferencedContainer = "container:Lightbox.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D523B0A81C43AA2A001AD1EC"
|
||||
BuildableName = "Lightbox.framework"
|
||||
BlueprintName = "Lightbox-iOS"
|
||||
ReferencedContainer = "container:Lightbox.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
# Lightbox
|
||||
|
||||
[](https://travis-ci.org/hyperoslo/Lightbox)
|
||||
[](https://circleci.com/gh/hyperoslo/Lightbox)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](http://cocoadocs.org/docsets/Lightbox)
|
||||
[](http://cocoadocs.org/docsets/Lightbox)
|
||||

|
||||
|
||||
[Demo](https://appetize.io/app/wfgwc2uvg82m9pzbt17p4rrgh4?device=iphone5s&scale=75&orientation=portrait&osVersion=9.3)
|
||||
|
||||
<img src="https://raw.githubusercontent.com/hyperoslo/Lightbox/master/Images/Icon.png" alt="Lightbox Icon" align="right" />
|
||||
|
||||
**Lightbox** is a convenient and easy to use image viewer for your iOS app,
|
||||
@@ -17,10 +15,16 @@ packed with all the features you expect:
|
||||
- [x] Video support.
|
||||
- [x] Double-tap to zoom.
|
||||
- [x] Image caption.
|
||||
- [x] Dynamic background.
|
||||
- [x] Dynamic background based on [Hue](https://github.com/hyperoslo/Hue)
|
||||
- [x] Remote image loading and caching based on [Imaginary](https://github.com/hyperoslo/Imaginary)
|
||||
- [x] Interactive transition animations.
|
||||
- [x] Powerful configuration.
|
||||
- [x] Demo project.
|
||||
- [x] [Live Demo](https://appetize.io/app/wfgwc2uvg82m9pzbt17p4rrgh4?device=iphone5s&scale=75&orientation=portrait&osVersion=9.3)
|
||||
|
||||
<div align="center">
|
||||
<img src="Images/demo.png" height="500">
|
||||
<img src="Images/demo2.png" height="500">
|
||||
</div>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -106,9 +110,7 @@ extension ViewController: LightboxControllerDismissalDelegate: class {
|
||||
|
||||
### Image loading
|
||||
|
||||
By default images are loaded using `sendAsynchronousRequest` method of
|
||||
`NSURLConnection`. But it's easy to change this behavior using **Lightbox**
|
||||
configuration.
|
||||
By default images are loaded using [Imaginary](https://github.com/hyperoslo/Imaginary) for reliable loading and caching. But it's easy to change this behavior using **LightboxConfig**
|
||||
|
||||
```swift
|
||||
LightboxConfig.loadImage = {
|
||||
@@ -119,7 +121,7 @@ LightboxConfig.loadImage = {
|
||||
|
||||
### Video
|
||||
|
||||
**Lightbox** has video support out of the box. Configure video by using `videoURL`:
|
||||
**Lightbox** can show and plays video using default `AVPlayerViewController`. Showning video by using `videoURL`:
|
||||
|
||||
```swift
|
||||
LightboxImage(
|
||||
@@ -157,7 +159,7 @@ LightboxConfig.DeleteButton.image = UIImage(named: ImageList.Lightbox.deleteButt
|
||||
LightboxConfig.DeleteButton.textAttributes = TextAttributes.Lightbox.deleteButton
|
||||
LightboxConfig.DeleteButton.text = "Delete"
|
||||
|
||||
LightboxConfig.InfoLabel.ellipsisText = "ShowMore"
|
||||
LightboxConfig.InfoLabel.ellipsisText = "Show more"
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -28,14 +28,6 @@ class LightboxTransition: UIPercentDrivenInteractiveTransition {
|
||||
func transition(_ show: Bool) {
|
||||
guard let controller = lightboxController else { return }
|
||||
|
||||
controller.headerView.transform = show
|
||||
? CGAffineTransform.identity
|
||||
: CGAffineTransform(translationX: 0, y: -200)
|
||||
|
||||
controller.footerView.transform = show
|
||||
? CGAffineTransform.identity
|
||||
: CGAffineTransform(translationX: 0, y: 250)
|
||||
|
||||
if interactive {
|
||||
controller.view.backgroundColor = UIColor.black.withAlphaComponent(show ? 1 : 0)
|
||||
} else {
|
||||
|
||||
@@ -2,6 +2,7 @@ import UIKit
|
||||
import Hue
|
||||
import AVKit
|
||||
import AVFoundation
|
||||
import Imaginary
|
||||
|
||||
public class LightboxConfig {
|
||||
/// Whether to show status bar while Lightbox is presented
|
||||
@@ -17,6 +18,20 @@ public class LightboxConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// How to load image onto UIImageView
|
||||
public static var loadImage: (UIImageView, URL, ((UIImage?) -> Void)?) -> Void = { (imageView, imageURL, completion) in
|
||||
|
||||
// Use Imaginary by default
|
||||
imageView.setImage(url: imageURL, placeholder: nil, completion: { result in
|
||||
switch result {
|
||||
case .value(let image):
|
||||
completion?(image)
|
||||
case .error:
|
||||
completion?(nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Indicator is used to show while image is being fetched
|
||||
public static var makeLoadingIndicator: () -> UIView = {
|
||||
return LoadingIndicator()
|
||||
|
||||
@@ -22,15 +22,13 @@ open class LightboxController: UIViewController {
|
||||
|
||||
lazy var scrollView: UIScrollView = { [unowned self] in
|
||||
let scrollView = UIScrollView()
|
||||
scrollView.frame = self.screenBounds
|
||||
scrollView.isPagingEnabled = false
|
||||
scrollView.delegate = self
|
||||
scrollView.isUserInteractionEnabled = true
|
||||
scrollView.showsHorizontalScrollIndicator = false
|
||||
scrollView.decelerationRate = UIScrollViewDecelerationRateFast
|
||||
|
||||
return scrollView
|
||||
}()
|
||||
}()
|
||||
|
||||
lazy var overlayTapGestureRecognizer: UITapGestureRecognizer = { [unowned self] in
|
||||
let gesture = UITapGestureRecognizer()
|
||||
@@ -61,14 +59,14 @@ open class LightboxController: UIViewController {
|
||||
view.delegate = self
|
||||
|
||||
return view
|
||||
}()
|
||||
}()
|
||||
|
||||
open fileprivate(set) lazy var footerView: FooterView = { [unowned self] in
|
||||
let view = FooterView()
|
||||
view.delegate = self
|
||||
|
||||
return view
|
||||
}()
|
||||
}()
|
||||
|
||||
open fileprivate(set) lazy var overlayView: UIView = { [unowned self] in
|
||||
let view = UIView(frame: CGRect.zero)
|
||||
@@ -79,11 +77,7 @@ open class LightboxController: UIViewController {
|
||||
view.alpha = 0
|
||||
|
||||
return view
|
||||
}()
|
||||
|
||||
var screenBounds: CGRect {
|
||||
return UIApplication.shared.delegate?.window??.bounds ?? .zero
|
||||
}
|
||||
}()
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
@@ -127,7 +121,7 @@ open class LightboxController: UIViewController {
|
||||
|
||||
open var spacing: CGFloat = 20 {
|
||||
didSet {
|
||||
configureLayout()
|
||||
configureLayout(view.bounds.size)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,10 +184,32 @@ open class LightboxController: UIViewController {
|
||||
super.viewDidAppear(animated)
|
||||
if !presented {
|
||||
presented = true
|
||||
configureLayout()
|
||||
configureLayout(view.bounds.size)
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
scrollView.frame = view.bounds
|
||||
footerView.frame.size = CGSize(
|
||||
width: view.bounds.width,
|
||||
height: 100
|
||||
)
|
||||
|
||||
footerView.frame.origin = CGPoint(
|
||||
x: 0,
|
||||
y: view.bounds.height - footerView.frame.height
|
||||
)
|
||||
|
||||
headerView.frame = CGRect(
|
||||
x: 0,
|
||||
y: 16,
|
||||
width: view.bounds.width,
|
||||
height: 100
|
||||
)
|
||||
}
|
||||
|
||||
open override var prefersStatusBarHidden: Bool {
|
||||
return LightboxConfig.hideStatusBar
|
||||
}
|
||||
@@ -222,7 +238,7 @@ open class LightboxController: UIViewController {
|
||||
pageViews.append(pageView)
|
||||
}
|
||||
|
||||
configureLayout()
|
||||
configureLayout(view.bounds.size)
|
||||
}
|
||||
|
||||
// MARK: - Pagination
|
||||
@@ -258,7 +274,7 @@ open class LightboxController: UIViewController {
|
||||
|
||||
// MARK: - Layout
|
||||
|
||||
open func configureLayout(_ size: CGSize = UIApplication.shared.delegate?.window??.bounds.size ?? .zero) {
|
||||
open func configureLayout(_ size: CGSize) {
|
||||
scrollView.frame.size = size
|
||||
scrollView.contentSize = CGSize(
|
||||
width: size.width * CGFloat(numberOfPages) + spacing * CGFloat(numberOfPages - 1),
|
||||
@@ -275,18 +291,8 @@ open class LightboxController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
let bounds = scrollView.bounds
|
||||
let headerViewHeight = headerView.closeButton.frame.height > headerView.deleteButton.frame.height
|
||||
? headerView.closeButton.frame.height
|
||||
: headerView.deleteButton.frame.height
|
||||
|
||||
headerView.frame = CGRect(x: 0, y: 16, width: bounds.width, height: headerViewHeight)
|
||||
footerView.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 70)
|
||||
|
||||
[headerView, footerView].forEach { ($0 as AnyObject).configureLayout() }
|
||||
|
||||
footerView.frame.origin.y = bounds.height - footerView.frame.height
|
||||
|
||||
overlayView.frame = scrollView.frame
|
||||
overlayView.resizeGradientLayer()
|
||||
}
|
||||
@@ -332,7 +338,7 @@ extension LightboxController: UIScrollViewDelegate {
|
||||
}
|
||||
|
||||
targetContentOffset.pointee.x = x
|
||||
currentPage = Int(x / screenBounds.width)
|
||||
currentPage = Int(x / pageWidth)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,8 +403,8 @@ extension LightboxController: HeaderViewDelegate {
|
||||
self.pageViews.remove(at: prevIndex).removeFromSuperview()
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
|
||||
self.configureLayout()
|
||||
self.currentPage = Int(self.scrollView.contentOffset.x / self.screenBounds.width)
|
||||
self.configureLayout(self.view.bounds.size)
|
||||
self.currentPage = Int(self.scrollView.contentOffset.x / self.view.bounds.width)
|
||||
deleteButton.isEnabled = true
|
||||
}
|
||||
}
|
||||
@@ -416,8 +422,6 @@ extension LightboxController: HeaderViewDelegate {
|
||||
extension LightboxController: FooterViewDelegate {
|
||||
|
||||
public func footerView(_ footerView: FooterView, didExpand expanded: Bool) {
|
||||
footerView.frame.origin.y = screenBounds.height - footerView.frame.height
|
||||
|
||||
UIView.animate(withDuration: 0.25, animations: {
|
||||
self.overlayView.alpha = expanded ? 1.0 : 0.0
|
||||
self.headerView.deleteButton.alpha = expanded ? 0.0 : 1.0
|
||||
|
||||
@@ -22,19 +22,12 @@ open class LightboxImage {
|
||||
self.videoURL = videoURL
|
||||
}
|
||||
|
||||
open func addImageTo(_ imageView: UIImageView, completion: ((_ image: UIImage?) -> Void)? = nil) {
|
||||
open func addImageTo(_ imageView: UIImageView, completion: ((UIImage?) -> Void)? = nil) {
|
||||
if let image = image {
|
||||
imageView.image = image
|
||||
completion?(image)
|
||||
} else if let imageURL = imageURL {
|
||||
imageView.setImage(url: imageURL, placeholder: nil, completion: { result in
|
||||
switch result {
|
||||
case .value(let image):
|
||||
completion?(image)
|
||||
case .error:
|
||||
completion?(nil)
|
||||
}
|
||||
})
|
||||
LightboxConfig.loadImage(imageView, imageURL, completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ open class FooterView: UIView {
|
||||
label.delegate = self
|
||||
|
||||
return label
|
||||
}()
|
||||
}()
|
||||
|
||||
open fileprivate(set) lazy var pageLabel: UILabel = { [unowned self] in
|
||||
let label = UILabel(frame: CGRect.zero)
|
||||
@@ -24,7 +24,7 @@ open class FooterView: UIView {
|
||||
label.numberOfLines = 1
|
||||
|
||||
return label
|
||||
}()
|
||||
}()
|
||||
|
||||
open fileprivate(set) lazy var separatorView: UIView = { [unowned self] in
|
||||
let view = UILabel(frame: CGRect.zero)
|
||||
@@ -32,7 +32,7 @@ open class FooterView: UIView {
|
||||
view.backgroundColor = LightboxConfig.PageIndicator.separatorColor
|
||||
|
||||
return view
|
||||
}()
|
||||
}()
|
||||
|
||||
let gradientColors = [UIColor(hex: "040404").alpha(0.1), UIColor(hex: "040404")]
|
||||
open weak var delegate: FooterViewDelegate?
|
||||
@@ -76,17 +76,29 @@ open class FooterView: UIView {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Layout
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
fileprivate func resetFrames() {
|
||||
frame.size.height = infoLabel.frame.height + 40 + 0.5
|
||||
do {
|
||||
let bottomPadding: CGFloat
|
||||
if #available(iOS 11, *) {
|
||||
bottomPadding = safeAreaInsets.bottom
|
||||
} else {
|
||||
bottomPadding = 0
|
||||
}
|
||||
|
||||
pageLabel.frame.origin = CGPoint(
|
||||
x: (frame.width - pageLabel.frame.width) / 2,
|
||||
y: frame.height - pageLabel.frame.height - 2)
|
||||
pageLabel.frame.origin = CGPoint(
|
||||
x: (frame.width - pageLabel.frame.width) / 2,
|
||||
y: frame.height - pageLabel.frame.height - 2 - bottomPadding
|
||||
)
|
||||
}
|
||||
|
||||
separatorView.frame = CGRect(x: 0, y: pageLabel.frame.minY - 2.5,
|
||||
width: frame.width, height: 0.5)
|
||||
separatorView.frame = CGRect(
|
||||
x: 0,
|
||||
y: pageLabel.frame.minY - 2.5,
|
||||
width: frame.width,
|
||||
height: 0.5
|
||||
)
|
||||
|
||||
infoLabel.frame.origin.y = separatorView.frame.minY - infoLabel.frame.height - 15
|
||||
|
||||
@@ -107,7 +119,6 @@ extension FooterView: LayoutConfigurable {
|
||||
extension FooterView: InfoLabelDelegate {
|
||||
|
||||
public func infoLabel(_ infoLabel: InfoLabel, didExpand expanded: Bool) {
|
||||
resetFrames()
|
||||
_ = (expanded || infoLabel.fullText.isEmpty) ? removeGradientLayer() : addGradientLayer(gradientColors)
|
||||
delegate?.footerView(self, didExpand: expanded)
|
||||
}
|
||||
|
||||
@@ -6,13 +6,6 @@ protocol HeaderViewDelegate: class {
|
||||
}
|
||||
|
||||
open class HeaderView: UIView {
|
||||
|
||||
var centerTextStyle: NSMutableParagraphStyle = {
|
||||
var style = NSMutableParagraphStyle()
|
||||
style.alignment = .center
|
||||
return style
|
||||
}()
|
||||
|
||||
open fileprivate(set) lazy var closeButton: UIButton = { [unowned self] in
|
||||
let title = NSAttributedString(
|
||||
string: LightboxConfig.CloseButton.text,
|
||||
@@ -38,7 +31,7 @@ open class HeaderView: UIView {
|
||||
button.isHidden = !LightboxConfig.CloseButton.enabled
|
||||
|
||||
return button
|
||||
}()
|
||||
}()
|
||||
|
||||
open fileprivate(set) lazy var deleteButton: UIButton = { [unowned self] in
|
||||
let title = NSAttributedString(
|
||||
@@ -65,7 +58,7 @@ open class HeaderView: UIView {
|
||||
button.isHidden = !LightboxConfig.DeleteButton.enabled
|
||||
|
||||
return button
|
||||
}()
|
||||
}()
|
||||
|
||||
weak var delegate: HeaderViewDelegate?
|
||||
|
||||
@@ -99,9 +92,22 @@ open class HeaderView: UIView {
|
||||
extension HeaderView: LayoutConfigurable {
|
||||
|
||||
@objc public func configureLayout() {
|
||||
closeButton.frame.origin = CGPoint(
|
||||
x: bounds.width - closeButton.frame.width - 17, y: 0)
|
||||
let topPadding: CGFloat
|
||||
|
||||
deleteButton.frame.origin = CGPoint(x: 17, y: 0)
|
||||
if #available(iOS 11, *) {
|
||||
topPadding = safeAreaInsets.top
|
||||
} else {
|
||||
topPadding = 0
|
||||
}
|
||||
|
||||
closeButton.frame.origin = CGPoint(
|
||||
x: bounds.width - closeButton.frame.width - 17,
|
||||
y: topPadding
|
||||
)
|
||||
|
||||
deleteButton.frame.origin = CGPoint(
|
||||
x: 17,
|
||||
y: topPadding
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ open class InfoLabel: UILabel {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate var truncatedText: String {
|
||||
var truncatedText: String {
|
||||
var truncatedText = fullText
|
||||
|
||||
guard numberOfLines(fullText) > numberOfVisibleLines else {
|
||||
@@ -50,7 +50,7 @@ open class InfoLabel: UILabel {
|
||||
|
||||
// Perform quick "rough cut"
|
||||
while numberOfLines(truncatedText) > numberOfVisibleLines * 2 {
|
||||
truncatedText = String(truncatedText.characters.prefix(truncatedText.characters.count / 2))
|
||||
truncatedText = String(truncatedText.prefix(truncatedText.count / 2))
|
||||
}
|
||||
|
||||
// Capture the endIndex of truncatedText before appending ellipsis
|
||||
@@ -60,8 +60,13 @@ open class InfoLabel: UILabel {
|
||||
|
||||
// Remove characters ahead of ellipsis until the text is the right number of lines
|
||||
while numberOfLines(truncatedText) > numberOfVisibleLines {
|
||||
truncatedTextCursor = truncatedText.index(before: truncatedTextCursor)
|
||||
truncatedText.remove(at: truncatedTextCursor)
|
||||
// To avoid "Cannot decrement before startIndex"
|
||||
guard truncatedTextCursor > truncatedText.startIndex else {
|
||||
break
|
||||
}
|
||||
|
||||
truncatedTextCursor = truncatedText.index(before: truncatedTextCursor)
|
||||
truncatedText.remove(at: truncatedTextCursor)
|
||||
}
|
||||
|
||||
return truncatedText
|
||||
|
||||
Reference in New Issue
Block a user