Skip to content

Commit

Permalink
Merge branch 'firebaseui-0.2.0'
Browse files Browse the repository at this point in the history
* firebaseui-0.2.0:
  0.2.0 release candidate:   + FirebaseCollectionViewDataSource   + Nullability annotations and improved swift support   + Documentation!
  Please enter the commit message for your changes. Lines starting
  FirebaseUI 0.2.0 release:   + FirebaseCollectionViewDataSource
  Ignoring /target.
  • Loading branch information
asciimike committed Aug 14, 2015
2 parents 3d05238 + a6b0165 commit 02cfb6f
Show file tree
Hide file tree
Showing 35 changed files with 2,790 additions and 95 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ DerivedData

# Third Party
/sdk

# Generated
/target
/site
13 changes: 7 additions & 6 deletions FirebaseUI.podspec
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
Pod::Spec.new do |s|
s.name = "FirebaseUI"
s.version = "0.1.2"
s.version = "0.2.0"
s.summary = "UI binding libraries for Firebase."
s.homepage = "https://github.com/firebase/FirebaseUI-iOS"
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { "Firebase" => "[email protected]" }
s.source = { :git => "https://github.com/firebase/FirebaseUI-iOS.git", :tag => 'v0.1.2' }
s.social_media_url = "https://twitter.com/firebase"
s.source = { :git => "https://github.com/firebase/FirebaseUI-iOS.git", :tag => 'v0.2.0' }
s.source_files = "FirebaseUI/**/*.{h,m}"
s.dependency 'Firebase', '~> 2.3'
s.dependency "Firebase", "~> 2.2"
s.platform = :ios
s.ios.deployment_target = '7.0'
s.ios.deployment_target = "7.0"
s.libraries = "c++", "icucore"
s.ios.framework = "CFNetwork", "Security", "Firebase", "SystemConfiguration", "UIKit", "Foundation"
s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/Firebase"'}
s.ios.framework = "UIKit", "Firebase", "Security", "CFNetwork", "SystemConfiguration"
s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/Firebase"' }
s.requires_arc = true
end
38 changes: 21 additions & 17 deletions FirebaseUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
D8B6ACF81B583D3E005CDDB2 /* FirebaseUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B6ACEB1B583C33005CDDB2 /* FirebaseUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
D8B6ACF91B583D3E005CDDB2 /* FirebaseDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B6ACED1B583C33005CDDB2 /* FirebaseDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
D8B6ACFB1B583D48005CDDB2 /* FirebaseArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B6ACEC1B583C33005CDDB2 /* FirebaseArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
D8DA10F11B7AC50400D00954 /* FirebaseCollectionViewDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D8DA10F01B7AC50400D00954 /* FirebaseCollectionViewDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
D8DF55621B742DB40030E996 /* FirebaseCollectionViewDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = D8DF55611B742DB40030E996 /* FirebaseCollectionViewDataSource.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -68,13 +70,10 @@
D8B6ACEF1B583C41005CDDB2 /* FirebaseArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseArray.m; path = Implementation/FirebaseArray.m; sourceTree = "<group>"; };
D8B6ACF11B583C41005CDDB2 /* FirebaseTableViewDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseTableViewDataSource.m; path = Implementation/FirebaseTableViewDataSource.m; sourceTree = "<group>"; };
D8B6ACF21B583C41005CDDB2 /* FirebaseDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseDataSource.m; path = Implementation/FirebaseDataSource.m; sourceTree = "<group>"; };
D8B6AD971B58D45F005CDDB2 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "usr/lib/libc++.dylib"; sourceTree = SDKROOT; };
D8B6AD991B58D486005CDDB2 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
D8B6AD9B1B58D48C005CDDB2 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
D8B6AD9D1B58D494005CDDB2 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
D8B6AD9F1B58D49E005CDDB2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
D8C579A61B57349000899F86 /* libFirebaseUI.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFirebaseUI.a; sourceTree = BUILT_PRODUCTS_DIR; };
D8C579BB1B5837DF00899F86 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
D8DA10F01B7AC50400D00954 /* FirebaseCollectionViewDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FirebaseCollectionViewDataSource.h; path = API/FirebaseCollectionViewDataSource.h; sourceTree = "<group>"; };
D8DF55611B742DB40030E996 /* FirebaseCollectionViewDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseCollectionViewDataSource.m; path = Implementation/FirebaseCollectionViewDataSource.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -95,11 +94,6 @@
isa = PBXGroup;
children = (
D8124F401B72A90C003441AD /* Firebase.framework */,
D8B6AD9F1B58D49E005CDDB2 /* SystemConfiguration.framework */,
D8B6AD9D1B58D494005CDDB2 /* Security.framework */,
D8B6AD9B1B58D48C005CDDB2 /* CFNetwork.framework */,
D8B6AD991B58D486005CDDB2 /* libicucore.dylib */,
D8B6AD971B58D45F005CDDB2 /* libc++.dylib */,
D8B6ACE61B583877005CDDB2 /* Foundation.framework */,
D8C579BB1B5837DF00899F86 /* UIKit.framework */,
);
Expand All @@ -114,13 +108,15 @@
D8B6ACEC1B583C33005CDDB2 /* FirebaseArray.h */,
D8B6ACED1B583C33005CDDB2 /* FirebaseDataSource.h */,
D8B6ACEE1B583C33005CDDB2 /* FirebaseTableViewDataSource.h */,
D8DA10F01B7AC50400D00954 /* FirebaseCollectionViewDataSource.h */,
);
name = API;
sourceTree = "<group>";
};
D8B6ACEA1B5839F7005CDDB2 /* Implementation */ = {
isa = PBXGroup;
children = (
D8DF55611B742DB40030E996 /* FirebaseCollectionViewDataSource.m */,
D8B6ACEF1B583C41005CDDB2 /* FirebaseArray.m */,
D8B6ACF21B583C41005CDDB2 /* FirebaseDataSource.m */,
D8B6ACF11B583C41005CDDB2 /* FirebaseTableViewDataSource.m */,
Expand Down Expand Up @@ -165,6 +161,7 @@
D8B6ACF91B583D3E005CDDB2 /* FirebaseDataSource.h in Headers */,
D8784C401B719F280025587E /* FirebaseArrayDelegate.h in Headers */,
D8124F431B72B347003441AD /* FirebaseTableViewDataSource.h in Headers */,
D8DA10F11B7AC50400D00954 /* FirebaseCollectionViewDataSource.h in Headers */,
D8B6ACFB1B583D48005CDDB2 /* FirebaseArray.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -240,7 +237,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Using the default Ray Wenderlich build script http://www.raywenderlich.com/65964/create-a-framework-for-ios\nset -e\n\nexport FRAMEWORK_LOCN=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework\"\n\n# Create the path to the real Headers die\nmkdir -p \"${FRAMEWORK_LOCN}/Versions/A/Headers\"\n\n# Create the required symlinks\n/bin/ln -sfh A \"${FRAMEWORK_LOCN}/Versions/Current\"\n/bin/ln -sfh Versions/Current/Headers \"${FRAMEWORK_LOCN}/Headers\"\n/bin/ln -sfh \"Versions/Current/${PRODUCT_NAME}\" \\\n\"${FRAMEWORK_LOCN}/${PRODUCT_NAME}\"\n\n# Copy the public headers into the framework\n/bin/cp -a \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/\" \\\n\"${FRAMEWORK_LOCN}/Versions/A/Headers\"";
shellScript = "set -e\n\nexport FRAMEWORK_LOCN=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework\"\n\n# Create the path to the real Headers die\nmkdir -p \"${FRAMEWORK_LOCN}/Versions/A/Headers\"\n\n# Create the required symlinks\n/bin/ln -sfh A \"${FRAMEWORK_LOCN}/Versions/Current\"\n/bin/ln -sfh Versions/Current/Headers \"${FRAMEWORK_LOCN}/Headers\"\n/bin/ln -sfh \"Versions/Current/${PRODUCT_NAME}\" \\\n\"${FRAMEWORK_LOCN}/${PRODUCT_NAME}\"\n\n# Copy the public headers into the framework\n/bin/cp -a \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/\" \\\n\"${FRAMEWORK_LOCN}/Versions/A/Headers\"";
};
D8B6ADA91B58DCF9005CDDB2 /* MultiPlatform Build */ = {
isa = PBXShellScriptBuildPhase;
Expand All @@ -263,6 +260,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D8DF55621B742DB40030E996 /* FirebaseCollectionViewDataSource.m in Sources */,
D8B6ACF61B583C41005CDDB2 /* FirebaseDataSource.m in Sources */,
D8B6ACF31B583C41005CDDB2 /* FirebaseArray.m in Sources */,
D8124F421B72B344003441AD /* FirebaseTableViewDataSource.m in Sources */,
Expand All @@ -283,6 +281,7 @@
D8B6ADA51B58DCDD005CDDB2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_MODULES_AUTOLINK = YES;
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
};
Expand All @@ -291,6 +290,7 @@
D8B6ADA61B58DCDD005CDDB2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_MODULES_AUTOLINK = YES;
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
};
Expand Down Expand Up @@ -377,17 +377,19 @@
D8C579B01B57349000899F86 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_MODULES_AUTOLINK = YES;
DEAD_CODE_STRIPPING = NO;
DEFINES_MODULE = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(PROJECT_DIR)/sdk",
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(SDKROOT)/Developer/Library/Frameworks",
"$(PROJECT_DIR)/sdk",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
OTHER_LDFLAGS = "-ObjC";
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
PUBLIC_HEADERS_FOLDER_PATH = "include/$(PROJECT_NAME)";
SKIP_INSTALL = YES;
Expand All @@ -398,17 +400,19 @@
D8C579B11B57349000899F86 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_MODULES_AUTOLINK = YES;
DEAD_CODE_STRIPPING = NO;
DEFINES_MODULE = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(PROJECT_DIR)/sdk",
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(SDKROOT)/Developer/Library/Frameworks",
"$(PROJECT_DIR)/sdk",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
OTHER_LDFLAGS = "-ObjC";
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
PUBLIC_HEADERS_FOLDER_PATH = "include/$(PROJECT_NAME)";
SKIP_INSTALL = YES;
Expand Down
6 changes: 5 additions & 1 deletion FirebaseUI/API/FirebaseArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@

@class FQuery;
@class Firebase;
@class FDataSnapshot;

/**
* FirebaseArray provides an array structure that is synchronized with a Firebase reference or query. It is useful for building custom data structures or sources, and provides the base for FirebaseDataSource.
*/
@interface FirebaseArray : NSObject

/**
Expand All @@ -48,7 +52,7 @@
/**
* The delegate object that array changes are surfaced to.
*/
@property (strong, nonatomic) NSMutableArray *snapshots;
@property (strong, nonatomic) NSMutableArray<FDataSnapshot *> *snapshots;

#pragma mark -
#pragma mark Initializer methods
Expand Down
127 changes: 127 additions & 0 deletions FirebaseUI/API/FirebaseCollectionViewDataSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Firebase UI Bindings iOS Library
*
* Copyright © 2015 Firebase - All Rights Reserved
* https://www.firebase.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binaryform must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY FIREBASE AS IS AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL FIREBASE BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#import <UIKit/UIKit.h>

#import "FirebaseDataSource.h"

@class Firebase;

/**
* FirebaseCollectionViewDataSource provides an class that conforms to the UICollcetionViewDataSource protocol which allows UICollectionViews to implement FirebaseCollectionViewDataSource in order to provide a UICollectionView synchronized to a Firebase reference or query. In addition to handling all Firebase child events (added, changed, removed, moved), FirebaseCollectionViewDataSource handles UITableViewCell creation, either with the default UICollectionViewCell, prototype cells, custom UICollectionViewCell subclasses, or custom XIBs, and provides a simple [FirebaseCollectionViewDataSource populateCellWithBlock:] method which allows developers to populate the cells created for them with desired data from Firebase.
*/
@interface FirebaseCollectionViewDataSource : FirebaseDataSource <UICollectionViewDataSource>

/**
* The model class to coerce FDataSnapshots to (if desired). For instance, if the modelClass is set to [Message class] in Obj-C or Message.self in Swift, then objects of type Message will be returned instead of type FDataSnapshot.
*/
@property (strong, nonatomic, nonnull) Class modelClass;

/**
* The reuse identifier for cells in the UICollectionView.
*/
@property (strong, nonatomic, nonnull) NSString *reuseIdentifier;

/**
* The UICollectionView instance that operations (inserts, removals, moves, etc.) are performed against.
*/
@property (strong, nonatomic, nonnull) UICollectionView *collectionView;

/**
* The callback to populate a subclass of UICollectionViewCell with an object provided by the datasource.
*/
@property (strong, nonatomic, nonnull) void(^populateCell)(__nonnull __kindof UICollectionViewCell *cell, __nonnull __kindof NSObject *object);

/**
* Initialize an instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with FDataSnapshots.
* @param ref A Firebase reference to bind the datasource to
* @param identifier A string to use as a CellReuseIdentifier
* @param collectionView An instance of a UICollectionView to bind to
* @return An instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with FDataSnapshots
*/
- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView;

/**
* Initialize an instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with FDataSnapshots.
* @param ref A Firebase reference to bind the datasource to
* @param cell A subclass of UICollectionViewCell used to populate the UICollectionView, defaults to UICollectionViewCell if nil
* @param identifier A string to use as a CellReuseIdentifier
* @param collectionView An instance of a UICollectionView to bind to
* @return An instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with FDataSnapshots
*/
- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref cellClass:(nullable Class)cell reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView;

/**
* Initialize an instance of FirebaseCollectionViewDataSource that populates a custom xib with FDataSnapshots.
* @param ref A Firebase reference to bind the datasource to
* @param nibName The name of a xib file to create the layout for a UICollectionViewCell
* @param identifier A string to use as a CellReuseIdentifier
* @param collectionView An instance of a UICollectionView to bind to
* @return An instance of FirebaseCollectionViewDataSource that populates a custom xib with FDataSnapshots
*/
- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref nibNamed:(nonnull NSString *)nibName reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView;

/**
* Initialize an instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with a custom model class.
* @param ref A Firebase reference to bind the datasource to
* @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil
* @param identifier A string to use as a CellReuseIdentifier
* @param collectionView An instance of a UICollectionView to bind to
* @return An instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with a custom model class
*/
- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView;

/**
* Initialize an instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with a custom model class.
* @param ref A Firebase reference to bind the datasource to
* @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil
* @param cell A subclass of UICollectionViewCell used to populate the UICollectionView, defaults to UICollectionViewCell if nil
* @param identifier A string to use as a CellReuseIdentifier
* @param collectionView An instance of a UICollectionView to bind to
* @return An instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with a custom model class
*/
- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model cellClass:(nullable Class)cell reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView;

/**
* Initialize an instance of FirebaseCollectionViewDataSource that populates a custom xib with a custom model class.
* @param ref A Firebase reference to bind the datasource to
* @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil
* @param nibName The name of a xib file to create the layout for a UICollectionViewCell
* @param identifier A string to use as a CellReuseIdentifier
* @param collectionView An instance of a UICollectionView to bind to
* @return An instance of FirebaseCollectionViewDataSource that populates a custom xib with a custom model class
*/
- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model nibNamed:(nonnull NSString *)nibName reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView;

/**
* This method populates the fields of a UICollectionViewCell or subclass given an FDataSnapshot (or custom model object).
* @param callback A block which returns an initialized UICollectionViewCell (or subclass) and the corresponding object to populate the cell with.
*/
- (void)populateCellWithBlock:(nonnull void(^)(__nonnull __kindof UICollectionViewCell *cell, __nonnull __kindof NSObject *object))callback;

@end
Loading

0 comments on commit 02cfb6f

Please sign in to comment.