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 85a9391..a765945 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 @@ -87,6 +87,7 @@ }, 10_000); // 10秒後に通知 } foundChatroom(userId,token); + System.out.println(chatroomIdLiveData.getValue()); if (chatroomId != null) loadLatestMessage(chatroomId, userId, token); //chatroomIdがnullの時は呼び出さないようにしました }; @@ -158,15 +159,17 @@ if (response.isSuccessful() && response.body() != null) { Chatroom chatroom = response.body(); - chatroomIdLiveData.setValue(chatroom.getChatRoomId()); - chatFriendToMeLiveData.setValue( - userId.equals(chatroom.getUser0Id()) + if(chatroomIdLiveData.getValue() == null || !chatroomIdLiveData.getValue().equals(chatroom.getChatRoomId())){ + + chatroomIdLiveData.postValue(chatroom.getChatRoomId()); + chatFriendToMeLiveData.postValue( + userId.equals(chatroom.getUser0Id()) ? chatroom.getUser1Id() : chatroom.getUser0Id() ); - } else { - chatroomIdLiveData.setValue(null); - chatroomClosed.setValue(true); + }} else { +// chatroomIdLiveData.setValue(null); +// chatroomClosed.setValue(true); } } diff --git a/app/src/main/java/com/example/tampopo_client/viewmodels/UserViewModel.java b/app/src/main/java/com/example/tampopo_client/viewmodels/UserViewModel.java index 84ddf44..779f6f8 100644 --- a/app/src/main/java/com/example/tampopo_client/viewmodels/UserViewModel.java +++ b/app/src/main/java/com/example/tampopo_client/viewmodels/UserViewModel.java @@ -45,15 +45,15 @@ private final Retrofit retrofit; private static UserResource userResource; - private static final MutableLiveData user = new MutableLiveData<>(); - private final MutableLiveData token = new MutableLiveData<>(); - private final MutableLiveData icon = new MutableLiveData<>(); - private final MutableLiveDataloading = new MutableLiveData<>(false); - private static final MutableLiveData error = new MutableLiveData<>(); + private static final MutableLiveData user = new MutableLiveData<>(); + private final MutableLiveData token = new MutableLiveData<>(); + private final MutableLiveData icon = new MutableLiveData<>(); + private final MutableLiveData loading = new MutableLiveData<>(false); + private static final MutableLiveData error = new MutableLiveData<>(); //コンストラクタ - public UserViewModel(){ + public UserViewModel() { this.retrofit = new Retrofit.Builder() .baseUrl("http://nitta-lab-www.is.konan-u.ac.jp/tampopo/") .addConverterFactory(ScalarsConverterFactory.create()) @@ -62,11 +62,25 @@ this.userResource = retrofit.create(UserResource.class); } - public LiveData getUser() { return user; } - public LiveData getToken() { return token; } - public LiveData getIcon() { return icon; } - public LiveDataisLoading() { return loading;} - public static LiveData getError() { return error; } + public LiveData getUser() { + return user; + } + + public LiveData getToken() { + return token; + } + + public LiveData getIcon() { + return icon; + } + + public LiveData isLoading() { + return loading; + } + + public static LiveData getError() { + return error; + } //新規登録 enqueueで非同期処理、Callbackで成功失敗の処理、LiveDataに反映 //サーバーから返ってきた型と合わせないとFailureに流れる @@ -74,7 +88,8 @@ public void createUser(String id, String password) { loading.setValue(true); userResource.createUser(id, password).enqueue(new Callback() { - @Override public void onResponse(Call c, Response res) { + @Override + public void onResponse(Call c, Response res) { loading.setValue(false); if (res.isSuccessful()) { User u = res.body(); @@ -83,7 +98,9 @@ error.setValue("登録失敗: " + res.code()); } } - @Override public void onFailure(Call c, Throwable t) { + + @Override + public void onFailure(Call c, Throwable t) { loading.setValue(false); error.setValue("エラー: " + t.getMessage()); } @@ -94,7 +111,8 @@ public void login(String id, String password) { loading.setValue(true); userResource.login(id, password).enqueue(new Callback() { - @Override public void onResponse(Call c, Response res) { + @Override + public void onResponse(Call c, Response res) { loading.setValue(false); if (res.isSuccessful()) { userResource.getUser(id); @@ -104,12 +122,15 @@ error.setValue("ログイン失敗: " + res.code()); } } - @Override public void onFailure(Call c, Throwable t) { + + @Override + public void onFailure(Call c, Throwable t) { loading.setValue(false); error.setValue("エラー: " + t.getMessage()); } }); } + //ニックネーム public String getNickname(String id) { Call call = userResource.getName(id); @@ -129,8 +150,8 @@ // } - //アイコン - public String getIcon(String id) { + //フレンドのアイコンをとってくる + public String getFriendIcon(String id) { Call call = userResource.getIcon(id); try { Response response = call.execute(); @@ -138,7 +159,6 @@ if (response.isSuccessful()) { System.out.println(response.code()); String iconUrl = response.body(); - icon.postValue(iconUrl); return iconUrl; } else { System.out.println(response.code()); @@ -163,7 +183,14 @@ // }); } - //アイコン(非同期) + //アイコン(非同期)idはログインユーザーのuser-id + + /** + * 自身のアイコンを取ってくる + * + * @param id ログインユーザーのuser-id + * @deprecated + */ public void getIconAsync(String id) { Call call = userResource.getIcon(id); call.enqueue(new Callback() { @@ -182,6 +209,31 @@ }); } + /** + * 自身のアイコンを取ってくる + */ + public void getMyIcon(String id) { +// User currentUser = user.getValue(); +// if (currentUser == null) { +// return; +// } + Call call = userResource.getIcon(id); + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + String iconUrl = response.body(); + icon.postValue(iconUrl); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + Log.e("UserViewModel", "Error"); + } + }); + } + public void updateIcon(String id, String newIcon, String token) { Call call = userResource.updateIcon(id, newIcon, token); @@ -196,7 +248,9 @@ System.out.println(response.code()); } } - @Override public void onFailure(Call call, Throwable t) { + + @Override + public void onFailure(Call call, Throwable t) { System.out.println("エラー: " + t.getMessage()); } }); @@ -229,11 +283,12 @@ } }); } + //パスワードの変更(市井) - public void updatePassword(String userId, String newPassword ,String tokenValue) { + public void updatePassword(String userId, String newPassword, String tokenValue) { loading.setValue(true); - userResource.updatePassword(userId, newPassword ,tokenValue).enqueue(new Callback() { + userResource.updatePassword(userId, newPassword, tokenValue).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { loading.setValue(false); @@ -288,8 +343,6 @@ } - - //viewModelのところでを呼び出すがフレンド系は西村さんの方で管理する } 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 890aaf2..2311cd0 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 @@ -8,6 +8,8 @@ import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; +import android.widget.TextView; + import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; @@ -27,6 +29,7 @@ private EditText receiverMessage; private Button sendButton; private ImageButton backButton; + private EditText roomId; Tampopo tampopo; @@ -46,7 +49,7 @@ 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); receiverMessage.setKeyListener(null);//受信メッセージ編集不可 // buttonSend.setOnClickListener(new OnClickListener() { @@ -72,6 +75,7 @@ //String myId = tampopo.getUserId(); //String friendId = tampopo.getChatFriendId(); String chatroomId = tampopo.getChatroomId(); + roomId.setText(chatroomId); //String chatroomId = "0"; //String token = tampopo.getToken(); diff --git a/app/src/main/java/com/example/tampopo_client/views/FriendIconView.java b/app/src/main/java/com/example/tampopo_client/views/FriendIconView.java index e0c8ccf..f49fa75 100644 --- a/app/src/main/java/com/example/tampopo_client/views/FriendIconView.java +++ b/app/src/main/java/com/example/tampopo_client/views/FriendIconView.java @@ -32,6 +32,11 @@ private TextView mFriendNickname; private ImageView mFriendChatNotification; private boolean chatNotification = false; + + public void setFriendUserId(String friendUserId) { + this.friendUserId = friendUserId; + } + private String friendUserId; private String friendUserNickname; private ChatViewModel chatViewModel; 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 70132b7..720729e 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 @@ -33,6 +33,7 @@ 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; @@ -41,6 +42,7 @@ import com.example.tampopo_client.viewmodels.ChatViewModel; import com.example.tampopo_client.viewmodels.ChatViewModelFactory; import com.example.tampopo_client.viewmodels.UserViewModel; +import com.google.android.material.imageview.ShapeableImageView; import java.util.ArrayList; import java.util.HashMap; @@ -113,6 +115,18 @@ //tampopoを宣言する tampopo = (Tampopo) getApplication(); + String uid = tampopo.getUserId(); + String token = tampopo.getToken(); + ShapeableImageView myIcon = findViewById(R.id.myicon); + + userViewModel.getMyIcon(uid); + userViewModel.getIcon().observe(this, new Observer() { + @Override + public void onChanged(String iconUrl) { + Glide.with(MainActivity.this).load(iconUrl).into(myIcon); + } + }); + //activityViewModelを宣言する ActivityViewModelFactory factory = new ActivityViewModelFactory(tampopo.getUserId(), tampopo.getToken()); // Factoryを使って、引数をコンストラクタにわたしつつViewModelを作成 activityViewModel = new ViewModelProvider(this, factory).get(ActivityViewModel.class); @@ -486,7 +500,6 @@ LinearLayout messageList = findViewById(R.id.messageList); ConstraintLayout layout = findViewById(R.id.main); - i = 0; for (String friendId : friends) { FriendIconView userView = userViews.get(friendId); //userViews.put(friendId, null); @@ -509,17 +522,18 @@ //FriendIconView container = new FriendIconView(this); - new Thread(new Runnable() { - @Override - public void run() { - FriendIconView container = new FriendIconView(MainActivity.this, friendId, userViewModel.getNickname(friendId), chatViewModel, userViewModel.getIcon(friendId)); + 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()); + 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); @@ -532,78 +546,79 @@ // .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に登録、画面に追加 - //TODO: - 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.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()); + if (i < 6) { + i++; } - }); -// List sortedFriendUserIds = activityViewModel.getSortedFriendUserIdsLiveData(); -// 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(); + // 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) { new Thread(new Runnable() { @Override diff --git a/app/src/main/java/com/example/tampopo_client/views/UserInfoActivity.java b/app/src/main/java/com/example/tampopo_client/views/UserInfoActivity.java index 6d50809..cdcc4e3 100644 --- a/app/src/main/java/com/example/tampopo_client/views/UserInfoActivity.java +++ b/app/src/main/java/com/example/tampopo_client/views/UserInfoActivity.java @@ -114,9 +114,9 @@ app.setIcon(changeIconUrl); } - if (usernicknameInput == null && changeIconUrl == null) { + if (android.text.TextUtils.isEmpty(usernickname) && changeIconUrl == null) { Toast.makeText(UserInfoActivity.this, "ニックネームとアイコンを設定してください", Toast.LENGTH_SHORT).show(); - }else if(usernicknameInput == null){ + }else if(android.text.TextUtils.isEmpty(usernickname)){ Toast.makeText(UserInfoActivity.this, "ニックネームを入力してください", Toast.LENGTH_SHORT).show(); } else if (changeIconUrl == null) { Toast.makeText(UserInfoActivity.this, "アイコンを設定してください", Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml index 0cf1cd2..cfdbc6a 100644 --- a/app/src/main/res/layout/activity_chat.xml +++ b/app/src/main/res/layout/activity_chat.xml @@ -66,5 +66,17 @@ android:layout_marginStart="5dp" android:layout_marginTop="5dp" /> + + \ No newline at end of file