-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/create chat room vc #29
Open
ojun9
wants to merge
34
commits into
master
Choose a base branch
from
feature/createChatRoomVC
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 29 commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
d200ce7
CreateChatRoomの各種ファイルを追加
ojun9 f151900
Storyboardに部品の配置をした
ojun9 f17d77a
カスタムセルを作って部品を接続した
ojun9 eaca76e
各cellのsetupを書いた
ojun9 ae1492c
CreateChatRoomViewControllerのセットアップを行った
ojun9 fc1e953
Searchのスペルが間違ってたのを修正
ojun9 9cdb665
ファイル名の最初が大文字になってたかったのを修正
ojun9 30e3bbf
デバックようにcellを表示した
ojun9 a9015c4
デバック用にimageを表示した
ojun9 6cd9b4a
serchUserTableviewを選択したときにデータをtableviewとcollectionviewに反映させる処理を書いた
ojun9 53e9783
radioImageViewに結果を反映させるようにした
ojun9 64d01bd
selectedUserCollectionViewのcellの表示を調整
ojun9 8cf5f94
selectedUserCollectionViewでバツボタン押せれた時に削除できるようにした
ojun9 74c38ab
キーボードが登場したときにcollectionviewを上に上げる処理を書いた
ojun9 7183396
キーボードを閉じる処理をcollectionviewの時はしないようにした
ojun9 68eec80
NavigationItemと各アイテムがタップされたときの処理を書いた
ojun9 8fc7cf1
searchBarSearchButtonClickedのときの処理を書いた
ojun9 1a5c774
バツボタン押してユーザ削除したときにtableviewに反映されない問題を修正
ojun9 97e2440
firestoreからwhereFieldでユーザを検索する機能を追加した
ojun9 b3b7879
activityIndicatorを追加して検索中にくるくるする処理を書いた
ojun9 a6f3baa
CollectionViewを表示/非表示するときにアニメーションを追加
ojun9 433dc02
presenterとviewにweakをつけた
ojun9 daf5d66
コメントの追加と,Rootを開発用に変更してたのを元に戻した
ojun9 9113277
TODOのコメントを追加
ojun9 64f6246
didTapCreateRoomButtonのタイポを修正
ojun9 b356c21
cellのviewの更新をcell内のconfigureでした
ojun9 6a23ac3
変数の1文字目が大文字になってるのを修正
ojun9 ed5a521
viewControllerから`searchedUsersArray `と`selectedUsersArray `を取り除いた
ojun9 a52e499
`DispatchQueue.main.async`が必要ないところを削除した
ojun9 d9a5050
Roomを保存する処理を書いた
ojun9 8f53c57
クロージャでcellを削除する処理を書いた
ojun9 8972caa
コードを一部整形
ojun9 6023a3d
cellの処理と配列の取得を変更
ojun9 9c71c2b
radioImageViewが見にくかったのを修正
ojun9 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
chat-iOS/Views/CreateChatRoom/CreateChatRoomViewBuilder.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// CreateChatRoomViewBuilder.swift | ||
// chat-iOS | ||
// | ||
// Created by jun on 2020/07/18. | ||
// | ||
|
||
import UIKit | ||
|
||
struct CreateChatRoomViewBuilder { | ||
static func create() -> UIViewController { | ||
guard let createChatRoomViewController = CreateChatRoomViewController.loadFromStoryboard() as? CreateChatRoomViewController else { | ||
fatalError("fatal: Failed to initialize the CreateChatRoomViewController") | ||
} | ||
let model = CreateChatRoomModel() | ||
let presenter = CreateChatRoomViewPresenter(model: model) | ||
createChatRoomViewController.inject(with: presenter) | ||
return createChatRoomViewController | ||
} | ||
} |
239 changes: 239 additions & 0 deletions
239
chat-iOS/Views/CreateChatRoom/CreateChatRoomViewController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
// | ||
// File.swift | ||
// chat-iOS | ||
// | ||
// Created by jun on 2020/07/18. | ||
// | ||
|
||
import UIKit | ||
|
||
final class CreateChatRoomViewController: UIViewController { | ||
private var presenter: CreateChatRoomViewPresenterProtocol! | ||
|
||
@IBOutlet weak var userNameSearchBar: UISearchBar! | ||
@IBOutlet weak var serchUserTableview: UITableView! | ||
@IBOutlet weak var selectedUserCollectionView: UICollectionView! | ||
|
||
@IBOutlet weak var selectedUserCollectionViewBottomsConstraints: NSLayoutConstraint! | ||
|
||
var activityIndicator = UIActivityIndicatorView() | ||
|
||
private let searchedUsersCellID = "SearchUserTableviewCell" | ||
private let selectedUsersCellID = "SelectedUserCollectionViewCell" | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
|
||
self.setupNavigationItem() | ||
self.setupUserSearchBar() | ||
self.setupSerchUserTableview() | ||
self.setupSelectedUserCollectionView() | ||
self.setupActivityIndicator() | ||
self.setupNotificationCenter() | ||
} | ||
|
||
private func setupNavigationItem() { | ||
self.navigationItem.title = "Choose friends" | ||
let stopItem = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(tapStopCreateRoomButton)) | ||
self.navigationItem.leftBarButtonItem = stopItem | ||
let saveItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(tapCreateRoomButton)) | ||
self.navigationItem.rightBarButtonItem = saveItem | ||
} | ||
|
||
private func setupUserSearchBar() { | ||
self.userNameSearchBar.placeholder = "Search by name" | ||
self.userNameSearchBar.delegate = self | ||
} | ||
|
||
private func setupSerchUserTableview() { | ||
self.serchUserTableview.rowHeight = 75 | ||
self.serchUserTableview.delegate = self | ||
self.serchUserTableview.dataSource = self | ||
self.serchUserTableview.tableFooterView = UIView() | ||
} | ||
|
||
private func setupSelectedUserCollectionView() { | ||
self.selectedUserCollectionView.isHidden = true | ||
self.selectedUserCollectionView.collectionViewLayout.invalidateLayout() | ||
self.selectedUserCollectionView.delegate = self | ||
self.selectedUserCollectionView.dataSource = self | ||
} | ||
|
||
private func setupActivityIndicator() { | ||
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50) | ||
self.activityIndicator.center = self.view.center | ||
self.activityIndicator.hidesWhenStopped = true | ||
self.view.addSubview(self.activityIndicator) | ||
} | ||
|
||
func setupNotificationCenter() { | ||
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShowNotification(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) | ||
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHideNotification(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) | ||
} | ||
|
||
/// キーボードが登場した時の処理 | ||
@objc func keyboardWillShowNotification(notification: NSNotification) { | ||
guard let userInfo = notification.userInfo else { return } | ||
guard let keyboard = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } | ||
|
||
self.selectedUserCollectionViewBottomsConstraints.constant = -keyboard.cgRectValue.height + self.view.safeAreaInsets.bottom | ||
UIView.animate(withDuration: 1.0, animations: { self.view.layoutIfNeeded() }) | ||
} | ||
|
||
/// キーボードが隠れた時の処理 | ||
@objc func keyboardWillHideNotification(notification: NSNotification) { | ||
guard notification.userInfo != nil else { return } | ||
|
||
self.selectedUserCollectionViewBottomsConstraints.constant = 0 | ||
UIView.animate(withDuration: 1.0, animations: { self.view.layoutIfNeeded() }) | ||
} | ||
|
||
@objc func tapStopCreateRoomButton() { | ||
self.presenter.didTapStopCreateRoomButton() | ||
} | ||
|
||
@objc func tapCreateRoomButton() { | ||
self.presenter.didTapCreateRoomutton() | ||
} | ||
|
||
/// `selectedUserCollectionView`にあるバツボタンタップされたときに呼ばれる関数。 | ||
/// - Parameter button: ボタンの`tag`でどのindexを消すかがわかる | ||
@objc func tapSelectedUserCollectionViewCellDeleteUserButton(_ button: UIButton) { | ||
self.presenter.didTapSelectedUserCollectionViewCellDeleteUserButton(index: button.tag) | ||
} | ||
|
||
func inject(with presenter: CreateChatRoomViewPresenterProtocol) { | ||
self.presenter = presenter | ||
self.presenter.view = self | ||
} | ||
} | ||
|
||
extension CreateChatRoomViewController: CreateChatRoomViewPresenterOutput { | ||
func reloadSerchUserTableview() { | ||
DispatchQueue.main.async { self.serchUserTableview.reloadData() } | ||
} | ||
|
||
func reloadSelectedUserCollectionView() { | ||
DispatchQueue.main.async { self.selectedUserCollectionView.reloadData() } | ||
guard self.selectedUserCollectionView.isHidden else { return } | ||
|
||
self.selectedUserCollectionView.alpha = 0 | ||
self.selectedUserCollectionView.isHidden = false | ||
UIView.animate( withDuration: 0.15, animations: { self.selectedUserCollectionView.alpha = 1 }, completion: nil) | ||
} | ||
|
||
func hiddenSelectedUsersCollectionView() { | ||
UIView.animate( | ||
withDuration: 0.25, | ||
animations: { self.selectedUserCollectionView.alpha = 0 }, | ||
completion: { _ in | ||
self.selectedUserCollectionView.isHidden = true | ||
self.selectedUserCollectionView.alpha = 1 | ||
} | ||
) | ||
} | ||
|
||
func dismissCreateChatRoomVC() { | ||
DispatchQueue.main.async { self.dismiss(animated: true, completion: nil) } | ||
} | ||
|
||
func clearSearchUserTableView() { | ||
DispatchQueue.main.async { self.serchUserTableview.reloadData() } | ||
} | ||
|
||
func startActivityIndicator() { | ||
DispatchQueue.main.async { self.activityIndicator.startAnimating() } | ||
} | ||
|
||
func stopActivityIndicator() { | ||
DispatchQueue.main.async { self.activityIndicator.stopAnimating() } | ||
} | ||
} | ||
|
||
extension CreateChatRoomViewController: UITableViewDelegate, UITableViewDataSource { | ||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | ||
return self.presenter.numberOfSearchedUsers | ||
} | ||
|
||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | ||
guard let cell = self.serchUserTableview.dequeueReusableCell(withIdentifier: self.searchedUsersCellID, for: indexPath) | ||
as? SearchUserTableviewCell else { return UITableViewCell() } | ||
|
||
let selectedUsersArray: [User] = self.presenter.getSelectedUsersArray() | ||
let searchedUsersArray: [User] = self.presenter.getSearchedUsersArray() | ||
let isSelected = !selectedUsersArray.filter({ $0.id == searchedUsersArray[indexPath.item].id ?? ""}).isEmpty | ||
cell.configure(with: searchedUsersArray[indexPath.item], isSelected: isSelected) | ||
|
||
//TODO:Firestoreから取得した後で表示し直すこと | ||
if #available(iOS 13.0, *) { | ||
cell.profileImageView.image = UIImage(systemName: "bolt.circle.fill") | ||
} else { | ||
// Fallback on earlier versions | ||
} | ||
|
||
return cell | ||
} | ||
|
||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | ||
let searchedUsersArray: [User] = self.presenter.getSearchedUsersArray() | ||
self.serchUserTableview.deselectRow(at: indexPath, animated: true) | ||
self.presenter.didSelectedSerchUserTableview(selectedUser: searchedUsersArray[indexPath.item]) | ||
} | ||
|
||
} | ||
|
||
extension CreateChatRoomViewController: UICollectionViewDelegate, UICollectionViewDataSource { | ||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { | ||
return self.presenter.numberOfSelectedUsers | ||
} | ||
|
||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | ||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: selectedUsersCellID, for: indexPath) as! SelectedUserCollectionViewCell | ||
let selectedUsersArray: [User] = self.presenter.getSelectedUsersArray() | ||
|
||
cell.userNameLabel.text = selectedUsersArray[indexPath.item].displayName | ||
|
||
cell.deleteUserButton.tag = indexPath.item | ||
cell.deleteUserButton.addTarget(self, action: #selector(tapSelectedUserCollectionViewCellDeleteUserButton(_:)), for: .touchUpInside) | ||
|
||
//TODO:Firestoreから取得した後で表示し直すこと | ||
if #available(iOS 13.0, *) { | ||
cell.profileImageView.image = UIImage(systemName: "bolt.circle.fill") | ||
} else { | ||
// Fallback on earlier versions | ||
} | ||
|
||
return cell | ||
} | ||
|
||
func numberOfSections(in collectionView: UICollectionView) -> Int { | ||
return 1 | ||
} | ||
|
||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { | ||
return CGSize(width: 85, height: 90) | ||
} | ||
|
||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { | ||
return UIEdgeInsets(top: 0.0, left: 10.0, bottom: 0.0, right: 10) | ||
} | ||
} | ||
|
||
extension CreateChatRoomViewController: UISearchBarDelegate { | ||
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { | ||
guard scrollView == self.serchUserTableview else { return } | ||
guard self.userNameSearchBar.isFirstResponder else { return } | ||
self.userNameSearchBar.resignFirstResponder() | ||
} | ||
|
||
/// 検索ボタンがタップされたときに呼ばれる関数 | ||
/// - Parameter searchBar: サーチバー | ||
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { | ||
guard let searchBarText = searchBar.text else { return } | ||
guard !searchBarText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return } | ||
guard self.userNameSearchBar.isFirstResponder else { return } | ||
self.userNameSearchBar.resignFirstResponder() | ||
|
||
self.presenter.didSearchBarSearchButtonClicked(searchText: searchBarText) | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
chat-iOS/Views/CreateChatRoom/CreateChatRoomViewModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// | ||
// CreateChatRoomViewModel.swift | ||
// chat-iOS | ||
// | ||
// Created by jun on 2020/07/18. | ||
// | ||
|
||
import Firebase | ||
|
||
protocol CreateChatRoomModelProtocol { | ||
var presenter: CreateChatRoomModelOutput! { get set } | ||
var selectedUsersArray: [User] { get set } | ||
var searchedUsersArray: [User] { get set } | ||
|
||
func isContaintsUser(user: User) -> Bool | ||
func searchUser(searchText: String) | ||
func removeSelectedUserFromSelectedUserArray(user: User) | ||
func appendUserToSelectedUserArray(user: User) | ||
func removeSelectedUsersArray(index: Int) -> [User] | ||
func createChatRoom() | ||
} | ||
|
||
protocol CreateChatRoomModelOutput: class { | ||
func successRemoveSelectedUser() | ||
func successAppendUser() | ||
|
||
func successCreateChatRoom() | ||
|
||
func successSearchUser() | ||
} | ||
|
||
final class CreateChatRoomModel: CreateChatRoomModelProtocol { | ||
weak var presenter: CreateChatRoomModelOutput! | ||
private var firestore: Firestore! | ||
var selectedUsersArray: [User] = Array() | ||
var searchedUsersArray: [User] = Array() | ||
|
||
init() { | ||
self.firestore = Firestore.firestore() | ||
let settings = FirestoreSettings() | ||
self.firestore.settings = settings | ||
} | ||
|
||
/// ユーザをFirestoreから検索する関数 | ||
/// - Parameter searchText: 検索するユーザ名 | ||
func searchUser(searchText: String) { | ||
self.firestore.collection("message/v1/users").whereField("displayName", isEqualTo: searchText).getDocuments { [weak self] (documentSnapshot, error) in | ||
if let error = error { | ||
print("Error: \(error.localizedDescription)") | ||
return | ||
} | ||
|
||
guard let documents = documentSnapshot?.documents else { | ||
print("The document doesn't exist.") | ||
return | ||
} | ||
|
||
let searchedUsers = documents.compactMap { queryDocumentSnapshot -> User? in | ||
return try? queryDocumentSnapshot.data(as: User.self) | ||
} | ||
|
||
self?.searchedUsersArray = searchedUsers | ||
self?.presenter.successSearchUser() | ||
} | ||
} | ||
|
||
/// ユーザが既に選択されているかを返す | ||
/// - Parameter user: 検索するユーザ | ||
/// - Returns: 検索結果 | ||
func isContaintsUser(user: User) -> Bool { | ||
if self.selectedUsersArray.filter({ $0.id == user.id ?? "" }).isEmpty { return false } | ||
return true | ||
} | ||
|
||
func removeSelectedUserFromSelectedUserArray(user: User) { | ||
self.selectedUsersArray = self.selectedUsersArray.filter({ $0.id != user.id }) | ||
|
||
self.presenter.successRemoveSelectedUser() | ||
} | ||
|
||
func appendUserToSelectedUserArray(user: User) { | ||
self.selectedUsersArray.append(user) | ||
self.presenter.successAppendUser() | ||
} | ||
|
||
/// `selectedUsersArray`からあるインデックスを削除する | ||
/// - Parameter index: 削除する配列番号 | ||
/// - Returns: 削除した後の`selectedUsersArray` | ||
func removeSelectedUsersArray(index: Int) -> [User] { | ||
self.selectedUsersArray.remove(at: index) | ||
return self.selectedUsersArray | ||
} | ||
|
||
//TODO:- Firesotreに保存する | ||
func createChatRoom() { | ||
self.presenter.successCreateChatRoom() | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tagを使わずにdelegateかクロージャの方が良いかなと思うのですがどうでしょうか?
参考 https://fluffy.es/handling-button-tap-inside-uitableviewcell-without-using-tag/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これは結局
SearchUserTableviewCell
内にcell番号自体を保存する必要がある(サイト内ではユーチューバの名前がクロージャーで送られてる)かつ,ボタンで使うのはcellで固有のString等の情報でなく単にcellの番号のみの取得なので,今回の処理では
tag
を使った実装にしたのですがどうでしょうか?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
タグを使わない方が良い(例えばsectionがいっこだけじゃない時にややこしくなる)と思っていて
その上で今回はtagを使ってindexPath.itemを渡しているので
それならクロージャを使って
cellのクラス内でbuttonがtapされた時に
deleteUserActionが実行されるようにして
こんな感じでindexPath.itemを渡した方が良いかなと思いました
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど。理解しました!了解です
クロージャで実装します!