mirror of
https://github.com/wahyd4/Yep.git
synced 2026-08-16 16:28:45 +10:00
493 lines
19 KiB
Swift
493 lines
19 KiB
Swift
//
|
|
// EditProfileViewController.swift
|
|
// Yep
|
|
//
|
|
// Created by NIX on 15/4/24.
|
|
// Copyright (c) 2015年 Catch Inc. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import RealmSwift
|
|
import TPKeyboardAvoiding
|
|
import Proposer
|
|
import Navi
|
|
|
|
class EditProfileViewController: UIViewController {
|
|
|
|
struct Notification {
|
|
static let Logout = "LogoutNotification"
|
|
}
|
|
|
|
@IBOutlet weak var avatarImageView: UIImageView!
|
|
@IBOutlet weak var avatarImageViewWidthConstraint: NSLayoutConstraint!
|
|
|
|
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
|
|
|
|
@IBOutlet weak var mobileLabel: UILabel!
|
|
|
|
@IBOutlet weak var editProfileTableView: TPKeyboardAvoidingTableView!
|
|
|
|
lazy var imagePicker: UIImagePickerController = {
|
|
let imagePicker = UIImagePickerController()
|
|
imagePicker.delegate = self
|
|
imagePicker.allowsEditing = true
|
|
return imagePicker
|
|
}()
|
|
|
|
lazy var doneButton: UIBarButtonItem = {
|
|
let button = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "saveIntroduction:")
|
|
return button
|
|
}()
|
|
|
|
let editProfileLessInfoCellIdentifier = "EditProfileLessInfoCell"
|
|
let editProfileMoreInfoCellIdentifier = "EditProfileMoreInfoCell"
|
|
let editProfileColoredTitleCellIdentifier = "EditProfileColoredTitleCell"
|
|
|
|
var introduction: String {
|
|
get {
|
|
return YepUserDefaults.introduction.value ?? NSLocalizedString("No Introduction yet.", comment: "")
|
|
}
|
|
}
|
|
|
|
let introAttributes = [NSFontAttributeName: YepConfig.EditProfile.introFont]
|
|
|
|
struct Listener {
|
|
static let Nickname = "EditProfileLessInfoCell.Nickname"
|
|
static let Introduction = "EditProfileLessInfoCell.Introduction"
|
|
static let Badge = "EditProfileLessInfoCell.Badge"
|
|
}
|
|
|
|
deinit {
|
|
YepUserDefaults.nickname.removeListenerWithName(Listener.Nickname)
|
|
YepUserDefaults.introduction.removeListenerWithName(Listener.Introduction)
|
|
YepUserDefaults.badge.removeListenerWithName(Listener.Badge)
|
|
|
|
editProfileTableView?.delegate = nil
|
|
|
|
println("deinit EditProfileViewController")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
title = NSLocalizedString("Edit Profile", comment: "")
|
|
|
|
let avatarSize = YepConfig.editProfileAvatarSize()
|
|
avatarImageViewWidthConstraint.constant = avatarSize
|
|
|
|
updateAvatar() {
|
|
}
|
|
|
|
mobileLabel.text = YepUserDefaults.fullPhoneNumber
|
|
|
|
editProfileTableView.registerNib(UINib(nibName: editProfileLessInfoCellIdentifier, bundle: nil), forCellReuseIdentifier: editProfileLessInfoCellIdentifier)
|
|
editProfileTableView.registerNib(UINib(nibName: editProfileMoreInfoCellIdentifier, bundle: nil), forCellReuseIdentifier: editProfileMoreInfoCellIdentifier)
|
|
editProfileTableView.registerNib(UINib(nibName: editProfileColoredTitleCellIdentifier, bundle: nil), forCellReuseIdentifier: editProfileColoredTitleCellIdentifier)
|
|
}
|
|
|
|
// MARK: Actions
|
|
|
|
func updateAvatar(completion:() -> Void) {
|
|
if let avatarURLString = YepUserDefaults.avatarURLString.value {
|
|
|
|
let avatarSize = YepConfig.editProfileAvatarSize()
|
|
let avatarStyle: AvatarStyle = .RoundedRectangle(size: CGSize(width: avatarSize, height: avatarSize), cornerRadius: avatarSize * 0.5, borderWidth: 0)
|
|
let plainAvatar = PlainAvatar(avatarURLString: avatarURLString, avatarStyle: avatarStyle)
|
|
avatarImageView.navi_setAvatar(plainAvatar, withFadeTransitionDuration: avatarFadeTransitionDuration)
|
|
|
|
completion()
|
|
}
|
|
}
|
|
|
|
@IBAction func changeAvatar(sender: UITapGestureRecognizer) {
|
|
|
|
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
|
|
|
|
let choosePhotoAction: UIAlertAction = UIAlertAction(title: NSLocalizedString("Choose Photo", comment: ""), style: .Default) { action -> Void in
|
|
|
|
let openCameraRoll: ProposerAction = { [weak self] in
|
|
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum) {
|
|
if let strongSelf = self {
|
|
strongSelf.imagePicker.sourceType = .PhotoLibrary
|
|
strongSelf.presentViewController(strongSelf.imagePicker, animated: true, completion: nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
proposeToAccess(.Photos, agreed: openCameraRoll, rejected: {
|
|
self.alertCanNotAccessCameraRoll()
|
|
})
|
|
}
|
|
alertController.addAction(choosePhotoAction)
|
|
|
|
let takePhotoAction: UIAlertAction = UIAlertAction(title: NSLocalizedString("Take Photo", comment: ""), style: .Default) { action -> Void in
|
|
|
|
let openCamera: ProposerAction = { [weak self] in
|
|
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera){
|
|
if let strongSelf = self {
|
|
strongSelf.imagePicker.sourceType = .Camera
|
|
strongSelf.presentViewController(strongSelf.imagePicker, animated: true, completion: nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
proposeToAccess(.Camera, agreed: openCamera, rejected: {
|
|
self.alertCanNotOpenCamera()
|
|
})
|
|
}
|
|
alertController.addAction(takePhotoAction)
|
|
|
|
let cancelAction: UIAlertAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel) { action -> Void in
|
|
self.dismissViewControllerAnimated(true, completion: nil)
|
|
}
|
|
alertController.addAction(cancelAction)
|
|
|
|
self.presentViewController(alertController, animated: true, completion: nil)
|
|
|
|
// touch to create (if need) for faster appear
|
|
delay(0.2) { [weak self] in
|
|
self?.imagePicker.hidesBarsOnTap = false
|
|
}
|
|
}
|
|
|
|
func saveIntroduction(sender: UIBarButtonItem) {
|
|
|
|
let introductionCellIndexPath = NSIndexPath(forRow: InfoRow.Intro.rawValue, inSection: Section.Info.rawValue)
|
|
if let introductionCell = editProfileTableView.cellForRowAtIndexPath(introductionCellIndexPath) as? EditProfileMoreInfoCell {
|
|
introductionCell.infoTextView.resignFirstResponder()
|
|
}
|
|
}
|
|
}
|
|
|
|
extension EditProfileViewController: UITableViewDataSource, UITableViewDelegate {
|
|
|
|
enum Section: Int {
|
|
case Info
|
|
case LogOut
|
|
}
|
|
|
|
enum InfoRow: Int {
|
|
case Username = 0
|
|
case Nickname
|
|
case Intro
|
|
}
|
|
|
|
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
|
|
return 2
|
|
}
|
|
|
|
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
|
|
switch section {
|
|
|
|
case Section.Info.rawValue:
|
|
return 3
|
|
|
|
case Section.LogOut.rawValue:
|
|
return 1
|
|
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
|
|
|
switch indexPath.section {
|
|
|
|
case Section.Info.rawValue:
|
|
|
|
switch indexPath.row {
|
|
|
|
case InfoRow.Username.rawValue:
|
|
|
|
let cell = tableView.dequeueReusableCellWithIdentifier(editProfileLessInfoCellIdentifier) as! EditProfileLessInfoCell
|
|
|
|
cell.annotationLabel.text = NSLocalizedString("Username", comment: "")
|
|
|
|
var username = ""
|
|
if let
|
|
myUserID = YepUserDefaults.userID.value,
|
|
realm = try? Realm(),
|
|
me = userWithUserID(myUserID, inRealm: realm) {
|
|
username = me.username
|
|
}
|
|
|
|
if username.isEmpty {
|
|
cell.infoLabel.text = NSLocalizedString("None", comment: "")
|
|
cell.accessoryImageView.hidden = false
|
|
cell.selectionStyle = .Default
|
|
} else {
|
|
cell.infoLabel.text = username
|
|
cell.accessoryImageView.hidden = true
|
|
cell.selectionStyle = .None
|
|
}
|
|
|
|
cell.badgeImageView.image = nil
|
|
cell.infoLabelTrailingConstraint.constant = EditProfileLessInfoCell.ConstraintConstant.minInfoLabelTrailing
|
|
|
|
return cell
|
|
|
|
case InfoRow.Nickname.rawValue:
|
|
|
|
let cell = tableView.dequeueReusableCellWithIdentifier(editProfileLessInfoCellIdentifier) as! EditProfileLessInfoCell
|
|
|
|
cell.annotationLabel.text = NSLocalizedString("Nickname", comment: "")
|
|
cell.accessoryImageView.hidden = false
|
|
cell.selectionStyle = .Default
|
|
|
|
YepUserDefaults.nickname.bindAndFireListener(Listener.Nickname) { [weak cell] nickname in
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
cell?.infoLabel.text = nickname
|
|
}
|
|
}
|
|
|
|
YepUserDefaults.badge.bindAndFireListener(Listener.Badge) { [weak cell] badgeName in
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
if let badgeName = badgeName, badge = BadgeView.Badge(rawValue: badgeName) {
|
|
cell?.badgeImageView.image = badge.image
|
|
cell?.badgeImageView.tintColor = badge.color
|
|
cell?.infoLabelTrailingConstraint.constant = EditProfileLessInfoCell.ConstraintConstant.normalInfoLabelTrailing
|
|
|
|
} else {
|
|
cell?.badgeImageView.image = nil
|
|
cell?.infoLabelTrailingConstraint.constant = EditProfileLessInfoCell.ConstraintConstant.minInfoLabelTrailing
|
|
}
|
|
}
|
|
}
|
|
|
|
return cell
|
|
|
|
case InfoRow.Intro.rawValue:
|
|
|
|
let cell = tableView.dequeueReusableCellWithIdentifier(editProfileMoreInfoCellIdentifier) as! EditProfileMoreInfoCell
|
|
|
|
cell.annotationLabel.text = NSLocalizedString("Introduction", comment: "")
|
|
|
|
YepUserDefaults.introduction.bindAndFireListener(Listener.Introduction) { [weak cell] introduction in
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
cell?.infoTextView.text = introduction ?? NSLocalizedString("Introduce yourself here.", comment: "")
|
|
}
|
|
}
|
|
|
|
cell.infoTextViewIsDirtyAction = { [weak self] isDirty in
|
|
self?.navigationItem.rightBarButtonItem = self?.doneButton
|
|
self?.doneButton.enabled = isDirty
|
|
}
|
|
|
|
cell.infoTextViewDidEndEditingAction = { [weak self] newIntroduction in
|
|
self?.doneButton.enabled = false
|
|
|
|
if let oldIntroduction = YepUserDefaults.introduction.value {
|
|
if oldIntroduction == newIntroduction {
|
|
return
|
|
}
|
|
}
|
|
|
|
YepHUD.showActivityIndicator()
|
|
|
|
updateMyselfWithInfo(["introduction": newIntroduction], failureHandler: { (reason, errorMessage) in
|
|
defaultFailureHandler(reason, errorMessage: errorMessage)
|
|
|
|
YepHUD.hideActivityIndicator()
|
|
|
|
}, completion: { success in
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
YepUserDefaults.introduction.value = newIntroduction
|
|
|
|
self?.editProfileTableView.reloadData()
|
|
}
|
|
|
|
YepHUD.hideActivityIndicator()
|
|
})
|
|
}
|
|
|
|
return cell
|
|
|
|
default:
|
|
return UITableViewCell()
|
|
}
|
|
|
|
case Section.LogOut.rawValue:
|
|
let cell = tableView.dequeueReusableCellWithIdentifier(editProfileColoredTitleCellIdentifier) as! EditProfileColoredTitleCell
|
|
cell.coloredTitleLabel.text = NSLocalizedString("Log out", comment: "")
|
|
cell.coloredTitleColor = UIColor.redColor()
|
|
return cell
|
|
|
|
default:
|
|
return UITableViewCell()
|
|
}
|
|
}
|
|
|
|
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
|
|
|
switch indexPath.section {
|
|
|
|
case Section.Info.rawValue:
|
|
|
|
switch indexPath.row {
|
|
|
|
case InfoRow.Username.rawValue:
|
|
return 60
|
|
|
|
case InfoRow.Nickname.rawValue:
|
|
return 60
|
|
|
|
case InfoRow.Intro.rawValue:
|
|
|
|
let tableViewWidth = CGRectGetWidth(editProfileTableView.bounds)
|
|
let introLabelMaxWidth = tableViewWidth - YepConfig.EditProfile.introInset
|
|
|
|
let rect = introduction.boundingRectWithSize(CGSize(width: introLabelMaxWidth, height: CGFloat(FLT_MAX)), options: [.UsesLineFragmentOrigin, .UsesFontLeading], attributes: introAttributes, context: nil)
|
|
|
|
let height = 20 + 22 + 10 + ceil(rect.height) + 20
|
|
|
|
return max(height, 120)
|
|
|
|
default:
|
|
return 0
|
|
}
|
|
|
|
case Section.LogOut.rawValue:
|
|
return 60
|
|
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
|
|
|
tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
|
|
|
switch indexPath.section {
|
|
|
|
case Section.Info.rawValue:
|
|
|
|
switch indexPath.row {
|
|
|
|
case InfoRow.Username.rawValue:
|
|
|
|
if let
|
|
myUserID = YepUserDefaults.userID.value,
|
|
me = userWithUserID(myUserID, inRealm: try! Realm()) {
|
|
|
|
let username = me.username
|
|
|
|
if username.isEmpty {
|
|
|
|
YepAlert.textInput(title: NSLocalizedString("Set Username", comment: ""), message: NSLocalizedString("Please note that you can only set username once.", comment: ""), placeholder: NSLocalizedString("use letters, numbers, and underscore", comment: ""), oldText: nil, confirmTitle: NSLocalizedString("Set", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { text in
|
|
|
|
let newUsername = text
|
|
|
|
updateMyselfWithInfo(["username": newUsername], failureHandler: { [weak self] reason, errorMessage in
|
|
defaultFailureHandler(reason, errorMessage: errorMessage)
|
|
|
|
YepAlert.alertSorry(message: errorMessage ?? NSLocalizedString("Set username failed!", comment: ""), inViewController: self)
|
|
|
|
}, completion: { success in
|
|
dispatch_async(dispatch_get_main_queue()) { [weak tableView] in
|
|
guard let realm = try? Realm() else {
|
|
return
|
|
}
|
|
|
|
if let
|
|
myUserID = YepUserDefaults.userID.value,
|
|
me = userWithUserID(myUserID, inRealm: realm) {
|
|
let _ = try? realm.write {
|
|
me.username = newUsername
|
|
}
|
|
}
|
|
|
|
// update UI
|
|
|
|
if let usernameCell = tableView?.cellForRowAtIndexPath(indexPath) as? EditProfileLessInfoCell {
|
|
usernameCell.infoLabel.text = newUsername
|
|
}
|
|
}
|
|
})
|
|
|
|
}, cancelAction: {
|
|
})
|
|
}
|
|
}
|
|
|
|
case InfoRow.Nickname.rawValue:
|
|
performSegueWithIdentifier("showEditNicknameAndBadge", sender: nil)
|
|
|
|
default:
|
|
break
|
|
}
|
|
|
|
case Section.LogOut.rawValue:
|
|
|
|
YepAlert.confirmOrCancel(title: NSLocalizedString("Notice", comment: ""), message: NSLocalizedString("Do you want to logout?", comment: ""), confirmTitle: NSLocalizedString("Yes", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { () -> Void in
|
|
|
|
unregisterThirdPartyPush()
|
|
|
|
cleanRealmAndCaches()
|
|
|
|
YepUserDefaults.cleanAllUserDefaults()
|
|
|
|
if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
|
|
appDelegate.startShowStory()
|
|
}
|
|
|
|
}, cancelAction: { () -> Void in
|
|
})
|
|
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: UIImagePicker
|
|
|
|
extension EditProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
|
|
|
|
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
|
|
|
|
activityIndicator.startAnimating()
|
|
|
|
let image = image.largestCenteredSquareImage().resizeToTargetSize(YepConfig.avatarMaxSize())
|
|
let imageData = UIImageJPEGRepresentation(image, YepConfig.avatarCompressionQuality())
|
|
|
|
s3UploadFileOfKind(.Avatar, inFilePath: nil, orFileData: imageData, mimeType: MessageMediaType.Image.mineType, failureHandler: { (reason, errorMessage) in
|
|
|
|
defaultFailureHandler(reason, errorMessage: errorMessage)
|
|
|
|
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
|
self?.activityIndicator.stopAnimating()
|
|
}
|
|
|
|
}, completion: { s3UploadParams in
|
|
|
|
let newAvatarURLString = "\(s3UploadParams.url)\(s3UploadParams.key)"
|
|
|
|
updateMyselfWithInfo(["avatar_url": newAvatarURLString], failureHandler: { (reason, errorMessage) in
|
|
defaultFailureHandler(reason, errorMessage: errorMessage)
|
|
|
|
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
|
self?.activityIndicator.stopAnimating()
|
|
}
|
|
|
|
}, completion: { success in
|
|
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
|
|
YepUserDefaults.avatarURLString.value = newAvatarURLString
|
|
|
|
self.updateAvatar() {
|
|
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
|
self?.activityIndicator.stopAnimating()
|
|
}
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
dismissViewControllerAnimated(true, completion: nil)
|
|
}
|
|
}
|