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 62ed1f3..9476ab1 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 @@ -214,6 +214,81 @@ } /** + * 通話終了時の後片付け: 最新アクティビティが「通話中」であればそれを削除し、 + * 直前のアクティビティを最新としてLiveDataに反映する。 + * 相手ユーザーの更新はサーバ側の認可に依存するため、失敗してもアプリは落とさない。 + * + * @param userId 対象ユーザーID(自分またはフレンド) + * @param token 呼び出しユーザーの認証トークン + */ + public void endCallForUser(String userId, String token) { + try { + Call> fetchActivityCall = activitiesResource.getActivities(userId, "LATEST"); + fetchActivityCall.enqueue(new Callback>() { + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + if (!response.isSuccessful() || response.body() == null || response.body().isEmpty()) { + return; + } + + Activity latest = response.body().values().iterator().next(); + if (latest == null || latest.getText() == null) { + return; + } + + if (!"通話中".equals(latest.getText())) { + // 既に通話以外のステータスであれば何もしない + return; + } + + // 最新が通話中なら削除 + Call deleteCall = activitiesResource.deleteActivity(userId, latest.getActivityId(), token); + deleteCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + // 削除に成功/失敗に関わらず最新を取り直してLiveDataへ反映する + pullLatestActivity(userId, activitiesResource, new ActivityFetchCallback() { + @Override + public void onSuccess(Activity activity) { + if (userId.equals(myUserId)) { + myLatestActivityLiveData.postValue(activity); + } else { + // フレンド用のLiveDataに反映 + if (friendToActivitiesLiveData.get(userId) == null) { + friendToActivitiesLiveData.put(userId, new MutableLiveData<>(List.of())); + } + MutableLiveData> userActivitiesLiveData = friendToActivitiesLiveData.get(userId); + if (userActivitiesLiveData != null) { + userActivitiesLiveData.postValue(List.of(activity)); + } + } + } + + @Override + public void onFailure(Throwable throwable) { + Log.e(ActivityViewModel.class.getSimpleName(), "Failed to refresh latest activity after deletion.", throwable); + } + }); + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + Log.e(ActivityViewModel.class.getSimpleName(), "Failed to delete call activity.", t); + } + }); + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + Log.e(ActivityViewModel.class.getSimpleName(), "Failed to fetch latest activity for endCall.", t); + } + }); + } catch (Exception e) { + Log.e(ActivityViewModel.class.getSimpleName(), "Unexpected error in endCallForUser.", e); + } + } + + /** * 最新のユーザーのアクティビティを取得・更新する * * @param userId 取得対象のユーザーのID diff --git a/app/src/main/java/com/example/tampopo_client/viewmodels/ChatViewModel.java b/app/src/main/java/com/example/tampopo_client/viewmodels/ChatViewModel.java index 80b1fce..5aed3cb 100644 --- a/app/src/main/java/com/example/tampopo_client/viewmodels/ChatViewModel.java +++ b/app/src/main/java/com/example/tampopo_client/viewmodels/ChatViewModel.java @@ -236,7 +236,7 @@ // 4. チャットルーム削除 // =============================== public void destroyChatroom(String chatroomId, String userId, String token) { - Call call = chatroomResource.destroyChatroom(token, chatroomId, userId); + Call call = chatroomResource.destroyChatroom(chatroomId, userId, token); call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { 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 494c624..73b341c 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 @@ -19,11 +19,15 @@ import com.example.tampopo_client.R; import com.example.tampopo_client.Tampopo; import com.example.tampopo_client.viewmodels.ChatViewModel; +import com.example.tampopo_client.viewmodels.UserViewModel; import com.example.tampopo_client.viewmodels.ChatViewModelFactory; +import com.example.tampopo_client.viewmodels.ActivityViewModel; +import com.example.tampopo_client.viewmodels.ActivityViewModelFactory; public class ChatActivity extends AppCompatActivity { private ChatViewModel chatViewModel; + private ActivityViewModel activityViewModel; //メンバー変数 private EditText senderMessage; @@ -48,13 +52,31 @@ chatViewModel = new ViewModelProvider(this, factory1).get(ChatViewModel.class); chatViewModel.setChatRoomId(tampopo.getChatroomId()); + // アクティビティ更新用のViewModel(通話中の表示に利用) + ActivityViewModelFactory activityFactory = new ActivityViewModelFactory(tampopo.getUserId(), tampopo.getToken()); + activityViewModel = new ViewModelProvider(this, activityFactory).get(ActivityViewModel.class); + senderMessage = findViewById(R.id.sender_message); receiverMessage = findViewById(R.id.receiver_message); sendButton = findViewById(R.id.send_Button); backButton = findViewById(R.id.back_Button); roomId = findViewById(R.id.chat_room_id); TextView friendIdTextView = findViewById(R.id.friend_id); - friendIdTextView.setText(tampopo.getChatFriendId()); + // まずはIDを仮表示 + String friendId = tampopo.getChatFriendId(); + friendIdTextView.setText(friendId); + // 相手のニックネームを取得して表示(非同期) + new Thread(() -> { + try { + UserViewModel userViewModel = new UserViewModel(); + String nickname = userViewModel.getNickname(friendId); + if (nickname != null && !nickname.isEmpty()) { + runOnUiThread(() -> friendIdTextView.setText(nickname)); + } + } catch (Exception e) { + Log.e("ChatDebug", "ニックネーム取得に失敗", e); + } + }).start(); receiverMessage.setKeyListener(null);//受信メッセージ編集不可 // buttonSend.setOnClickListener(new OnClickListener() { @@ -134,6 +156,25 @@ //戻るボタン backButton.setOnClickListener(new OnClickListener() { //backButtonがクリックされたときの処理 public void onClick(View view) { //ボタンがクリックされたときに実行される処理本体 + // 通話終了時のアクティビティを元に戻す(最新の「通話中」を削除して直前の表示に) + try { + if (activityViewModel != null && tampopo != null) { + String me = tampopo.getUserId(); + String friend = tampopo.getChatFriendId(); + String token = tampopo.getToken(); + if (me != null && token != null) { + activityViewModel.endCallForUser(me, token); + } + if (friend != null && token != null) { + // 相手側のアクティビティも可能なら最新の「通話中」を削除 + activityViewModel.endCallForUser(friend, token); + } + } + } catch (Exception e) { + Log.e("ChatDebug", "通話終了ステータス更新に失敗", e); + } + + // 自分が退出(相手も退出済みならサーバ側でルーム削除される想定) chatViewModel.destroyChatroom(tampopo.getChatroomId(),tampopo.getUserId(),tampopo.getToken()); Intent intent = new Intent(ChatActivity.this, MainActivity.class); //ChatActivity から MainActivity に画面遷移 startActivity(intent); @@ -157,5 +198,27 @@ chatViewModel.startUpdating(1L); } + // チャット開始時に自分と相手のアクティビティへ「通話中」を設定する + // 備考: サーバの認可仕様によっては相手ユーザーのアクティビティ更新が拒否される場合があります。 + // その場合でも少なくとも自分側は「通話中」に更新されます。 + try { + if (activityViewModel != null && tampopo != null) { + String me = tampopo.getUserId(); + String friend = tampopo.getChatFriendId(); + String token = tampopo.getToken(); + + if (me != null && token != null) { + activityViewModel.createActivity(me, token, "通話中"); + } + + if (friend != null && token != null) { + // 相手側のアクティビティも可能なら更新(権限があれば反映される) + activityViewModel.createActivity(friend, token, "通話中"); + } + } + } catch (Exception e) { + Log.e("ChatDebug", "通話中ステータス更新に失敗", e); + } + } }