diff --git a/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java b/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java index 3d15caf..455723a 100644 --- a/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java +++ b/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java @@ -47,6 +47,7 @@ private final List sortedFriendUserIds = new ArrayList<>(); + /** * ActivityのViewModelを作成する。 * @@ -150,7 +151,7 @@ if (userActivities == null || userActivities.isEmpty()) { userActivitiesLiveData.postValue(List.of(latestActivity)); } else { - if (userActivities.equals(List.of(latestActivity))) { + if (userActivities.get(0).getActivityId().equals(latestActivity.getActivityId())) { return; } diff --git a/app/src/main/java/com/example/tampopo_client/views/ChatActivity.java b/app/src/main/java/com/example/tampopo_client/views/ChatActivity.java index 48ac410..0be32fb 100644 --- a/app/src/main/java/com/example/tampopo_client/views/ChatActivity.java +++ b/app/src/main/java/com/example/tampopo_client/views/ChatActivity.java @@ -63,29 +63,32 @@ // } // }); - Intent intent = getIntent(); - String friendId = intent.getStringExtra("friendId"); - String chatroomId = intent.getStringExtra("chatroomId"); +// Intent intent = getIntent(); +// String friendId = intent.getStringExtra("friendId"); +// String chatroomId = intent.getStringExtra("chatroomId"); - Log.d("ChatDebug", "チャット相手ID: " + friendId); - Log.d("ChatDebug", "チャットルームID: " + chatroomId); + String myId = tampopo.getUserId(); + String friendId = tampopo.getChatFriendId(); + String chatroomId = tampopo.getChatroomId(); + //String chatroomId = "0"; String token = tampopo.getToken(); - chatroomViewModel.enterChatroom(myId, friendId, token); - if (friendId == null || friendId.isEmpty()) { - Log.e("ChatDebug","Error: friendIdがnullです"); - } + // chatroomViewModel.enterChatroom(myId, friendId, token); - chatroomViewModel.getChatroomIdLiveData().observe(this, id -> { - if (id != null) { - tampopo.setChatroomId(id); - System.out.println("チャットルーム作成完了! ID: " + id); - } else { - System.out.println("チャットルーム作成に失敗しました"); - } - }); + //Log.d("ChatDebug", "チャット相手ID: " + friendId); + Log.d("ChatDebug", "チャットルームID: " + chatroomId); + + +// chatroomViewModel.getChatroomIdLiveData().observe(this, id -> { +// if (id != null) { +// tampopo.setChatroomId(id); +// System.out.println("チャットルーム作成完了! ID: " + id); +// } else { +// System.out.println("チャットルーム作成に失敗しました"); +// } +// }); //メッセージ送信 @@ -93,11 +96,13 @@ @Override public void onClick(View view) { //ボタンがクリックされたときに実行される処理本体 String senderText = senderMessage.getText().toString(); //senderMessageにユーザーが入力した文字を取り出して、String型の 変数receiverText に入れる + Log.d("ChatDebug", senderText); if (!senderText.isEmpty()) { //senderTextが空でなければ String senderId = tampopo.getUserId(); String token = tampopo.getToken(); String chatroomId = tampopo.getChatroomId(); - chatroomViewModel.sendMessage(chatroomId, senderId,senderText, token); + //String chatroomId = "0"; + chatroomViewModel.sendMessage(chatroomId, senderId, senderText, token); senderMessage.setText(senderText);//自分のメッセージを送信欄に表示 } } @@ -136,4 +141,3 @@ } } -// \ No newline at end of file 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 a477013..9911876 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 @@ -1,9 +1,5 @@ package com.example.tampopo_client.views; -import android.app.Dialog; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; @@ -11,6 +7,7 @@ import android.os.Handler; import android.os.Looper; import android.util.Log; +import android.util.TypedValue; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; @@ -18,17 +15,15 @@ import android.widget.EditText; import android.widget.GridView; import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; import androidx.activity.EdgeToEdge; +import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.ConstraintSet; import androidx.core.app.ActivityCompat; -import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; @@ -41,27 +36,18 @@ 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.ChatViewModelFactory; -import com.example.tampopo_client.viewmodels.UserViewModel; -import com.google.android.material.imageview.ShapeableImageView; import com.example.tampopo_client.viewmodels.ActivityViewModelFactory; import com.example.tampopo_client.viewmodels.ChatViewModel; import com.example.tampopo_client.viewmodels.ChatViewModelFactory; -import com.example.tampopo_client.viewmodels.NotificationListener; import com.example.tampopo_client.viewmodels.UserViewModel; -import com.google.android.material.imageview.ShapeableImageView; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import android.util.TypedValue; - -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.constraintlayout.widget.ConstraintSet; - -public class MainActivity extends AppCompatActivity implements NotificationListener { +public class MainActivity extends AppCompatActivity { + //public class MainActivity extends AppCompatActivity implements NotificationListener { private EditText editMessage; private ImageButton sendButton; @@ -98,7 +84,7 @@ //疑似的な通知のためにchatViewModelを定義する chatViewModel = new ViewModelProvider(this).get(ChatViewModel.class); - chatViewModel.addNotificationListener(this); + //chatViewModel.addNotificationListener(this); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { @@ -141,47 +127,50 @@ public void onChanged(List friends) { // フレンドの追加と削除 updateActivityView(friends); - - for (String friendId : userViews.keySet()) { - final String updateFriendId = friendId; - MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(updateFriendId); - //MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(updateFriendId); - - FriendIconView friendView = userViews.get(friendId); - if (friendView == null) continue; - - activitiesLiveData.observeForever(new Observer>() { - @Override - public void onChanged(List activities) { - // 更新したフレンドの再登場,更新してないフレンドの退場 - //更新した人を見つけてFriendIconViewを呼び出して、 - FriendIconView userView = userViews.get(updateFriendId); - if (userView != null && activities != null && !activities.isEmpty()) { - Activity latest = activities.get(activities.size() - 1); - String updateFriendId = latest.getUserId(); - } - //フレンドの位置決め - // 最新更新フレンドをリストに追加(最大6人保持) - List list = activityViewModel.getSortedFriendUserIds(); - int size = list.size(); - List latestSix = list.subList(Math.max(size - 6, 0), size); - - synchronized (recentUpdatedFriends) { - if (latestSix.contains(updateFriendId)) { - recentUpdatedFriends.remove(updateFriendId); - recentUpdatedFriends.add(0, updateFriendId); - if (recentUpdatedFriends.size() > 6) { - recentUpdatedFriends.remove(recentUpdatedFriends.size() - 1); - } - } - } - - } - }); - } } }); + //アクティビティを投稿した人がアクティビティを更新しないか監視する + //なにかをクリックしたらここに飛んでくる + 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; + + 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); + } + } + } +//スレッド処理をいれて更新できるようにする + } + }); + } + + // for (String friendId : userViews.keySet()) { // final String updateFriendId = friendId; // MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(updateFriendId); @@ -222,18 +211,28 @@ //メイン画面から設定画面への遷移 ImageButton settingButton = (ImageButton) findViewById(R.id.setting); - settingButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(MainActivity.this, SettingActivity.class); - startActivity(intent); - } - }); + settingButton. - messageList = findViewById(R.id.messageList); + setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + Intent intent = new Intent(MainActivity.this, SettingActivity.class); + startActivity(intent); + } + }); - // ボタンを押すとダイアログ表示(トリガー用) - openDialogButton = findViewById(R.id.openDialogButton); - openDialogButton.setOnClickListener(v -> showInputDialog()); + messageList = + + findViewById(R.id.messageList); + +// ボタンを押すとダイアログ表示(トリガー用) + openDialogButton = + + findViewById(R.id.openDialogButton); + openDialogButton. + + setOnClickListener(v -> + + showInputDialog()); } @@ -273,6 +272,7 @@ } } + private void showInputDialog() { // カスタムビュー読み込み View dialogView = getLayoutInflater().inflate(R.layout.main_dialog, null); @@ -342,7 +342,46 @@ } } - private void updateActivityView(List friends) { + private void setupActivityObservers(List sortedFriendUserIds) { + for (String friendId : sortedFriendUserIds) { + FriendIconView userView = userViews.get(friendId); + if (userView == null) { + Log.w("MainActivity", "userViews に存在しません: " + friendId); + continue; + } + + MutableLiveData> activitiesLiveData = + activityViewModel.getActivitiesLiveDataFromUserId(friendId); + + activitiesLiveData.observeForever(new Observer>() { + @Override + public void onChanged(List activities) { + if (activities == null || activities.isEmpty()) return; + + Activity latest = activities.get(activities.size() - 1); + Log.d("ActivityUpdate", friendId + " 最新: " + latest.getText()); + + // FriendIconView の更新 + //userView.setComment(latest.getText()); + + // 最近更新したフレンドリストを更新(最大6人) + synchronized (sortedFriendUserIds) { + sortedFriendUserIds.remove(friendId); + sortedFriendUserIds.add(0, friendId); + + if (sortedFriendUserIds.size() > 6) { + sortedFriendUserIds.remove(sortedFriendUserIds.size() - 1); + } + } + + // 並び順をログ出力(デバッグ用) + Log.d("RecentFriends", "最新更新順: " + sortedFriendUserIds); + } + }); + } + } + + private void updateActivityView(@NonNull List friends) { ///natty ユーザごとにコメントの更新をする LinearLayout messageList = findViewById(R.id.messageList); ConstraintLayout layout = findViewById(R.id.main); @@ -350,25 +389,37 @@ i = 0; for (String friendId : friends) { FriendIconView userView = userViews.get(friendId); + //userViews.put(friendId, null); MutableLiveData> activitiesLiveData = activityViewModel.getActivitiesLiveDataFromUserId(friendId); - - if (userView == null) { - // 新しいユーザなので、アイコン+コメントを作成 - //FriendIconView container = new FriendIconView(this); +// 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); - new Thread(new Runnable() { - @Override - public void run() { - FriendIconView container = new FriendIconView(MainActivity.this, friendId, userViewModel.getNickname(friendId), chatViewModel); + new Thread(new Runnable() { + @Override + public void run() { + FriendIconView container = new FriendIconView(MainActivity.this, friendId, userViewModel.getNickname(friendId), chatViewModel); - Handler handler = new Handler(Looper.getMainLooper()); - handler.post(new Runnable() { - @Override - public void run() { - container.setPadding(16, 16, 16, 16); - container.setId(View.generateViewId()); + 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); @@ -381,98 +432,124 @@ // .setAllCornerSizes(50) // 丸く // .build() // ); - ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams( - ConstraintLayout.LayoutParams.WRAP_CONTENT, - ConstraintLayout.LayoutParams.WRAP_CONTENT - ); - container.setLayoutParams(params); - layout.addView(container); + 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); + // 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() - ); + 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.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); + set.applyTo(layout); - if (i < 6) { - i++; - } - - // TODO: CHANGE - activitiesLiveData.observeForever(container.getActivitiesObserver()); + if (i < 6) { + i++; } - }); - } - }).start(); - } + + // 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 showChatNotification(String friendName) { - NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); +//プッシュ通知 +//private void showChatNotification(String friendName) { +//NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); - String channelId = "chat_channel"; +//String channelId = "chat_channel"; - NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId) - .setSmallIcon(R.drawable.default_icon) // 通知アイコン - .setContentTitle("新しいチャット") - .setContentText(friendName + " さんから通話があります") - .setPriority(NotificationCompat.PRIORITY_HIGH) - .setAutoCancel(true); // タップしたら消える - NotificationChannel channel = new NotificationChannel( - channelId, - "Chat Notifications", - NotificationManager.IMPORTANCE_HIGH - ); - notificationManager.createNotificationChannel(channel); +// NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId) +// .setSmallIcon(R.drawable.default_icon) // 通知アイコン +// .setContentTitle("新しいチャット") +// .setContentText(friendName + " さんから通話があります") +// .setPriority(NotificationCompat.PRIORITY_HIGH) +// .setAutoCancel(true); // タップしたら消える +// NotificationChannel channel = new NotificationChannel( +// channelId, +// "Chat Notifications", +// NotificationManager.IMPORTANCE_HIGH +// ); +//notificationManager.createNotificationChannel(channel); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - if (ContextCompat.checkSelfPermission( - this, - android.Manifest.permission.POST_NOTIFICATIONS - ) == PackageManager.PERMISSION_GRANTED) { - Log.d("NotificationTest", "notify() 呼ばれた!!"); - notificationManager.notify(0, builder.build()); - } else { - // 許可されていない → リクエストする - ActivityCompat.requestPermissions( - this, - new String[]{android.Manifest.permission.POST_NOTIFICATIONS}, - 1001 - ); - } - } else { - Log.d("NotificationTest", "notify() 呼ばれた!!"); - notificationManager.notify(0, builder.build()); - } - } +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { +// if (ContextCompat.checkSelfPermission( +// this, +// android.Manifest.permission.POST_NOTIFICATIONS +// ) == PackageManager.PERMISSION_GRANTED) { +// Log.d("NotificationTest", "notify() 呼ばれた!!"); +// notificationManager.notify(0, builder.build()); +// } else { +// // 許可されていない → リクエストする +// ActivityCompat.requestPermissions( +// this, +// new String[]{android.Manifest.permission.POST_NOTIFICATIONS}, +// 1001 +// ); +// } +// } else { +// Log.d("NotificationTest", "notify() 呼ばれた!!"); +// notificationManager.notify(0, builder.build()); +// } +//} - //通知を受信したときのダイアログ これが動いてます - //friendName+から通話があります。ってでるから通知が来たときのフレンドを変数に置く必要がある - @Override - public void onNotificationReceived() { - // 通知を受信したときにダイアログを表示 - runOnUiThread(() -> showChatNotification("user02")); - } -} \ No newline at end of file +//通知を受信したときのダイアログ これが動いてます +//friendName+から通話があります。ってでるから通知が来たときのフレンドを変数に置く必要がある +// @Override +// public void onNotificationReceived() { +// // 通知を受信したときにダイアログを表示 +// runOnUiThread(() -> showChatNotification("user02")); +// } + +