mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 13:17:49 +00:00
1460 lines
53 KiB
Plaintext
1460 lines
53 KiB
Plaintext
//
|
|
// RBProfileViewController.mm
|
|
// RobloxMobile
|
|
//
|
|
// Created by Christian Hresko on 6/6/14.
|
|
// Copyright (c) 2014 ROBLOX. All rights reserved.
|
|
//
|
|
|
|
#import "RBProfileViewController.h"
|
|
#import "RobloxTheme.h"
|
|
#import "LoginManager.h"
|
|
#import "WelcomeScreenController.h"
|
|
#import "RBPurchaseViewController.h"
|
|
#import "RBAccountManagerViewController.h"
|
|
#import "RobloxImageView.h"
|
|
#import "UIAlertView+Blocks.h"
|
|
#import "RobloxData.h"
|
|
#import "UserInfo.h"
|
|
#import "RobloxInfo.h"
|
|
#import "RobloxNotifications.h"
|
|
#import "Flurry.h"
|
|
#import "RBbarButtonMenu.h"
|
|
#import "UIScrollView+Auto.h"
|
|
#import "UIView+Position.h"
|
|
#import "RobloxHUD.h"
|
|
#import "GameSortHorizontalViewController.h"
|
|
#import "GameThumbnailCell.h"
|
|
#import "RBPlayerThumbnailCell.h"
|
|
#import "RBFullFriendListScreenController.h"
|
|
#import "RBWebGamePreviewScreenController.h"
|
|
#import "RBSingleSortScreenController.h"
|
|
#import "RBMessageComposeScreenController.H"
|
|
#import "GameBadgeViewController.h"
|
|
#import "RobloxGoogleAnalytics.h"
|
|
#import "RBGameViewController.h"
|
|
#import "iOSSettingsService.h"
|
|
#import "RobloxWebUtility.h"
|
|
#import "RBXEventReporter.h"
|
|
|
|
#define ROBLOXBADGECELL_ID @"RobloxBadgeCell"
|
|
#define PLAYERBADGECELL_ID @"PlayerBadgeCell"
|
|
#define FRIENDCELL_ID @"FriendCell"
|
|
#define FOLLOWINGCELL_ID @"FollowingCell"
|
|
#define FOLLOWERCELL_ID @"FollowerCell"
|
|
#define BADGECELL_SUPP @"BadgeCellSupp"
|
|
#define FRIENDCELL_SUPP @"FriendCellSupp"
|
|
|
|
#define GAME_ITEM_SIZE CGSizeMake(225, 155)
|
|
#define GAME_THUMBNAIL_SIZE CGSizeMake(420, 230)
|
|
#define PROFILE_IMAGE_SIZE CGSizeMake(352, 352)
|
|
#define FRIEND_AVATAR_SIZE CGSizeMake(110, 110)
|
|
#define BADGE_SIZE CGSizeMake(110, 110) // Player badges are fixed sized, so the request
|
|
|
|
#define MAX_ELEMENTS_PER_REQUEST 20
|
|
|
|
//---METRICS---
|
|
#define PVC_openRobux @"PROFILE SCREEN - Open Robux"
|
|
#define PVC_openBuildersClub @"PROFILE SCREEN - Open Builders Club"
|
|
#define PVC_openSettings @"PROFILE SCREEN - Open Settings"
|
|
#define PVC_openLogout @"PROFILE SCREEN - Open Logout"
|
|
#define PVC_catalogSearch @"PROFILE SCREEN - User Search"
|
|
#define PVC_openExternalLink @"PROFILE SCREEN - Open External Link"
|
|
#define PVC_openProfile @"PROFILE SCREEN - Open Profile"
|
|
#define PVC_openGameDetail @"PROFILE SCREEN - Open Game Detail"
|
|
#define PVC_launchGame @"PROFILE SCREEN - Launch Game"
|
|
|
|
#define MAX_PLAYER_FRIENDS 200
|
|
#define ERROR_PLAYER_FRIENDS -1
|
|
|
|
#pragma mark -
|
|
#pragma mark Collection View Cells
|
|
|
|
|
|
@interface RBXPlayerBadgeCell : UICollectionViewCell
|
|
|
|
@property (weak, nonatomic) IBOutlet RobloxImageView* badgeImage;
|
|
@property (strong, nonatomic) RBXBadgeInfo* badgeInfo;
|
|
|
|
@end
|
|
|
|
@implementation RBXPlayerBadgeCell
|
|
|
|
- (void)setBadgeInfo:(RBXBadgeInfo *)badgeInfo
|
|
{
|
|
_badgeInfo = badgeInfo;
|
|
|
|
self.badgeImage.animateInOptions = RBXImageViewAnimateInAlways;
|
|
[self.badgeImage loadBadgeWithURL:badgeInfo.imageURL withSize:BADGE_SIZE completion:nil];
|
|
}
|
|
|
|
@end
|
|
|
|
@interface RBXRobloxBadgeCell : UICollectionViewCell
|
|
|
|
@property (weak, nonatomic) IBOutlet RobloxImageView* badgeImage;
|
|
@property (strong, nonatomic) RBXBadgeInfo* badgeInfo;
|
|
|
|
@end
|
|
|
|
@implementation RBXRobloxBadgeCell
|
|
|
|
- (void)setBadgeInfo:(RBXBadgeInfo *)badgeInfo
|
|
{
|
|
_badgeInfo = badgeInfo;
|
|
|
|
self.badgeImage.animateInOptions = RBXImageViewAnimateInAlways;
|
|
[self.badgeImage loadBadgeWithURL:badgeInfo.imageURL withSize:BADGE_SIZE completion:nil];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
#pragma mark
|
|
#pragma mark ActionSheets
|
|
@interface RBFriendshipActionSheet : UIActionSheet <UIActionSheetDelegate>
|
|
typedef enum
|
|
{
|
|
SHEET_TAG_FRIEND = 1,
|
|
SHEET_TAG_PENDING_REQUEST = 2
|
|
} SHEET_TAGS;
|
|
|
|
@property int sheetIdTag;
|
|
@property RBProfileViewController* profile;
|
|
-(id) initFriendSheetFromProfile:(RBProfileViewController*)profilePage;
|
|
-(id) initFriendRequestSheetFromProfile:(RBProfileViewController*)profilePage;
|
|
@end
|
|
|
|
@implementation RBFriendshipActionSheet
|
|
|
|
//CONSTRUCTORS
|
|
-(id) initFriendSheetFromProfile:(RBProfileViewController*)profilePage
|
|
{
|
|
//the user is currently a friend, display the current friend options
|
|
self = [super initWithTitle:nil
|
|
delegate:self
|
|
cancelButtonTitle:NSLocalizedString(@"CancelWord", nil)
|
|
destructiveButtonTitle:nil
|
|
otherButtonTitles:NSLocalizedString(@"RemoveFriendPhrase", nil), nil];
|
|
|
|
_sheetIdTag = SHEET_TAG_FRIEND;
|
|
|
|
_profile = profilePage;
|
|
return self;
|
|
}
|
|
-(id) initFriendRequestSheetFromProfile:(RBProfileViewController*)profilePage
|
|
{
|
|
_sheetIdTag = SHEET_TAG_PENDING_REQUEST;
|
|
_profile = profilePage;
|
|
return self;
|
|
}
|
|
|
|
|
|
//DELEGATE FUNCTIONS
|
|
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
|
|
{
|
|
switch (_sheetIdTag)
|
|
{
|
|
case SHEET_TAG_FRIEND:
|
|
if (buttonIndex == 0) //Remove friend
|
|
{
|
|
[self actionSheetRemoveFriend];
|
|
}
|
|
else //Cancel
|
|
{
|
|
}
|
|
break;
|
|
|
|
|
|
case SHEET_TAG_PENDING_REQUEST:
|
|
if (buttonIndex == 0) //Accept Friend Request
|
|
{
|
|
|
|
}
|
|
else if (buttonIndex == 1) //Reject Friend Request
|
|
{
|
|
|
|
}
|
|
else //Cancel
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//BUTTON FUNCTIONS
|
|
-(void) actionSheetRemoveFriend
|
|
{
|
|
// Remove friend
|
|
[RobloxHUD showSpinnerWithLabel:nil dimBackground:YES];
|
|
|
|
[RobloxData unfriend:_profile.userId completion:^(BOOL success)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[RobloxHUD hideSpinner:YES];
|
|
if(success) { [self updateProfileFriendshipButtonWithStatus:RBXFriendshipStatusNonFriends]; }
|
|
else
|
|
{
|
|
[RobloxHUD showMessage:@"Error - Could Not Remove Friend"];
|
|
}
|
|
});
|
|
}];
|
|
}
|
|
-(void) actionSheetAcceptFriendRequest
|
|
{
|
|
// TO DO : FIGURE OUT A WAY TO GET THE INVITATION ID
|
|
// Accept Friend Request
|
|
// [RobloxHUD showSpinnerWithLabel:nil dimBackground:YES];
|
|
//
|
|
// [RobloxData acceptFriendRequest:<#(NSUInteger)#> withTargetUserID:_profile.userId completion:^(BOOL success)
|
|
// {
|
|
// dispatch_async(dispatch_get_main_queue(), ^
|
|
// {
|
|
// [RobloxHUD hideSpinner:YES];
|
|
// if(success) { [self updateProfileFriendshipButtonWithStatus:RBXFriendshipStatusFriends]; }
|
|
// else
|
|
// {
|
|
// [RobloxHUD showMessage:@"Error - Could Not Accept Friend Request"];
|
|
// }
|
|
// });
|
|
// }];
|
|
}
|
|
-(void) actionSheetRejectFriendRequest
|
|
{
|
|
// TO DO : FIGURE OUT A WAY TO GET THE INVITATION ID
|
|
// Remove best friend
|
|
// [RobloxHUD showSpinnerWithLabel:nil dimBackground:YES];
|
|
//
|
|
// [RobloxData declineFriendRequest:<#(NSUInteger)#> withTargetUserID:_profile.userId completion:^(BOOL success)
|
|
// {
|
|
// dispatch_async(dispatch_get_main_queue(), ^
|
|
// {
|
|
// [RobloxHUD hideSpinner:YES];
|
|
// if(success) { [self updateProfileFriendshipButtonWithStatus:RBXFriendshipStatusNonFriends]; }
|
|
// else
|
|
// {
|
|
// [RobloxHUD showMessage:@"Error"];
|
|
// }
|
|
// });
|
|
// }];
|
|
}
|
|
-(void) updateProfileFriendshipButtonWithStatus:(RBXFriendshipStatus)aNewStatus
|
|
{
|
|
_profile.profile.friendshipStatus = aNewStatus;
|
|
[_profile updateFriendshipButton];
|
|
}
|
|
@end
|
|
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Profile View Controller
|
|
|
|
@implementation RBProfileViewController
|
|
{
|
|
RBXUserPresence* _userPresence;
|
|
|
|
NSMutableArray* _playerBadges;
|
|
NSMutableArray* _robloxBadges;
|
|
NSMutableArray* _friends;
|
|
NSMutableArray* _followers;
|
|
NSMutableArray* _following;
|
|
int _userFriendCount; //used privately
|
|
|
|
GameSortHorizontalViewController* _recentlyPlayedViewController;
|
|
GameSortHorizontalViewController* _myGamesViewController;
|
|
GameSortHorizontalViewController* _favoriteGamesViewController;
|
|
|
|
IBOutlet UIScrollView* _scrollView;
|
|
|
|
//header elements
|
|
IBOutlet UIView* _headerContainer;
|
|
IBOutlet RobloxImageView* _avatarImageView;
|
|
IBOutlet UIImageView* _userOnlineMarker;
|
|
IBOutlet UILabel* _userNameLabel;
|
|
IBOutlet UILabel* _userStatusLabel;
|
|
IBOutlet UILabel* _robuxTitle;
|
|
IBOutlet UILabel* _ticketsTitle;
|
|
IBOutlet UILabel* _friendsTitle;
|
|
IBOutlet UILabel* _robuxLabel;
|
|
IBOutlet UILabel* _ticketsLabel;
|
|
IBOutlet UILabel* _friendsLabel;
|
|
|
|
//main buttons
|
|
IBOutlet UIButton *_friendshipButton;
|
|
IBOutlet UIButton *_sendMessageButton;
|
|
IBOutlet UIButton *_followIntoGameButton;
|
|
IBOutlet UIButton *_followUserButton;
|
|
|
|
//friends elements
|
|
IBOutlet UIView* _friendsContainerView;
|
|
IBOutlet UICollectionView* _friendsCollectionView;
|
|
IBOutlet UILabel* _friendsHeaderTitle;
|
|
IBOutlet UIButton* _seeAllFriendsButton;
|
|
|
|
//followers elements
|
|
IBOutlet UIView* _followersContainerView;
|
|
IBOutlet UICollectionView* _followersCollectionView;
|
|
IBOutlet UILabel* _followersHeaderTitle;
|
|
IBOutlet UIButton* _seeAllFollowersButton;
|
|
|
|
//following elements
|
|
IBOutlet UIView* _followingContainerView;
|
|
IBOutlet UICollectionView* _followingCollectionView;
|
|
IBOutlet UILabel* _followingHeaderTitle;
|
|
IBOutlet UIButton* _seeAllFollowingButton;
|
|
|
|
//badges elements
|
|
IBOutlet UIView* _badgesContainerView;
|
|
IBOutlet UILabel* _badgesHeaderTitle;
|
|
IBOutlet UICollectionView* _badgesCollectionView;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark View Loading
|
|
- (id)initWithCoder:(NSCoder *)aDecoder
|
|
{
|
|
self = [super initWithCoder:aDecoder];
|
|
if (self)
|
|
{
|
|
self.title = NSLocalizedString(@"Profile", nil);
|
|
}
|
|
return self;
|
|
}
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
|
|
_playerBadges = [NSMutableArray array];
|
|
_robloxBadges = [NSMutableArray array];
|
|
_friends = [NSMutableArray array];
|
|
_following = [NSMutableArray array];
|
|
_followers = [NSMutableArray array];
|
|
|
|
//apply a few local changes
|
|
self.edgesForExtendedLayout = UIRectEdgeNone;
|
|
self.view.backgroundColor = [RobloxTheme lightBackground];
|
|
|
|
//grab the profile information about the player
|
|
[self requestUserInfo];
|
|
|
|
// Some controls are not in the view if this user is not the one logged in
|
|
if( [self isSessionUser] ) { [self initPlayerProfile]; }
|
|
else { [self initOtherProfile]; }
|
|
|
|
|
|
//initialize the screen
|
|
[self initCommonProfileElements];
|
|
|
|
}
|
|
- (void)viewDidLayoutSubviews
|
|
{
|
|
[super viewDidLayoutSubviews];
|
|
|
|
[_scrollView setContentSizeForDirection:UIScrollViewDirectionVertical];
|
|
}
|
|
- (void)viewWillAppear:(BOOL)animated
|
|
{
|
|
[self setViewTheme:RBXThemeCreative];
|
|
[super viewWillAppear:animated];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFriendsUpdated:) name:RBX_NOTIFY_FRIENDS_UPDATED object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFollowingUpdated:) name:RBX_NOTIFY_FOLLOWING_UPDATED object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRobuxUpdated:) name:RBX_NOTIFY_ROBUX_UPDATED object:nil];
|
|
|
|
//reload the dynamic data, but only if we have already fetched the player's profile information
|
|
if ([self isSessionUser] && _profile)
|
|
{
|
|
//don't lock up the UIThread with this request, push it to a background thread
|
|
//each function has a callback that updates on the UIThread, this is safe
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
|
{
|
|
//update the player's following, followers, badges, and friends
|
|
if (_profile.userID)
|
|
[self fetchProfileElementsForUser:_profile.userID];
|
|
|
|
//update the labels at the top of the screen
|
|
[self showUserInfo:_profile];
|
|
});
|
|
}
|
|
|
|
[[RBXEventReporter sharedInstance] reportScreenLoaded:RBXAContextProfile];
|
|
}
|
|
- (void)viewWillDisappear:(BOOL)animated
|
|
{
|
|
[super viewWillDisappear:animated];
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:RBX_NOTIFY_FRIENDS_UPDATED object:nil];
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:RBX_NOTIFY_FOLLOWING_UPDATED object:nil];
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:RBX_NOTIFY_ROBUX_UPDATED object:nil];
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Initialization and Layout Methods
|
|
- (void) initCommonProfileElements
|
|
{
|
|
// Set header background and border
|
|
_headerContainer.backgroundColor = [UIColor whiteColor];
|
|
CALayer* headerLayer = _headerContainer.layer;
|
|
headerLayer.shadowOpacity = 0.25;
|
|
headerLayer.shadowColor = [UIColor colorWithWhite:(0x6B/255.f) alpha:1.0].CGColor;
|
|
headerLayer.shadowOffset = CGSizeMake(0,0);
|
|
headerLayer.shadowRadius = 2.0;
|
|
|
|
// Localize, initialize and stylize labels and buttons
|
|
//Header Elements
|
|
_userNameLabel.text = @"";
|
|
_userStatusLabel.text = @"";
|
|
_userStatusLabel.hidden = YES; //THIS WILL REMAIN HIDDEN UNTIL FOREVER / IT IS SUPPORTED
|
|
_friendsLabel.text = @"";
|
|
_friendsTitle.text = NSLocalizedString(@"FriendsWord", nil);
|
|
[RobloxTheme applyToProfileHeaderSubtitle:_friendsTitle];
|
|
[RobloxTheme applyToProfileHeaderValue:_friendsLabel];
|
|
[RobloxTheme applyToProfileHeaderValue:_userNameLabel];
|
|
|
|
//Friends
|
|
[_friendsHeaderTitle setText:[NSLocalizedString(@"FriendsWord", nil) uppercaseString]];
|
|
[_seeAllFriendsButton setTitle:NSLocalizedString(@"SeeAllPhrase", nil) forState:UIControlStateNormal];
|
|
[_seeAllFriendsButton setHidden:YES];
|
|
[RobloxTheme applyToGameSortSeeAllButton:_seeAllFriendsButton];
|
|
[RobloxTheme applyToTableHeaderTitle:_friendsHeaderTitle];
|
|
|
|
//Following
|
|
[_followingHeaderTitle setText:[NSLocalizedString(@"FollowingWord", nil) uppercaseString]];
|
|
[_seeAllFollowingButton setTitle:NSLocalizedString(@"SeeAllPhrase", nil) forState:UIControlStateNormal];
|
|
[_seeAllFollowingButton setHidden:YES];
|
|
[RobloxTheme applyToGameSortSeeAllButton:_seeAllFollowingButton];
|
|
[RobloxTheme applyToTableHeaderTitle:_followingHeaderTitle];
|
|
_followingContainerView.hidden = NO;
|
|
|
|
//Followers
|
|
[_followersHeaderTitle setText:[NSLocalizedString(@"FollowersWord", nil) uppercaseString]];
|
|
[_seeAllFollowersButton setTitle:NSLocalizedString(@"SeeAllPhrase", nil) forState:UIControlStateNormal];
|
|
[_seeAllFollowersButton setHidden:YES];
|
|
[RobloxTheme applyToGameSortSeeAllButton:_seeAllFollowersButton];
|
|
[RobloxTheme applyToTableHeaderTitle:_followersHeaderTitle];
|
|
_followersContainerView.hidden = NO;
|
|
|
|
//Badges
|
|
_badgesHeaderTitle.text = [NSLocalizedString(@"BadgesWord", nil) uppercaseString];
|
|
[RobloxTheme applyToTableHeaderTitle:_badgesHeaderTitle];
|
|
|
|
|
|
|
|
//add navigation bar elements
|
|
UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
|
|
[self.navigationItem setBackBarButtonItem:backButton];
|
|
|
|
//add the builders club stuff only if the user is logged in
|
|
if ([self isLoggedIn])
|
|
[self addIcons:nil];
|
|
else
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addIcons:) name:RBX_NOTIFY_LOGIN_SUCCEEDED object:nil];
|
|
|
|
[self setFlurryEventsForExternalLinkEvent:nil
|
|
andWebViewEvent:nil
|
|
andOpenProfileEvent:PVC_openProfile
|
|
andOpenGameDetailEvent:PVC_openGameDetail];
|
|
|
|
//add a search bar to allow players to search for other players
|
|
[self addSearchIconWithSearchType:SearchResultUsers andFlurryEvent:nil];
|
|
|
|
//layout the views
|
|
[self setUpCollectionViews];
|
|
}
|
|
- (void) initPlayerProfile
|
|
{
|
|
_robuxTitle.text = [NSLocalizedString(@"RobuxWord", nil) uppercaseString];
|
|
_ticketsTitle.text = NSLocalizedString(@"TicketsWord", nil);
|
|
_robuxLabel.text = @"";
|
|
_ticketsLabel.text = @"";
|
|
|
|
[RobloxTheme applyToProfileHeaderSubtitle:_robuxTitle];
|
|
[RobloxTheme applyToProfileHeaderSubtitle:_ticketsTitle];
|
|
[RobloxTheme applyToProfileHeaderValue:_robuxLabel];
|
|
[RobloxTheme applyToProfileHeaderValue:_ticketsLabel];
|
|
|
|
|
|
//With the new layout, hide the player's friends and recently played as they've been relocated to the Home Screen
|
|
if ([self isNewLayout])
|
|
{
|
|
_friendsContainerView.hidden = YES;
|
|
}
|
|
|
|
}
|
|
- (void) initOtherProfile
|
|
{
|
|
_sendMessageButton.hidden = YES;
|
|
_friendshipButton.hidden = YES;
|
|
_followIntoGameButton.hidden = YES;
|
|
_followUserButton.hidden = YES;
|
|
}
|
|
- (void)setUpCollectionViews
|
|
{
|
|
__weak RBProfileViewController* weakSelf = self;
|
|
|
|
NSNumber* userID = [self getUserID];
|
|
|
|
// My games
|
|
_myGamesViewController = [[GameSortHorizontalViewController alloc] initWithNibName:@"GameSortHorizontalViewController" bundle:nil];
|
|
[_myGamesViewController setAnalyticsLocation:RBXALocationProfile andContext:RBXAContextMain];
|
|
_myGamesViewController.gameSelectedHandler = ^(RBXGameData* gameData) { [weakSelf showGameDetails:gameData]; };
|
|
_myGamesViewController.seeAllHandler = ^(NSNumber* sortID) { [weakSelf seeAllGamesForSort:sortID]; };
|
|
[self addChildViewController:_myGamesViewController];
|
|
[_scrollView addSubview:_myGamesViewController.view];
|
|
|
|
[RobloxData
|
|
fetchUserPlaces:userID
|
|
startIndex:0
|
|
numGames:MAX_ELEMENTS_PER_REQUEST
|
|
thumbSize:GAME_THUMBNAIL_SIZE
|
|
completion:^(NSArray *games)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
_myGamesViewController.view.hidden = games == nil || games.count == 0;
|
|
[_myGamesViewController setSort:[RBXGameSort MyGamesSort] withGames:games];
|
|
|
|
if( _profile != nil && ![self isSessionUser] )
|
|
{
|
|
_myGamesViewController.sortTitle = [NSString stringWithFormat:NSLocalizedString(@"FriendPlacesFormat", nil), _profile.username];
|
|
}
|
|
});
|
|
}];
|
|
|
|
|
|
// Favorite games
|
|
_favoriteGamesViewController = [[GameSortHorizontalViewController alloc] initWithNibName:@"GameSortHorizontalViewController" bundle:nil];
|
|
[_favoriteGamesViewController setAnalyticsLocation:RBXALocationProfile andContext:RBXAContextMain];
|
|
_favoriteGamesViewController.gameSelectedHandler = ^(RBXGameData* gameData) { [weakSelf showGameDetails:gameData]; };
|
|
_favoriteGamesViewController.seeAllHandler = ^(NSNumber* sortID) { [weakSelf seeAllGamesForSort:sortID]; };
|
|
[self addChildViewController:_favoriteGamesViewController];
|
|
[_scrollView addSubview:_favoriteGamesViewController.view];
|
|
|
|
[RobloxData
|
|
fetchUserFavoriteGames:userID
|
|
startIndex:0
|
|
numGames:MAX_ELEMENTS_PER_REQUEST
|
|
thumbSize:GAME_THUMBNAIL_SIZE
|
|
completion:^(NSArray *games)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
_favoriteGamesViewController.view.hidden = games == nil || games.count == 0;
|
|
[_favoriteGamesViewController setSort:[RBXGameSort FavoriteGamesSort] withGames:games];
|
|
[self layoutCollectionViews];
|
|
});
|
|
}];
|
|
|
|
|
|
// Badges
|
|
_badgesCollectionView.dataSource = self;
|
|
_badgesCollectionView.delegate = self;
|
|
[_badgesCollectionView setContentInset:UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)];
|
|
|
|
|
|
// Friends
|
|
_friendsCollectionView.dataSource = self;
|
|
_friendsCollectionView.delegate = self;
|
|
[_friendsCollectionView setContentInset:UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)];
|
|
[_friendsCollectionView registerNib:[UINib nibWithNibName:@"RBPlayerThumbnailCell" bundle:nil] forCellWithReuseIdentifier:FRIENDCELL_ID];
|
|
|
|
// Followers
|
|
if (_followingContainerView)
|
|
{
|
|
_followingCollectionView.dataSource = self;
|
|
_followingCollectionView.delegate = self;
|
|
[_followingCollectionView setContentInset:UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)];
|
|
[_followingCollectionView registerNib:[UINib nibWithNibName:@"RBPlayerThumbnailCell" bundle:nil] forCellWithReuseIdentifier:FOLLOWINGCELL_ID];
|
|
}
|
|
|
|
|
|
// Following
|
|
_followersCollectionView.dataSource = self;
|
|
_followersCollectionView.delegate = self;
|
|
[_followersCollectionView setContentInset:UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)];
|
|
[_followersCollectionView registerNib:[UINib nibWithNibName:@"RBPlayerThumbnailCell" bundle:nil] forCellWithReuseIdentifier:FOLLOWERCELL_ID];
|
|
|
|
|
|
[self layoutCollectionViews];
|
|
}
|
|
- (void)layoutCollectionViews
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
#define OFFSET_Y 20
|
|
CGFloat lastY = CGRectGetMaxY(_headerContainer.frame) + OFFSET_Y;
|
|
|
|
if (_friendsContainerView.hidden == NO)
|
|
{
|
|
lastY = CGRectGetMaxY(_friendsContainerView.frame) + OFFSET_Y;
|
|
_seeAllFriendsButton.hidden = NO;
|
|
}
|
|
|
|
if(_followingContainerView != nil && _followingContainerView.hidden == NO)
|
|
{
|
|
_followingContainerView.y = lastY;
|
|
lastY = CGRectGetMaxY(_followingContainerView.frame) + OFFSET_Y;
|
|
_seeAllFollowingButton.hidden = NO;
|
|
}
|
|
|
|
if(_followersContainerView.hidden == NO)
|
|
{
|
|
_followersContainerView.y = lastY;
|
|
lastY = CGRectGetMaxY(_followersContainerView.frame) + OFFSET_Y;
|
|
_seeAllFollowersButton.hidden = NO;
|
|
}
|
|
|
|
if(_favoriteGamesViewController != nil && _favoriteGamesViewController.view.hidden == NO)
|
|
{
|
|
_favoriteGamesViewController.view.y = lastY;
|
|
lastY = CGRectGetMaxY(_favoriteGamesViewController.view.frame) + OFFSET_Y;
|
|
}
|
|
|
|
if(_myGamesViewController != nil && _myGamesViewController.view.hidden == NO)
|
|
{
|
|
_myGamesViewController.view.y = lastY;
|
|
lastY = CGRectGetMaxY(_myGamesViewController.view.frame) + OFFSET_Y;
|
|
}
|
|
|
|
|
|
if(_badgesContainerView.hidden == NO)
|
|
{
|
|
_badgesContainerView.y = lastY;
|
|
|
|
[_badgesCollectionView setSize:_badgesCollectionView.contentSize];
|
|
|
|
_badgesContainerView.size = CGRectUnion(_badgesCollectionView.frame, _badgesHeaderTitle.frame).size;
|
|
}
|
|
|
|
[_scrollView setContentSizeForDirection:UIScrollViewDirectionVertical];
|
|
|
|
});
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Notification Event Listeners
|
|
- (void) onFriendsUpdated:(NSNotification*)notification
|
|
{
|
|
NSNumber* userID = [self getUserID];
|
|
[self fetchFriendsForUser:userID];
|
|
}
|
|
- (void) onFollowingUpdated:(NSNotification*)notification
|
|
{
|
|
[self fetchMyFollowing];
|
|
}
|
|
- (void) onRobuxUpdated:(NSNotification*)notification
|
|
{
|
|
[self updateRobux];
|
|
}
|
|
- (void) addIcons:(NSNotification*) notification
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[self addRobuxIconWithFlurryEvent:PVC_openRobux
|
|
andBCIconWithFlurryEvent:PVC_openBuildersClub];
|
|
|
|
[self configureUserButtons];
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:RBX_NOTIFY_LOGIN_SUCCEEDED object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeIcons:) name:RBX_NOTIFY_LOGGED_OUT object:nil];
|
|
});
|
|
}
|
|
-(void) removeIcons:(NSNotification*) notification
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[self removeRobuxAndBCIcons];
|
|
|
|
[self initOtherProfile];
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:RBX_NOTIFY_LOGGED_OUT object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addIcons:) name:RBX_NOTIFY_LOGIN_SUCCEEDED object:nil];
|
|
});
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Property Accessors
|
|
- (BOOL)isSessionUser
|
|
{
|
|
return self.userId == nil;
|
|
}
|
|
- (BOOL)isLoggedIn
|
|
{
|
|
return [UserInfo CurrentPlayer].userLoggedIn;
|
|
}
|
|
- (BOOL)isNewLayout
|
|
{
|
|
iOSSettingsService* iOSSettings = [[RobloxWebUtility sharedInstance] getCachediOSSettings];
|
|
return !iOSSettings->GetValueEnableFriendsOnProfile();
|
|
}
|
|
- (NSNumber*)getUserID
|
|
{
|
|
if([self isSessionUser])
|
|
{
|
|
UserInfo* userInfo = [UserInfo CurrentPlayer];
|
|
return userInfo.userId;
|
|
}
|
|
else
|
|
return self.userId;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Data Requests and Fetches
|
|
- (void) requestUserInfo
|
|
{
|
|
// ** Request basic user info **
|
|
// If no user id is set, load the current user info
|
|
if( [self isSessionUser])
|
|
{
|
|
[RobloxData fetchMyProfileWithSize:PROFILE_IMAGE_SIZE completion:^(RBXUserProfileInfo *profile)
|
|
{
|
|
_profile = profile;
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[self showUserInfo:profile];
|
|
});
|
|
|
|
[self fetchProfileElementsForUser:_profile.userID];
|
|
}];
|
|
}
|
|
else
|
|
{
|
|
NSNumber* userID = [self getUserID];
|
|
[RobloxData fetchUserProfile:userID avatarSize:PROFILE_IMAGE_SIZE completion:^(RBXUserProfileInfo *profile)
|
|
{
|
|
_profile = profile;
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[self showUserInfo:profile];
|
|
});
|
|
|
|
[self fetchProfileElementsForUser:_profile.userID];
|
|
}];
|
|
}
|
|
}
|
|
- (void)updateRobux
|
|
{
|
|
[RobloxData fetchMyProfileWithSize:PROFILE_IMAGE_SIZE completion:^(RBXUserProfileInfo *profile)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
_robuxLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)profile.robux];
|
|
});
|
|
}];
|
|
}
|
|
- (void)fetchProfileElementsForUser:(NSNumber*)userID
|
|
{
|
|
if ([self isSessionUser])
|
|
{
|
|
// ** Request the player's Following **
|
|
[self fetchMyFollowing];
|
|
}
|
|
else
|
|
{
|
|
// ** Request User Presence **
|
|
[self fetchUserPresenceForUser:userID];
|
|
}
|
|
|
|
// ** Request Badges
|
|
[self fetchBadgesForUser:userID];
|
|
|
|
// ** Request Friends **
|
|
[self fetchFriendsForUser:userID];
|
|
|
|
// ** Request Followers **
|
|
[self fetchFollowersForUser:userID];
|
|
}
|
|
- (void)fetchFriendsForUser:(NSNumber *)userID
|
|
{
|
|
// ** Request friends **
|
|
_friends = [NSMutableArray array];
|
|
[_friendsCollectionView reloadData];
|
|
|
|
[RobloxData fetchUserFriends:userID friendType:RBXFriendTypeAllFriends startIndex:0 numItems:MAX_ELEMENTS_PER_REQUEST avatarSize:FRIEND_AVATAR_SIZE completion:^(NSUInteger totalFriends, NSArray *friends)
|
|
{
|
|
if(friends)
|
|
{
|
|
[_friends addObjectsFromArray:friends];
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
_friendsLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)totalFriends];
|
|
|
|
//check for reasons to hide the friends view
|
|
if (_friends.count == 0)
|
|
{
|
|
//-the user has no friends
|
|
_friendsContainerView.hidden = YES;
|
|
}
|
|
else if ([self isSessionUser] && [self isNewLayout])
|
|
{
|
|
//-the user is on the Profile page (not Other page) and the newLayout flag is activated
|
|
_friendsContainerView.hidden = YES;
|
|
}
|
|
else if ([self isLoggedIn] && [userID isEqualToNumber:[UserInfo CurrentPlayer].userId])
|
|
{
|
|
//user is logged in and looking at themself on a different page
|
|
_friendsContainerView.hidden = YES;
|
|
}
|
|
else
|
|
{
|
|
_friendsContainerView.hidden = NO;
|
|
[_friendsCollectionView reloadData];
|
|
}
|
|
|
|
[self layoutCollectionViews];
|
|
});
|
|
}
|
|
|
|
//if the user id of the user we just searched is not the player, then we need to know how many friends the user has
|
|
if ([self isLoggedIn])
|
|
{
|
|
//it is important to make sure the user is logged in, as the fetch requires an authenticated user
|
|
//check how many friends the user has
|
|
if (!userID || ![UserInfo CurrentPlayer].userId)
|
|
{
|
|
// if for some reason there has been some egregious error, add an error value and walk away
|
|
_userFriendCount = ERROR_PLAYER_FRIENDS;
|
|
return;
|
|
}
|
|
|
|
|
|
if ([[UserInfo CurrentPlayer].userId isEqualToNumber:userID])
|
|
_userFriendCount = (int)[_friends count];
|
|
else
|
|
{
|
|
//also get the count for how many friends the user currently has
|
|
[RobloxData fetchFriendCount:[UserInfo CurrentPlayer].userId
|
|
withCompletion:^(BOOL success, NSString *message, int count)
|
|
{
|
|
//if this call was unsuccessful, prevent the user from sending any friend requests
|
|
// by setting the friend count to the max allowed count
|
|
_userFriendCount = success ? count : ERROR_PLAYER_FRIENDS;
|
|
}];
|
|
}
|
|
}
|
|
|
|
}];
|
|
|
|
|
|
}
|
|
- (void)fetchFollowersForUser:(NSNumber*)userID
|
|
{
|
|
//_followers
|
|
[RobloxData fetchFollowersForUser:userID
|
|
atPage:1
|
|
avatarSize:FRIEND_AVATAR_SIZE
|
|
withCompletion:^(bool success, NSArray *followers)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
if (!success || followers.count == 0)
|
|
{
|
|
//the user has no followers, hide the followers setion
|
|
_followersContainerView.hidden = YES;
|
|
}
|
|
else
|
|
{
|
|
if (_followers) { [_followers removeAllObjects]; }
|
|
|
|
_followers = [NSMutableArray arrayWithArray:followers];
|
|
[_followersCollectionView reloadData];
|
|
}
|
|
});
|
|
[self layoutCollectionViews];
|
|
}];
|
|
}
|
|
- (void)fetchMyFollowing
|
|
{
|
|
//_following
|
|
[RobloxData fetchMyFollowingAtPage:1
|
|
avatarSize:FRIEND_AVATAR_SIZE
|
|
withCompletion:^(bool success, NSArray *following)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
if (!success || following.count == 0)
|
|
{
|
|
_followingContainerView.hidden = YES;
|
|
}
|
|
else
|
|
{
|
|
if (_following) { [_following removeAllObjects]; }
|
|
|
|
_following = [NSMutableArray arrayWithArray:following];
|
|
[_followingCollectionView reloadData];
|
|
|
|
}
|
|
});
|
|
[self layoutCollectionViews];
|
|
}];
|
|
}
|
|
- (void)fetchBadgesForUser:(NSNumber*)userID
|
|
{
|
|
// ** Request badges **
|
|
_playerBadges = [NSMutableArray array];
|
|
[RobloxData fetchUserBadges:RBXUserBadgeTypePlayer forUser:userID badgeSize:BADGE_SIZE completion:^(NSArray *badges)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
if(badges)
|
|
[_playerBadges addObjectsFromArray:badges];
|
|
else
|
|
[_playerBadges removeAllObjects];
|
|
|
|
[_badgesCollectionView reloadData];
|
|
_badgesContainerView.hidden = _robloxBadges.count == 0 && _playerBadges.count == 0;
|
|
[self layoutCollectionViews];
|
|
});
|
|
}];
|
|
|
|
_robloxBadges = [NSMutableArray array];
|
|
[RobloxData fetchUserBadges:RBXUserBadgeTypeRoblox forUser:userID badgeSize:BADGE_SIZE completion:^(NSArray *badges)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
if(badges)
|
|
[_robloxBadges addObjectsFromArray:badges];
|
|
else
|
|
[_robloxBadges removeAllObjects];
|
|
|
|
[_badgesCollectionView reloadData];
|
|
_badgesContainerView.hidden = _robloxBadges.count == 0 && _playerBadges.count == 0;
|
|
[self layoutCollectionViews];
|
|
});
|
|
}];
|
|
}
|
|
- (void)fetchUserPresenceForUser:(NSNumber*)userID
|
|
{
|
|
[RobloxData fetchPresenceForUser:userID withCompletion:^(RBXUserPresence* presence)
|
|
{
|
|
if (presence)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
_userPresence = presence;
|
|
[self showUserOnlineStatus];
|
|
});
|
|
}
|
|
}];
|
|
}
|
|
|
|
|
|
//USING THE RBXUSERPROFILE INFO, UPDATE ALL THE SCREEN ELEMENTS
|
|
- (void) showUserInfo:(RBXUserProfileInfo*)profile
|
|
{
|
|
_userNameLabel.text = profile.username;
|
|
//_userStatusLabel.text = profile.status;
|
|
//_userStatusLabel.hidden = [profile.status length] <= 0;
|
|
[_avatarImageView loadAvatarForUserID:profile.userID.intValue prefetchedURL:profile.avatarURL urlIsFinal:profile.avatarIsFinal withSize:PROFILE_IMAGE_SIZE completion:nil];
|
|
|
|
if( [self isSessionUser] )
|
|
{
|
|
_robuxLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)profile.robux];
|
|
_ticketsLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)profile.tickets];
|
|
}
|
|
else
|
|
{
|
|
//before adding the buttons the the Other's Profile page
|
|
// check that the current player is not looking at their own profile and that they are not guests
|
|
NSNumber* playerID = [UserInfo CurrentPlayer].userId == nil ? [NSNumber numberWithInt:-1] : [UserInfo CurrentPlayer].userId;
|
|
BOOL check1 = ([profile.userID isEqualToNumber:playerID] == NO);
|
|
BOOL check2 = ([self isLoggedIn]);
|
|
if (check1 && check2)
|
|
{
|
|
[self configureUserButtons];
|
|
}
|
|
self.title = [NSString stringWithFormat:NSLocalizedString(@"ProfileTitleFormat", nil), profile.username];
|
|
_myGamesViewController.sortTitle = [NSString stringWithFormat:NSLocalizedString(@"FriendPlacesFormat", nil), _profile.username];
|
|
|
|
//if we are on the Other's Profile page and we are looking at our own profile,
|
|
// hide the friends list if the new layout is active, because their friends list is on the home page
|
|
if ([UserInfo CurrentPlayer].userId && _profile.userID && [_profile.userID isEqualToNumber:[UserInfo CurrentPlayer].userId] && [self isNewLayout])
|
|
{
|
|
_friendsContainerView.hidden = YES;
|
|
[self layoutCollectionViews];
|
|
}
|
|
}
|
|
}
|
|
- (void) configureUserButtons
|
|
{
|
|
int visibleButtons = 4;
|
|
|
|
//make sure we have not navigated to the current user's public profile
|
|
|
|
// We need to hide the message button and adjust the position of other buttons
|
|
// if we are looking at the Roblox profile
|
|
bool isRoblox = ([self.userId intValue] == 1);
|
|
|
|
if (isRoblox)
|
|
{
|
|
_sendMessageButton.hidden = YES;
|
|
visibleButtons = 4;
|
|
}
|
|
else
|
|
_sendMessageButton.hidden = NO;
|
|
|
|
if(_profile.friendshipStatus == RBXFriendshipStatusNonFriends)
|
|
{
|
|
[_sendMessageButton setImage:[UIImage imageNamed:@"Send Message Disabled"] forState:UIControlStateDisabled];
|
|
_sendMessageButton.enabled = false;
|
|
}
|
|
|
|
_friendshipButton.hidden = NO;
|
|
_followIntoGameButton.hidden = NO;
|
|
_followUserButton.hidden = NO;
|
|
|
|
//set up the follow into game button
|
|
[_followIntoGameButton setImage:[UIImage imageNamed:@"Join Friend Game"] forState:UIControlStateNormal];
|
|
[_followIntoGameButton setImage:[UIImage imageNamed:@"Join Friend Down"] forState:UIControlStateSelected];
|
|
[_followIntoGameButton setImage:[UIImage imageNamed:@"Join Friend Disabled"] forState:UIControlStateDisabled];
|
|
|
|
//set up the friendship button with all of its states
|
|
[self updateFriendshipButton];
|
|
|
|
//update the follow user button
|
|
[self updateFollowButton];
|
|
|
|
|
|
//update the layout of the buttons based on what is visible
|
|
float origin = CGRectGetMaxX(_avatarImageView.frame);
|
|
float screenSpace = CGRectGetMinX(_friendsTitle.frame) - origin;
|
|
float buttonSpace = screenSpace / visibleButtons;
|
|
|
|
//position the buttons
|
|
int index = 0;
|
|
if (!isRoblox)
|
|
[_sendMessageButton setX:(origin + (buttonSpace * index++))];
|
|
|
|
[_friendshipButton setX:(origin + (buttonSpace * index++))];
|
|
[_followUserButton setX:(origin + (buttonSpace * index++))];
|
|
[_followIntoGameButton setX:(origin + (buttonSpace * index))];
|
|
}
|
|
- (void) showUserOnlineStatus
|
|
{
|
|
//update the interface with values corresponding to the user's online status
|
|
bool isPlayerOnline = _userPresence.isOnline;
|
|
bool lastPlaceExists = _userPresence.placeID != nil;
|
|
_followIntoGameButton.enabled = (isPlayerOnline && lastPlaceExists);
|
|
//_followIntoGameButton.hidden = !_followIntoGameButton.enabled;
|
|
|
|
//TODO: Display when the player was last online
|
|
|
|
|
|
//TODO: Display a green or red dot next to avatar to indicate if the player is online
|
|
NSString* imageName = _userPresence.isOnline ? @"User Online" : @"User Offline";
|
|
[_userOnlineMarker setImage:[UIImage imageNamed:imageName]];
|
|
|
|
//TODO: Display what game the user was last in
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark User Interface Actions
|
|
//Main Buttons
|
|
- (IBAction)didPressSendMessage:(id)sender
|
|
{
|
|
[self performSegueWithIdentifier:@"composeMessage" sender:nil];
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonMessage withContext:RBXAContextProfile];
|
|
}
|
|
- (IBAction)didPressFollowIntoGame:(id)sender
|
|
{
|
|
//before we follow into the game, check if the player is still online and in game
|
|
if (_userId)
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonJoinInGame
|
|
withContext:RBXAContextProfile
|
|
withCustomDataString:_userId.stringValue];
|
|
|
|
[RobloxHUD showSpinnerWithLabel:NSLocalizedString(@"ProfileCheckUserPresenceWord", nil) dimBackground:YES];
|
|
[RobloxData fetchPresenceForUser:_userId withCompletion:^(RBXUserPresence *presence)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
_userPresence = presence;
|
|
[RobloxHUD hideSpinner:YES];
|
|
|
|
//check if the player is still online and still in a game
|
|
if (presence.isOnline && presence.placeID != nil)
|
|
{
|
|
//if they are, attempt to follow them into the game
|
|
RBGameViewController* controller = [[RBGameViewController alloc] initWithLaunchParams:[RBXGameLaunchParams InitParamsForFollowUser:[_profile.userID integerValue]]];
|
|
[self presentViewController:controller animated:NO completion:nil];
|
|
}
|
|
else
|
|
{
|
|
//looks like they are no longer online, let's update the user presence
|
|
[self showUserOnlineStatus];
|
|
|
|
//alert the user that this won't work
|
|
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"GenericFailedGameFollowErrorTitle", nil)
|
|
message:NSLocalizedString(@"GenericFailedGameFollowErrorMessage", nil)
|
|
delegate:nil
|
|
cancelButtonTitle:NSLocalizedString(@"OkayWord", nil)
|
|
otherButtonTitles:nil];
|
|
[alert show];
|
|
}
|
|
});
|
|
}];
|
|
}
|
|
}
|
|
|
|
//See All Buttons
|
|
- (IBAction)didPressSeeAllFriends:(id)sender
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonSeeAll withContext:RBXAContextProfile withCustomDataString:@"friends"];
|
|
RBFullFriendListScreenController* controller = [[RBFullFriendListScreenController alloc] init];
|
|
controller.playerID = _profile.userID;
|
|
controller.playerName = _profile.username;
|
|
controller.listTypeValue = RBListTypeFriends;
|
|
controller.title = [NSString stringWithFormat:NSLocalizedString(@"UserFriends", nil), _profile.username];
|
|
[self.navigationController pushViewController:controller animated:YES];
|
|
}
|
|
- (IBAction)didPressSeeAllFollowers:(id)sender
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonSeeAll withContext:RBXAContextProfile withCustomDataString:@"followers"];
|
|
RBFullFriendListScreenController* controller = [[RBFullFriendListScreenController alloc] init];
|
|
controller.playerID = _profile.userID;
|
|
controller.playerName = _profile.username;
|
|
controller.listTypeValue = RBListTypeFollowers;
|
|
controller.title = [NSString stringWithFormat:NSLocalizedString(@"UserFollowers", nil), _profile.username];
|
|
[self.navigationController pushViewController:controller animated:YES];
|
|
}
|
|
- (IBAction)didPressSeeAllFollowing:(id)sender
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonSeeAll withContext:RBXAContextProfile withCustomDataString:@"following"];
|
|
RBFullFriendListScreenController* controller = [[RBFullFriendListScreenController alloc] init];
|
|
controller.playerID = _profile.userID;
|
|
controller.playerName = _profile.username;
|
|
controller.listTypeValue = RBListTypeFollowing;
|
|
controller.title = [NSString stringWithFormat:NSLocalizedString(@"UserFollowing", nil), _profile.username];
|
|
[self.navigationController pushViewController:controller animated:YES];
|
|
}
|
|
|
|
|
|
- (void) showGameDetails:(RBXGameData*)gameData
|
|
{
|
|
RBWebGamePreviewScreenController* controller = [[RBWebGamePreviewScreenController alloc] init];
|
|
controller.gameData = gameData;
|
|
[self.navigationController pushViewController:controller animated:YES];
|
|
}
|
|
|
|
- (void) seeAllGamesForSort:(NSNumber*)sortID
|
|
{
|
|
RBSingleSortScreenController* controller = [[RBSingleSortScreenController alloc] init];
|
|
controller.sortID = sortID;
|
|
controller.playerID = [self getUserID];
|
|
[self.navigationController pushViewController:controller animated:YES];
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Collection View Delegate Methods
|
|
|
|
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
|
|
{
|
|
if (collectionView == _badgesCollectionView) {
|
|
int numSections = 0;
|
|
if (_robloxBadges.count > 0) numSections++;
|
|
if (_playerBadges.count > 0) numSections++;
|
|
|
|
return numSections;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
|
|
{
|
|
if(collectionView == _badgesCollectionView)
|
|
{
|
|
switch (section)
|
|
{
|
|
case 0:
|
|
if (_robloxBadges.count > 0)
|
|
return _robloxBadges.count;
|
|
else
|
|
//there is the possibility that the player has no roblox badges, but they have player badges, so just shift the sections
|
|
return _playerBadges.count;
|
|
break;
|
|
case 1:
|
|
return _playerBadges.count;
|
|
break;
|
|
default:
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
else if(collectionView == _friendsCollectionView)
|
|
{
|
|
return _friends.count;
|
|
}
|
|
else if (collectionView == _followersCollectionView)
|
|
{
|
|
return _followers.count;
|
|
}
|
|
else if (collectionView == _followingCollectionView)
|
|
{
|
|
return _following.count;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
if ([collectionView isEqual:_badgesCollectionView])
|
|
{
|
|
switch (indexPath.section)
|
|
{
|
|
case 0:
|
|
{
|
|
if (_robloxBadges.count > 0)
|
|
{
|
|
RBXRobloxBadgeCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:ROBLOXBADGECELL_ID forIndexPath:indexPath];
|
|
cell.badgeInfo = _robloxBadges[indexPath.row];
|
|
return cell;
|
|
}
|
|
|
|
//there is the possibility that the player has no roblox badges, but they have player badges, so just shift the sections
|
|
RBXPlayerBadgeCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:PLAYERBADGECELL_ID forIndexPath:indexPath];
|
|
cell.badgeInfo = _playerBadges[indexPath.row];
|
|
return cell;
|
|
}
|
|
break;
|
|
case 1:
|
|
{
|
|
RBXPlayerBadgeCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:PLAYERBADGECELL_ID forIndexPath:indexPath];
|
|
cell.badgeInfo = _playerBadges[indexPath.row];
|
|
return cell;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if ([collectionView isEqual:_friendsCollectionView])
|
|
{
|
|
RBPlayerThumbnailCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:FRIENDCELL_ID forIndexPath:indexPath];
|
|
cell.friendInfo = _friends[indexPath.row];
|
|
return cell;
|
|
}
|
|
else if ([collectionView isEqual:_followingCollectionView])
|
|
{
|
|
RBPlayerThumbnailCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:FOLLOWINGCELL_ID forIndexPath:indexPath];
|
|
cell.friendInfo = _following[indexPath.row];
|
|
return cell;
|
|
}
|
|
else if ([collectionView isEqual:_followersCollectionView])
|
|
{
|
|
RBPlayerThumbnailCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:FOLLOWERCELL_ID forIndexPath:indexPath];
|
|
cell.friendInfo = _followers[indexPath.row];
|
|
return cell;
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
|
|
|
|
if ([collectionView isEqual:_friendsCollectionView])
|
|
{
|
|
RBXFriendInfo* friendInfo = _friends[indexPath.row];
|
|
[self pushProfileControllerWithUserID:friendInfo.userID];
|
|
}
|
|
else if ([collectionView isEqual:_followersCollectionView])
|
|
{
|
|
RBXFriendInfo* friendInfo = _followers[indexPath.row];
|
|
[self pushProfileControllerWithUserID:friendInfo.userID];
|
|
}
|
|
else if ([collectionView isEqual:_followingCollectionView])
|
|
{
|
|
RBXFriendInfo* friendInfo = _following[indexPath.row];
|
|
[self pushProfileControllerWithUserID:friendInfo.userID];
|
|
}
|
|
else if ([collectionView isEqual:_badgesCollectionView])
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonBadge withContext:RBXAContextProfile];
|
|
RBXBadgeInfo* badge;
|
|
if (indexPath.section == 0)
|
|
//There is a possibility that there are no roblox badges, but there might be player badges
|
|
badge = ((_robloxBadges.count) ? _robloxBadges[indexPath.row] : _playerBadges[indexPath.row]);
|
|
else
|
|
badge = _playerBadges[indexPath.row];
|
|
|
|
if (!badge) return;
|
|
GameBadgeViewController* badgePopup = [[GameBadgeViewController alloc] initWithBadgeInfo:badge];
|
|
[self.navigationController presentViewController:badgePopup animated:YES completion:nil];
|
|
}
|
|
}
|
|
|
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
|
|
{
|
|
if( [segue.identifier isEqualToString:@"composeMessage"] )
|
|
{
|
|
RBMessageComposeScreenController* controller = segue.destinationViewController;
|
|
[controller sendMessageToUser:_profile.userID name:_profile.username];
|
|
}
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Friendship
|
|
|
|
- (void)updateFriendshipButton
|
|
{
|
|
switch(_profile.friendshipStatus)
|
|
{
|
|
case RBXFriendshipStatusNonFriends:
|
|
[_friendshipButton setImage:[UIImage imageNamed:@"Friend Request Button"] forState:UIControlStateNormal];
|
|
break;
|
|
case RBXFriendshipStatusRequestSent:
|
|
[_friendshipButton setImage:[UIImage imageNamed:@"Friend Request Sent"] forState:UIControlStateNormal];
|
|
break;
|
|
case RBXFriendshipStatusRequestReceived:
|
|
[_friendshipButton setImage:[UIImage imageNamed:@"Friend Request Confirm"] forState:UIControlStateNormal];
|
|
break;
|
|
case RBXFriendshipStatusFriends:
|
|
[_friendshipButton setImage:[UIImage imageNamed:@"Friend Button"] forState:UIControlStateNormal];
|
|
break;
|
|
case RBXFriendshipStatusBestFriends:
|
|
[_friendshipButton setImage:[UIImage imageNamed:@"Friend Button"] forState:UIControlStateNormal];
|
|
break;
|
|
}
|
|
}
|
|
|
|
- (IBAction)friendshipButtonTouchUpInside:(id)sender
|
|
{
|
|
switch (_profile.friendshipStatus)
|
|
{
|
|
case RBXFriendshipStatusNonFriends:
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonFriendRequest withContext:RBXAContextProfile withCustomDataString:@"makeFriend"];
|
|
//check if the user has exceeded 200 friends
|
|
if (_userFriendCount >= MAX_PLAYER_FRIENDS)
|
|
{
|
|
//display an error message and quit
|
|
[RobloxHUD showMessage:NSLocalizedString(@"MaxFriendCountError", nil)];
|
|
return;
|
|
}
|
|
else if (_userFriendCount == ERROR_PLAYER_FRIENDS)
|
|
{
|
|
//display an error message and quit
|
|
[RobloxHUD showMessage:NSLocalizedString(@"GenericFailedFriendRequestError", nil)];
|
|
return;
|
|
}
|
|
|
|
[RobloxHUD showSpinnerWithLabel:nil dimBackground:YES];
|
|
[RobloxData requestFrienshipWithUserID:_profile.userID completion:^(BOOL success)
|
|
{
|
|
[RobloxHUD hideSpinner:YES];
|
|
if(success)
|
|
{
|
|
_profile.friendshipStatus = RBXFriendshipStatusRequestSent;
|
|
[self updateFriendshipButton];
|
|
}
|
|
else
|
|
{
|
|
[RobloxHUD showMessage:NSLocalizedString(@"GenericFailedFriendRequestError", nil)];
|
|
}
|
|
}];
|
|
break;
|
|
}
|
|
case RBXFriendshipStatusRequestSent:
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonFriendRequest withContext:RBXAContextProfile withCustomDataString:@"requestAlreadySent"];
|
|
// Nothing to do
|
|
break;
|
|
}
|
|
case RBXFriendshipStatusFriends:
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonFriendRequest withContext:RBXAContextProfile withCustomDataString:@"alreadyFriends"];
|
|
RBFriendshipActionSheet* actionSheet = [[RBFriendshipActionSheet alloc] initFriendSheetFromProfile:self];
|
|
[actionSheet showFromRect:_friendshipButton.frame inView:_friendshipButton.superview animated:YES];
|
|
break;
|
|
}
|
|
case RBXFriendshipStatusBestFriends:
|
|
{
|
|
RBFriendshipActionSheet* actionSheet = [[RBFriendshipActionSheet alloc] initFriendSheetFromProfile:self];
|
|
[actionSheet showFromRect:_friendshipButton.frame inView:_friendshipButton.superview animated:YES];
|
|
break;
|
|
}
|
|
case RBXFriendshipStatusRequestReceived:
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonFriendRequest withContext:RBXAContextProfile withCustomDataString:@"attemptConfirmRequest"];
|
|
// Nothing to do
|
|
//TO DO : Offer Dialog Box to Accept / Reject Friend Requests
|
|
//RBFriendshipActionSheet* actionSheet = [[RBFriendshipActionSheet alloc] initFriendRequestSheetFromProfile:self];
|
|
//[actionSheet showFromRect:_friendshipButton.frame inView:_friendshipButton.superview animated:YES];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark Followers
|
|
- (void)updateFollowButton
|
|
{
|
|
NSString* imageName = (_profile.isFollowing) ? @"Following User Button" : @"Follow User Button";
|
|
[_followUserButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
|
|
}
|
|
|
|
- (IBAction)didPressFollowUser:(id)sender
|
|
{
|
|
[RobloxHUD showSpinnerWithLabel:nil dimBackground:YES];
|
|
if (_profile.isFollowing)
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonFollow withContext:RBXAContextProfile withCustomDataString:@"unfollow"];
|
|
|
|
//we should not follow anymore
|
|
[RobloxData unfollowUser:_profile.userID completion:^(BOOL success) {
|
|
if (success)
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
_profile.isFollowing = NO;
|
|
[self updateFollowButton];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RBX_NOTIFY_FOLLOWING_UPDATED object:nil];
|
|
});
|
|
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
[RobloxHUD hideSpinner:YES];
|
|
[self fetchFollowersForUser:_profile.userID];
|
|
});
|
|
|
|
}];
|
|
}
|
|
else
|
|
{
|
|
[[RBXEventReporter sharedInstance] reportButtonClick:RBXAButtonFollow withContext:RBXAContextProfile withCustomDataString:@"follow"];
|
|
|
|
//let's follow this cool dude
|
|
[RobloxData followUser:_profile.userID completion:^(BOOL success) {
|
|
if (success)
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
_profile.isFollowing = YES;
|
|
[self updateFollowButton];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RBX_NOTIFY_FOLLOWING_UPDATED object:nil];
|
|
});
|
|
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
[RobloxHUD hideSpinner:YES];
|
|
[self fetchFollowersForUser:_profile.userID];
|
|
});
|
|
}];
|
|
}
|
|
|
|
|
|
}
|
|
@end
|
|
|
|
|
|
|
|
|
|
|