diff --git a/app/src/main/java/com/example/tampopo_client/views/MainActivity.java b/app/src/main/java/com/example/tampopo_client/views/MainActivity.java index 720729e..5f91723 100644 --- a/app/src/main/java/com/example/tampopo_client/views/MainActivity.java +++ b/app/src/main/java/com/example/tampopo_client/views/MainActivity.java @@ -9,7 +9,6 @@ import android.util.Log; import android.util.TypedValue; import android.view.View; -import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.Button; @@ -19,7 +18,6 @@ import android.widget.LinearLayout; import androidx.activity.EdgeToEdge; -import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; @@ -29,14 +27,12 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; -import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import com.bumptech.glide.Glide; import com.example.tampopo_client.R; import com.example.tampopo_client.Tampopo; -import com.example.tampopo_client.models.Activity; import com.example.tampopo_client.viewmodels.ActivityViewModel; import com.example.tampopo_client.viewmodels.ActivityViewModelFactory; import com.example.tampopo_client.viewmodels.ChatViewModel; @@ -143,7 +139,9 @@ } }); - // FriendIconViewを作成して、画面に配置する + /* + * FriendIconViewを作成して、画面に配置する + */ ConstraintLayout parent = findViewById(R.id.main); for (int i = 0; i < 6; i++) { @@ -161,128 +159,182 @@ createFriendIconView(i, null, marginTopInPx, marginStartInPx, parent); } - // 変更があったときに、FriendIconViewを更新する (2, 3) + /* + * 変更があったときに、FriendIconViewを更新する (2, 3) + */ activityViewModel.getSortedFriendUserIdsLiveData().observe(this, new Observer>() { @Override public void onChanged(List friendUserIds) { Log.d("SortedFriendUserIds", "フレンドIDが更新されました。"); - // 1. recentUpdatedFriendsを更新する - for (int i = 0; i < 6; i++) { - if (friendUserIds.get(i) != null) { - recentUpdatedFriends.set(i, friendUserIds.get(i)); + // 元の配列に影響を与えないようにコピーする + List latestFriendUseIds = new ArrayList<>(); + for (String friendUserId : friendUserIds) { + latestFriendUseIds.add(String.valueOf(friendUserId)); + } + + // ユーザーの数を6人まで制限する + if (latestFriendUseIds.size() > 6) { + latestFriendUseIds.subList(6, latestFriendUseIds.size()).clear(); + } + + // 各FriendIconViewの表示を切り替える + int prevFriendUserCount = recentUpdatedFriends.size(); + int latestFriendUserCount = latestFriendUseIds.size(); + if (prevFriendUserCount != latestFriendUserCount) { + if (prevFriendUserCount > latestFriendUserCount) { + for (int i = latestFriendUserCount; i < prevFriendUserCount; i++) { + FriendIconView friendIconView = friendIconViewMap.get(i); + assert friendIconView != null; + + friendIconView.setVisibility(View.GONE); + } + } else { + for (int i = prevFriendUserCount; i < latestFriendUserCount; i++) { + FriendIconView friendIconView = friendIconViewMap.get(i); + assert friendIconView != null; + + friendIconView.setVisibility(View.VISIBLE); + } } } - for (int i = 0; i < 6; i++) { + // 0, 以前のユーザーのObserveを停止する + for (int i = 0; i < recentUpdatedFriends.size(); i++) { + String friendUserId = recentUpdatedFriends.get(i); + FriendIconView friendIconView = friendIconViewMap.get(i); + assert friendIconView != null; + + activityViewModel.getActivitiesLiveDataFromUserId(friendUserId).removeObserver(friendIconView.getActivitiesObserver()); + } + + // 1. recentUpdatedFriendsを更新する + recentUpdatedFriends.clear(); + recentUpdatedFriends.addAll(latestFriendUseIds); + + // 2. FriendIconViewを更新する + for (int i = 0; i < recentUpdatedFriends.size(); i++) { FriendIconView friendIconView = friendIconViewMap.get(i); assert friendIconView != null; String friendId = recentUpdatedFriends.get(i); - if(friendId == null) { + if (friendId == null) { friendIconView.setVisibility(View.INVISIBLE); - }else{ + } else { friendIconView.setVisibility(View.VISIBLE); new Thread(new Runnable() { @Override public void run() { - //friendIconView.set(userViewModel.getIcon(friendId)); - friendIconView.setIconUrl(userViewModel.getIcon(friendId)); - friendIconView.setIconUrl(userViewModel.getIcon(friendId)); + String nickname = userViewModel.getNickname(friendId); + String iconUrl = userViewModel.getFriendIcon(friendId); + + Looper looper = Looper.getMainLooper(); + Handler handler = new Handler(looper); + handler.post(new Runnable() { + @Override + public void run() { + // FriendIconView.setUserId()でFriendIconViewが使用するユーザーIDを更新する + friendIconView.setFriendUserId(friendId); + + // FriendIconView.setNickname()でFriendIconViewが使用するニックネームを更新する + friendIconView.setNickname(nickname); + + // FriendIconView.setIcon()でFriendIconViewが使用するアイコンURLを更新する + friendIconView.setIconUrl(iconUrl); + + // 各FriendIconViewにActivityをobserveさせる + activityViewModel.getActivitiesLiveDataFromUserId(friendId).observe(MainActivity.this, friendIconView.getActivitiesObserver()); + } + }); } }).start(); - - // TODO: 2. FriendIconView.setUserId()でFriendIconViewが使用するユーザーIDを更新する - // TODO: 3. FriendIconView.setIcon()でFriendIconViewが使用するアイコンURLを更新する - // TODO: 4. FriendIconView.setNickname()でFriendIconViewが使用するニックネームを更新する } - } } }); - MutableLiveData> friendsLiveData = activityViewModel.getFriendUserIdsLiveData(); +// MutableLiveData> friendsLiveData = activityViewModel.getFriendUserIdsLiveData(); - friendsLiveData.observe(this, new Observer>() { - @Override//2 - public void onChanged(List friends) { - // フレンドの追加と削除 - updateActivityView(friends); - } - }); +// friendsLiveData.observe(this, new Observer>() { +// @Override//2 +// public void onChanged(List friends) { +// // フレンドの追加と削除 +//// updateActivityView(friends); +// } +// }); - //アクティビティを投稿した人がアクティビティを更新しないか監視する - //なにかをクリックしたらここに飛んでくる - for (String friendId : userViews.keySet()) { - //final String updateFriendId = friendId; - MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(friendId); - //MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(updateFriendId); - - //FriendIconView friendView = userViews.get(friendId); - //if (friendView == null) continue; - - -//natty もともと -// activitiesLiveData.observeForever(new Observer>() { -// //アクティビティを更新したらonChangedが呼び出される -// @Override -// public void onChanged(List activities) { -// // 更新したフレンドの再登場,更新してないフレンドの退場 -// //更新した人を見つけてFriendIconViewを呼び出して、 -// List sortedFriendUserIds = activityViewModel.getSortedFriendUserIds();//アクティビティを更新した最新6人のリスト -//// FriendIconView userView = userViews.get(friendId); -//// if (userView != null && activities != null && !activities.isEmpty()) { -//// //latestは最新のアクティビティを保持する -//// Activity latest = activities.get(activities.size() - 1); -//// } -//// // 最新更新フレンドをリストに追加(最大6人保持) -// int size = sortedFriendUserIds.size(); -// List latestSix = sortedFriendUserIds.subList(Math.max(size - 6, 0), size); +// //アクティビティを投稿した人がアクティビティを更新しないか監視する +// //なにかをクリックしたらここに飛んでくる +// for (String friendId : userViews.keySet()) { +// //final String updateFriendId = friendId; +// MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(friendId); +// //MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(updateFriendId); // -// synchronized (recentUpdatedFriends) { -// if (latestSix.contains(friendId)) { -// recentUpdatedFriends.remove(friendId); -// recentUpdatedFriends.add(0, friendId); -// if (recentUpdatedFriends.size() > 6) { -// recentUpdatedFriends.remove(recentUpdatedFriends.size() - 1); -// } -// } -// } -////スレッド処理をいれて更新できるようにする +// //FriendIconView friendView = userViews.get(friendId); +// //if (friendView == null) continue; +// +// +////natty もともと +//// activitiesLiveData.observeForever(new Observer>() { +//// //アクティビティを更新したらonChangedが呼び出される +//// @Override +//// public void onChanged(List activities) { +//// // 更新したフレンドの再登場,更新してないフレンドの退場 +//// //更新した人を見つけてFriendIconViewを呼び出して、 +//// List sortedFriendUserIds = activityViewModel.getSortedFriendUserIds();//アクティビティを更新した最新6人のリスト +////// FriendIconView userView = userViews.get(friendId); +////// if (userView != null && activities != null && !activities.isEmpty()) { +////// //latestは最新のアクティビティを保持する +////// Activity latest = activities.get(activities.size() - 1); +////// } +////// // 最新更新フレンドをリストに追加(最大6人保持) +//// int size = sortedFriendUserIds.size(); +//// List latestSix = sortedFriendUserIds.subList(Math.max(size - 6, 0), size); +//// +//// synchronized (recentUpdatedFriends) { +//// if (latestSix.contains(friendId)) { +//// recentUpdatedFriends.remove(friendId); +//// recentUpdatedFriends.add(0, friendId); +//// if (recentUpdatedFriends.size() > 6) { +//// recentUpdatedFriends.remove(recentUpdatedFriends.size() - 1); +//// } +//// } +//// } +//////スレッド処理をいれて更新できるようにする +//// } +// //}); +// +// //natty かきかえご +// activitiesLiveData.observe(this, activities -> { +// if (activities == null || activities.isEmpty()) return; +// +// // 最新のアクティビティを取得 +// Activity latest = activities.get(activities.size() - 1); +// +// // コメントを更新 +// FriendIconView friendView = userViews.get(friendId); +// if (friendView != null) { +// friendView.setComment(latest.getText()); // } - //}); +// +// // 並び順を更新 +// synchronized (recentUpdatedFriends) { +// recentUpdatedFriends.remove(friendId); +// recentUpdatedFriends.add(0, friendId); +// if (recentUpdatedFriends.size() > 6) { +// recentUpdatedFriends.remove(recentUpdatedFriends.size() - 1); +// } +// } +// +// // 🔥 並び替えた最新リストでUIを更新 +// //TODO: 3 +// runOnUiThread(() -> updateActivityView(recentUpdatedFriends)); +// }); +// //////////////////// +// - //natty かきかえご - activitiesLiveData.observe(this, activities -> { - if (activities == null || activities.isEmpty()) return; - - // 最新のアクティビティを取得 - Activity latest = activities.get(activities.size() - 1); - - // コメントを更新 - FriendIconView friendView = userViews.get(friendId); - if (friendView != null) { - friendView.setComment(latest.getText()); - } - - // 並び順を更新 - synchronized (recentUpdatedFriends) { - recentUpdatedFriends.remove(friendId); - recentUpdatedFriends.add(0, friendId); - if (recentUpdatedFriends.size() > 6) { - recentUpdatedFriends.remove(recentUpdatedFriends.size() - 1); - } - } - - // 🔥 並び替えた最新リストでUIを更新 - //TODO: 3 - runOnUiThread(() -> updateActivityView(recentUpdatedFriends)); - }); - //////////////////// - - - } +// } // for (String friendId : userViews.keySet()) { @@ -442,19 +494,19 @@ dialog.show(); } - //natty 仮のフレンド情報 - private int getUserIconResource(String userId) { - switch (userId) { - case "user01": - return R.drawable.friend01_icon; - case "user02": - return R.drawable.friend04_icon; - case "user03": - return R.drawable.friend03_icon; - default: - return R.drawable.default_icon; - } - } +// //natty 仮のフレンド情報 +// private int getUserIconResource(String userId) { +// switch (userId) { +// case "user01": +// return R.drawable.friend01_icon; +// case "user02": +// return R.drawable.friend04_icon; +// case "user03": +// return R.drawable.friend03_icon; +// default: +// return R.drawable.default_icon; +// } +// } // private void setupActivityObservers(List sortedFriendUserIds) { // for (String friendId : sortedFriendUserIds) { @@ -495,128 +547,128 @@ // } // } - private void updateActivityView(@NonNull List friends) { - ///natty ユーザごとにコメントの更新をする - LinearLayout messageList = findViewById(R.id.messageList); - ConstraintLayout layout = findViewById(R.id.main); - - for (String friendId : friends) { - FriendIconView userView = userViews.get(friendId); - //userViews.put(friendId, null); - MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(friendId); - -// for (String friendId : sortedFriendUserIds) { -// FriendIconView userView = userViews.get(friendId); -// MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(friendId); - //nattyもしnullだったらって処理入れた気がする -// if (userView == null) { -// userView = new FriendIconView( -// MainActivity.this, -// friendId, -// userViewModel.getNickname(friendId), -// chatViewModel -// ); -// userViews.put(friendId, userView); -// } - // 新しいユーザなので、アイコン+コメントを作成 - //FriendIconView container = new FriendIconView(this); - - - if(userView == null) { - new Thread(new Runnable() { - @Override - public void run() { - FriendIconView container = new FriendIconView(MainActivity.this, friendId, userViewModel.getNickname(friendId), chatViewModel, userViewModel.getFriendIcon(friendId)); - - Handler handler = new Handler(Looper.getMainLooper()); - handler.post(new Runnable() { - @Override - public void run() { - container.setPadding(16, 16, 16, 16); - container.setId(View.generateViewId()); - -// // ユーザのアイコン(固定) -// ShapeableImageView iconView = new ShapeableImageView(MainActivity.this); -// iconView.setLayoutParams(new LinearLayout.LayoutParams(100, 100)); -// iconView.setScaleType(ImageView.ScaleType.CENTER_CROP); -// iconView.setStrokeColor(ContextCompat.getColorStateList(MainActivity.this, R.color.red)); -// iconView.setStrokeWidth(2f); -// iconView.setShapeAppearanceModel( -// iconView.getShapeAppearanceModel().toBuilder() -// .setAllCornerSizes(50) // 丸く -// .build() -// ); - ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams( - ConstraintLayout.LayoutParams.WRAP_CONTENT, - ConstraintLayout.LayoutParams.WRAP_CONTENT - ); - container.setLayoutParams(params); - layout.addView(container); +// private void updateActivityView(@NonNull List friends) { +// ///natty ユーザごとにコメントの更新をする +// LinearLayout messageList = findViewById(R.id.messageList); +// ConstraintLayout layout = findViewById(R.id.main); // -// // ユーザIDに応じてアイコンリソースを決定(仮にハードコード or マッピング) -// iconView.setImageResource(getUserIconResource(friendId)); // ←ここがポイント - - // Mapに登録、画面に追加 - userViews.put(friendId, container); -// userView = container; -// messageList.addView(container); - - ConstraintSet set = new ConstraintSet(); - set.clone(layout); - int marginTopInPx = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - marginTopInDp[i], - getResources().getDisplayMetrics() - ); - int marginStartInPx = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - marginStartInDp[i], - getResources().getDisplayMetrics() - ); - - set.connect(container.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, marginTopInPx); - set.connect(container.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, marginStartInPx); - - set.applyTo(layout); - - if (i < 6) { - i++; - } - - // TODO: CHANGE - activitiesLiveData.observe(MainActivity.this, activities -> { - if (activities == null || activities.isEmpty()) return; - - Activity latest = activities.get(activities.size() - 1); - - // UIスレッドで安全に更新 - FriendIconView friendView = userViews.get(friendId); - if (friendView != null) { - friendView.setComment(latest.getText()); - Log.d("ActivityUpdate", friendId + " のコメントを更新: " + latest.getText()); - } - }); - - List sortedFriendUserIds = activityViewModel.getSortedFriendUserIds(); - int size = sortedFriendUserIds.size(); - List latestSix = sortedFriendUserIds.subList(Math.max(size - 6, 0), size); - - synchronized (recentUpdatedFriends) { - if (latestSix.contains(friendId)) { - recentUpdatedFriends.remove(friendId); - recentUpdatedFriends.add(0, friendId); - if (recentUpdatedFriends.size() > 6) { - recentUpdatedFriends.remove(recentUpdatedFriends.size() - 1); - } - } - } - } - }); - } - }).start(); - } - } - } +// for (String friendId : friends) { +// FriendIconView userView = userViews.get(friendId); +// //userViews.put(friendId, null); +// MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(friendId); +// +//// for (String friendId : sortedFriendUserIds) { +//// FriendIconView userView = userViews.get(friendId); +//// MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(friendId); +// //nattyもしnullだったらって処理入れた気がする +//// if (userView == null) { +//// userView = new FriendIconView( +//// MainActivity.this, +//// friendId, +//// userViewModel.getNickname(friendId), +//// chatViewModel +//// ); +//// userViews.put(friendId, userView); +//// } +// // 新しいユーザなので、アイコン+コメントを作成 +// //FriendIconView container = new FriendIconView(this); +// +// +// if (userView == null) { +// new Thread(new Runnable() { +// @Override +// public void run() { +// FriendIconView container = new FriendIconView(MainActivity.this, friendId, userViewModel.getNickname(friendId), chatViewModel, userViewModel.getFriendIcon(friendId)); +// +// Handler handler = new Handler(Looper.getMainLooper()); +// handler.post(new Runnable() { +// @Override +// public void run() { +// container.setPadding(16, 16, 16, 16); +// container.setId(View.generateViewId()); +// +//// // ユーザのアイコン(固定) +//// ShapeableImageView iconView = new ShapeableImageView(MainActivity.this); +//// iconView.setLayoutParams(new LinearLayout.LayoutParams(100, 100)); +//// iconView.setScaleType(ImageView.ScaleType.CENTER_CROP); +//// iconView.setStrokeColor(ContextCompat.getColorStateList(MainActivity.this, R.color.red)); +//// iconView.setStrokeWidth(2f); +//// iconView.setShapeAppearanceModel( +//// iconView.getShapeAppearanceModel().toBuilder() +//// .setAllCornerSizes(50) // 丸く +//// .build() +//// ); +// ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams( +// ConstraintLayout.LayoutParams.WRAP_CONTENT, +// ConstraintLayout.LayoutParams.WRAP_CONTENT +// ); +// container.setLayoutParams(params); +// layout.addView(container); +//// +//// // ユーザIDに応じてアイコンリソースを決定(仮にハードコード or マッピング) +//// iconView.setImageResource(getUserIconResource(friendId)); // ←ここがポイント +// +// // Mapに登録、画面に追加 +// userViews.put(friendId, container); +//// userView = container; +//// messageList.addView(container); +// +// ConstraintSet set = new ConstraintSet(); +// set.clone(layout); +// int marginTopInPx = (int) TypedValue.applyDimension( +// TypedValue.COMPLEX_UNIT_DIP, +// marginTopInDp[i], +// getResources().getDisplayMetrics() +// ); +// int marginStartInPx = (int) TypedValue.applyDimension( +// TypedValue.COMPLEX_UNIT_DIP, +// marginStartInDp[i], +// getResources().getDisplayMetrics() +// ); +// +// set.connect(container.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, marginTopInPx); +// set.connect(container.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, marginStartInPx); +// +// set.applyTo(layout); +// +// if (i < 6) { +// i++; +// } +// +// // TODO: CHANGE +// activitiesLiveData.observe(MainActivity.this, activities -> { +// if (activities == null || activities.isEmpty()) return; +// +// Activity latest = activities.get(activities.size() - 1); +// +// // UIスレッドで安全に更新 +// FriendIconView friendView = userViews.get(friendId); +// if (friendView != null) { +// friendView.setComment(latest.getText()); +// Log.d("ActivityUpdate", friendId + " のコメントを更新: " + latest.getText()); +// } +// }); +// +//// List sortedFriendUserIds = activityViewModel.getSortedFriendUserIds(); +//// int size = sortedFriendUserIds.size(); +//// List latestSix = sortedFriendUserIds.subList(Math.max(size - 6, 0), size); +//// +//// synchronized (recentUpdatedFriends) { +//// if (latestSix.contains(friendId)) { +//// recentUpdatedFriends.remove(friendId); +//// recentUpdatedFriends.add(0, friendId); +//// if (recentUpdatedFriends.size() > 6) { +//// recentUpdatedFriends.remove(recentUpdatedFriends.size() - 1); +//// } +//// } +//// } +// } +// }); +// } +// }).start(); +// } +// } +// } private void createFriendIconView(int index, String userId, int topMarginInPx, int startMarginInPx, ConstraintLayout parent) { @@ -624,7 +676,7 @@ @Override public void run() { String nickname = userId != null ? userViewModel.getNickname(userId) : null; - String iconUrl = userId != null ? userViewModel.getIcon(userId) : null; + String iconUrl = userId != null ? userViewModel.getFriendIcon(userId) : null; // TODO: userId, iconUrl, nicknameがnullのときやばくない? FriendIconView friendIconView = new FriendIconView(MainActivity.this, userId, nickname, chatViewModel, iconUrl); friendIconViewMap.put(index, friendIconView); @@ -633,6 +685,7 @@ handler.post(new Runnable() { @Override public void run() { + friendIconView.setVisibility(View.GONE); friendIconView.setPadding(16, 16, 16, 16); friendIconView.setId(View.generateViewId());