zhibo/android-app/app/src/main/java/com/example/livestreaming/ProfileActivity.java

942 lines
41 KiB
Java
Raw Normal View History

2025-12-17 15:38:00 +08:00
package com.example.livestreaming;
2025-12-23 12:39:14 +08:00
import android.Manifest;
2025-12-17 15:38:00 +08:00
import android.content.Context;
import android.content.Intent;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.graphics.drawable.Drawable;
2025-12-17 15:38:00 +08:00
import android.os.Bundle;
2025-12-19 15:11:49 +08:00
import android.net.Uri;
2025-12-18 14:20:41 +08:00
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
2025-12-18 14:20:41 +08:00
import android.widget.EditText;
import android.widget.Toast;
2025-12-17 15:38:00 +08:00
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
2025-12-17 15:38:00 +08:00
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
2025-12-18 14:20:41 +08:00
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.GridLayoutManager;
2025-12-17 15:38:00 +08:00
2025-12-18 14:20:41 +08:00
import com.bumptech.glide.Glide;
2025-12-23 12:39:14 +08:00
import com.example.livestreaming.BuildConfig;
2025-12-17 15:38:00 +08:00
import com.example.livestreaming.databinding.ActivityProfileBinding;
2025-12-23 12:39:14 +08:00
import com.example.livestreaming.ShareUtils;
import com.example.livestreaming.net.ApiClient;
import com.example.livestreaming.net.ApiResponse;
import com.example.livestreaming.net.UserInfoResponse;
2025-12-17 15:38:00 +08:00
import com.google.android.material.bottomnavigation.BottomNavigationView;
2025-12-23 12:39:14 +08:00
import com.google.android.material.bottomsheet.BottomSheetDialog;
2025-12-17 15:38:00 +08:00
import java.util.List;
2025-12-23 12:39:14 +08:00
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
2025-12-17 15:38:00 +08:00
public class ProfileActivity extends AppCompatActivity {
private static final String TAG = "ProfileActivity";
2025-12-17 15:38:00 +08:00
private ActivityProfileBinding binding;
2025-12-18 14:20:41 +08:00
private static final String PREFS_NAME = "profile_prefs";
private static final String KEY_NAME = "profile_name";
private static final String KEY_BIO = "profile_bio";
private static final String KEY_LEVEL = "profile_level";
private static final String KEY_FANS_BADGE = "profile_fans_badge";
private static final String KEY_BADGE = "profile_badge";
private static final String KEY_AVATAR_RES = "profile_avatar_res";
private static final String KEY_AVATAR_URI = "profile_avatar_uri";
private static final String KEY_BIRTHDAY = "profile_birthday";
private static final String KEY_GENDER = "profile_gender";
private static final String KEY_LOCATION = "profile_location";
2025-12-19 10:50:13 +08:00
private static final String BIO_HINT_TEXT = "填写个人签名更容易获得关注,点击此处添加";
private ActivityResultLauncher<Intent> editProfileLauncher;
private UserWorksAdapter worksAdapter;
2025-12-19 10:50:13 +08:00
2025-12-17 15:38:00 +08:00
public static void start(Context context) {
Intent intent = new Intent(context, ProfileActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityProfileBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 注册编辑资料页面的结果监听
editProfileLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
// 当从EditProfileActivity返回时立即刷新所有数据
loadProfileFromPrefs();
loadAndDisplayTags();
loadProfileInfo();
}
);
2025-12-18 14:20:41 +08:00
loadProfileFromPrefs();
loadUserInfoFromServer(); // 从服务器加载用户信息
loadAndDisplayTags();
loadProfileInfo();
loadFollowStats(); // 加载关注统计
2025-12-18 14:20:41 +08:00
setupEditableAreas();
setupAvatarClick();
2025-12-18 14:20:41 +08:00
setupNavigationClicks();
setupWorksRecycler();
setupProfileTabs();
2025-12-18 14:20:41 +08:00
2025-12-17 15:38:00 +08:00
BottomNavigationView bottomNavigation = binding.bottomNavInclude.bottomNavigation;
bottomNavigation.setSelectedItemId(R.id.nav_profile);
// 更新未读消息徽章
UnreadMessageManager.updateBadge(bottomNavigation);
2025-12-17 15:38:00 +08:00
bottomNavigation.setOnItemSelectedListener(item -> {
int id = item.getItemId();
if (id == R.id.nav_home) {
startActivity(new Intent(this, MainActivity.class));
finish();
return true;
}
if (id == R.id.nav_friends) {
startActivity(new Intent(this, FishPondActivity.class));
finish();
return true;
}
if (id == R.id.nav_wish_tree) {
WishTreeActivity.start(this);
finish();
return true;
}
if (id == R.id.nav_messages) {
MessagesActivity.start(this);
finish();
return true;
}
if (id == R.id.nav_profile) {
return true;
}
2025-12-17 15:38:00 +08:00
return true;
});
}
2025-12-18 14:20:41 +08:00
private void loadProfileFromPrefs() {
// TODO: 接入后端接口 - 获取用户资料
// 接口路径: GET /api/users/{userId}/profile
// 请求参数:
// - userId: 用户ID路径参数当前用户从token中获取
// 返回数据格式: ApiResponse<UserProfile>
// UserProfile对象应包含: id, name, avatarUrl, bio, level, badge, birthday, gender, location,
// followingCount, fansCount, likesCount等字段
// 首次加载时从接口获取,后续可从本地缓存读取
2025-12-18 14:20:41 +08:00
String n = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_NAME, null);
if (!TextUtils.isEmpty(n)) binding.name.setText(n);
String bio = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_BIO, null);
2025-12-19 10:50:13 +08:00
if (!TextUtils.isEmpty(bio) && !BIO_HINT_TEXT.equals(bio)) {
2025-12-18 14:20:41 +08:00
binding.bioText.setText(bio);
binding.bioText.setTextColor(0xFF111111);
2025-12-19 10:50:13 +08:00
} else {
binding.bioText.setText(BIO_HINT_TEXT);
binding.bioText.setTextColor(0xFF999999);
2025-12-18 14:20:41 +08:00
}
String avatarUri = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_AVATAR_URI, null);
if (!TextUtils.isEmpty(avatarUri)) {
Uri uri = Uri.parse(avatarUri);
// 如果是 file:// 协议,尝试转换为 FileProvider URI
if ("file".equals(uri.getScheme())) {
try {
java.io.File file = new java.io.File(uri.getPath());
if (file.exists()) {
uri = FileProvider.getUriForFile(
this,
getPackageName() + ".fileprovider",
file
);
}
} catch (Exception e) {
// 如果转换失败,使用原始 URI
}
}
2025-12-19 15:11:49 +08:00
Glide.with(this)
.load(uri)
2025-12-19 15:11:49 +08:00
.circleCrop()
.error(R.drawable.ic_account_circle_24)
.placeholder(R.drawable.ic_account_circle_24)
2025-12-19 15:11:49 +08:00
.into(binding.avatar);
2025-12-18 14:20:41 +08:00
} else {
int avatarRes = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getInt(KEY_AVATAR_RES, 0);
if (avatarRes != 0) {
2025-12-19 15:11:49 +08:00
Glide.with(this)
.load(avatarRes)
.circleCrop()
.error(R.drawable.ic_account_circle_24)
.into(binding.avatar);
} else {
binding.avatar.setImageResource(R.drawable.ic_account_circle_24);
2025-12-18 14:20:41 +08:00
}
}
// 等级/称号/徽章:保持固定显示(例如“月亮/星耀/至尊”),不从本地缓存覆盖。
}
/**
* 从服务器加载用户信息并同步到本地
*/
private void loadUserInfoFromServer() {
if (!AuthHelper.isLoggedIn(this)) {
return;
}
ApiClient.getService(this).getUserInfo().enqueue(new Callback<ApiResponse<UserInfoResponse>>() {
@Override
public void onResponse(Call<ApiResponse<UserInfoResponse>> call, Response<ApiResponse<UserInfoResponse>> response) {
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
UserInfoResponse userInfo = response.body().getData();
if (userInfo != null) {
syncUserInfoToLocal(userInfo);
}
}
}
@Override
public void onFailure(Call<ApiResponse<UserInfoResponse>> call, Throwable t) {
Log.e(TAG, "加载用户信息失败: " + t.getMessage());
}
});
}
/**
* 同步服务器用户信息到本地并更新UI
*/
private void syncUserInfoToLocal(UserInfoResponse userInfo) {
android.content.SharedPreferences.Editor editor = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit();
// 同步昵称
if (!TextUtils.isEmpty(userInfo.getNickname())) {
editor.putString(KEY_NAME, userInfo.getNickname());
binding.name.setText(userInfo.getNickname());
}
// 同步个性签名
if (!TextUtils.isEmpty(userInfo.getMark())) {
editor.putString(KEY_BIO, userInfo.getMark());
binding.bioText.setText(userInfo.getMark());
binding.bioText.setTextColor(0xFF111111);
}
// 同步头像
if (!TextUtils.isEmpty(userInfo.getAvatar())) {
String avatarUrl = userInfo.getAvatar();
String baseUrl = ApiClient.getCurrentBaseUrl(ProfileActivity.this);
// 处理相对路径
if (!avatarUrl.startsWith("http://") && !avatarUrl.startsWith("https://")) {
if (avatarUrl.startsWith("crmebimage/")) {
avatarUrl = baseUrl.replace("/api/", "/") + avatarUrl;
}
}
editor.putString(KEY_AVATAR_URI, avatarUrl);
Glide.with(ProfileActivity.this)
.load(avatarUrl)
.circleCrop()
.error(R.drawable.ic_account_circle_24)
.placeholder(R.drawable.ic_account_circle_24)
.into(binding.avatar);
}
// 同步生日
if (!TextUtils.isEmpty(userInfo.getBirthday())) {
editor.putString(KEY_BIRTHDAY, userInfo.getBirthday());
}
// 同步性别
if (userInfo.getSex() != null) {
String gender = "";
switch (userInfo.getSex()) {
case 1: gender = ""; break;
case 2: gender = ""; break;
case 3: gender = "保密"; break;
}
if (!TextUtils.isEmpty(gender)) {
editor.putString(KEY_GENDER, gender);
}
}
// 同步地址
if (!TextUtils.isEmpty(userInfo.getAddres())) {
editor.putString(KEY_LOCATION, userInfo.getAddres());
}
editor.apply();
// 刷新标签显示
loadAndDisplayTags();
loadProfileInfo();
}
2025-12-18 14:20:41 +08:00
private void setupEditableAreas() {
// TODO: 接入后端接口 - 更新用户资料
// 接口路径: PUT /api/users/{userId}/profile
// 请求参数:
// - userId: 用户ID路径参数从token中获取
// - name (可选): 昵称
// - bio (可选): 个人签名
// - avatarUrl (可选): 头像URL
// - birthday (可选): 生日
// - gender (可选): 性别
// - location (可选): 所在地
// 返回数据格式: ApiResponse<UserProfile>
// 更新成功后,同步更新本地缓存和界面显示
2025-12-18 14:20:41 +08:00
binding.name.setOnClickListener(v -> showEditDialog("编辑昵称", binding.name.getText() != null ? binding.name.getText().toString() : "", text -> {
binding.name.setText(text);
getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit().putString(KEY_NAME, text).apply();
}));
2025-12-19 10:50:13 +08:00
binding.bioText.setOnClickListener(v -> {
String current = binding.bioText.getText() != null ? binding.bioText.getText().toString() : "";
String initial = BIO_HINT_TEXT.equals(current) ? "" : current;
showEditDialog("编辑签名", initial, text -> {
if (TextUtils.isEmpty(text) || BIO_HINT_TEXT.equals(text)) {
binding.bioText.setText(BIO_HINT_TEXT);
binding.bioText.setTextColor(0xFF999999);
getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit().remove(KEY_BIO).apply();
} else {
binding.bioText.setText(text);
binding.bioText.setTextColor(0xFF111111);
getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit().putString(KEY_BIO, text).apply();
}
});
});
2025-12-18 14:20:41 +08:00
}
private void setupAvatarClick() {
binding.avatar.setOnClickListener(v -> {
AvatarViewerDialog dialog = AvatarViewerDialog.create(this);
// 优先从SharedPreferences读取最新的头像信息因为ImageView可能还在加载中
String avatarUri = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_AVATAR_URI, null);
int avatarRes = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getInt(KEY_AVATAR_RES, 0);
if (!TextUtils.isEmpty(avatarUri)) {
// 使用URI加载确保能正确显示
dialog.setAvatarUri(Uri.parse(avatarUri));
} else if (avatarRes != 0) {
dialog.setAvatarResId(avatarRes);
} else {
// 如果都没有尝试从ImageView获取Drawable
Drawable drawable = binding.avatar.getDrawable();
if (drawable != null) {
dialog.setAvatarDrawable(drawable);
} else {
dialog.setAvatarResId(R.drawable.ic_account_circle_24);
}
}
dialog.show();
2025-12-23 12:39:14 +08:00
});
}
2025-12-18 14:20:41 +08:00
private void setupNavigationClicks() {
binding.topActionSearch.setOnClickListener(v -> TabPlaceholderActivity.start(this, "定位/发现"));
2025-12-23 18:09:56 +08:00
binding.topActionClock.setOnClickListener(v -> {
// 检查登录状态,观看历史需要登录
if (!AuthHelper.requireLogin(this, "查看观看历史需要登录")) {
return;
}
WatchHistoryActivity.start(this);
});
2025-12-18 14:20:41 +08:00
binding.topActionMore.setOnClickListener(v -> TabPlaceholderActivity.start(this, "更多"));
binding.copyIdBtn.setOnClickListener(v -> {
String idText = binding.idLine.getText() != null ? binding.idLine.getText().toString() : "";
if (TextUtils.isEmpty(idText)) return;
String digits = idText.replaceAll("\\D+", "");
if (TextUtils.isEmpty(digits)) return;
ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
if (cm != null) {
cm.setPrimaryClip(ClipData.newPlainText("id", digits));
Toast.makeText(this, "已复制:" + digits, Toast.LENGTH_SHORT).show();
}
});
// TODO: 接入后端接口 - 获取关注/粉丝/获赞数量
// 接口路径: GET /api/users/{userId}/stats
// 请求参数:
// - userId: 用户ID路径参数
// 返回数据格式: ApiResponse<{followingCount: number, fansCount: number, likesCount: number}>
// 在ProfileActivity加载时调用更新关注、粉丝、获赞数量显示
2025-12-23 18:09:56 +08:00
binding.following.setOnClickListener(v -> {
// 检查登录状态,查看关注列表需要登录
if (!AuthHelper.requireLogin(this, "查看关注列表需要登录")) {
return;
}
FollowingListActivity.start(this);
});
binding.followers.setOnClickListener(v -> {
// 检查登录状态,查看粉丝列表需要登录
if (!AuthHelper.requireLogin(this, "查看粉丝列表需要登录")) {
return;
}
FansListActivity.start(this);
});
binding.likes.setOnClickListener(v -> {
// 检查登录状态,查看获赞列表需要登录
if (!AuthHelper.requireLogin(this, "查看获赞列表需要登录")) {
return;
}
LikesListActivity.start(this);
});
2025-12-18 14:20:41 +08:00
2026-01-03 17:01:58 +08:00
binding.action1.setOnClickListener(v -> {
// 我的关注
if (!AuthHelper.requireLogin(this, "查看关注列表需要登录")) {
return;
}
startActivity(new Intent(this, FollowingActivity.class));
});
2025-12-23 18:09:56 +08:00
binding.action2.setOnClickListener(v -> {
2026-01-03 17:01:58 +08:00
// 我的收藏(点赞的直播间)
if (!AuthHelper.requireLogin(this, "查看收藏需要登录")) {
2025-12-23 18:09:56 +08:00
return;
}
2026-01-03 17:01:58 +08:00
startActivity(new Intent(this, LikedRoomsActivity.class));
2025-12-23 18:09:56 +08:00
});
2025-12-18 14:20:41 +08:00
binding.action3.setOnClickListener(v -> startActivity(new Intent(this, MyFriendsActivity.class)));
binding.editProfile.setOnClickListener(v -> {
2025-12-23 18:09:56 +08:00
// 检查登录状态,编辑资料需要登录
if (!AuthHelper.requireLogin(this, "编辑资料需要登录")) {
return;
}
Intent intent = new Intent(this, EditProfileActivity.class);
editProfileLauncher.launch(intent);
});
2025-12-23 18:09:56 +08:00
binding.shareHome.setOnClickListener(v -> {
// 检查登录状态,分享个人主页需要登录
if (!AuthHelper.requireLogin(this, "分享个人主页需要登录")) {
return;
}
showShareProfileDialog();
});
// 主播中心按钮点击事件
binding.streamerCenterBtn.setOnClickListener(v -> {
StreamerCenterActivity.start(this);
});
binding.addFriendBtn.setOnClickListener(v -> {
// 检查登录状态,添加好友需要登录
if (!AuthHelper.requireLogin(this, "添加好友需要登录")) {
return;
}
AddFriendActivity.start(this);
});
2025-12-18 14:20:41 +08:00
}
private void setupProfileTabs() {
showTab(0);
binding.profileTabs.addOnTabSelectedListener(new com.google.android.material.tabs.TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(com.google.android.material.tabs.TabLayout.Tab tab) {
if (tab == null) return;
showTab(tab.getPosition());
}
@Override
public void onTabUnselected(com.google.android.material.tabs.TabLayout.Tab tab) {
}
@Override
public void onTabReselected(com.google.android.material.tabs.TabLayout.Tab tab) {
if (tab == null) return;
showTab(tab.getPosition());
}
});
2025-12-23 18:09:56 +08:00
// TODO: 接入后端接口 - 发布作品
// 接口路径: POST /api/works
// 请求参数:
// - userId: 用户ID从token中获取
// - title: 作品标题
// - description: 作品描述(可选)
// - coverUrl: 封面图片URL必填需要先上传图片
// - videoUrl (可选): 视频URL如果是视频作品
// - images (可选): 图片URL列表如果是图片作品
// 返回数据格式: ApiResponse<WorkItem>
// WorkItem对象应包含: id, title, coverUrl, likeCount, viewCount, publishTime等字段
// 发布成功后,刷新作品列表显示
// 空状态的发布按钮
2025-12-23 18:09:56 +08:00
binding.worksPublishBtn.setOnClickListener(v -> {
// 检查登录状态,发布作品需要登录
if (!AuthHelper.requireLogin(this, "发布作品需要登录")) {
return;
}
PublishWorkActivity.start(this);
});
// 悬浮按钮(固定显示)- 已隐藏
// binding.fabPublishWork.setOnClickListener(v -> {
// // 检查登录状态,发布作品需要登录
// if (!AuthHelper.requireLogin(this, "发布作品需要登录")) {
// return;
// }
// PublishWorkActivity.start(this);
// });
binding.likedGoBrowseBtn.setOnClickListener(v -> startActivity(new Intent(this, MainActivity.class)));
binding.favGoBrowseBtn.setOnClickListener(v -> startActivity(new Intent(this, MainActivity.class)));
binding.profileEditFromTab.setOnClickListener(v -> {
2025-12-23 18:09:56 +08:00
// 检查登录状态,编辑资料需要登录
if (!AuthHelper.requireLogin(this, "编辑资料需要登录")) {
return;
}
Intent intent = new Intent(this, EditProfileActivity.class);
editProfileLauncher.launch(intent);
});
}
private void setupWorksRecycler() {
worksAdapter = new UserWorksAdapter();
worksAdapter.setOnWorkClickListener(workItem -> {
if (workItem != null && !TextUtils.isEmpty(workItem.getId())) {
WorkDetailActivity.start(this, workItem.getId());
}
});
binding.worksRecycler.setLayoutManager(new GridLayoutManager(this, 3));
binding.worksRecycler.setAdapter(worksAdapter);
loadWorks();
}
private void loadWorks() {
// TODO: 接入后端接口 - 获取当前用户的作品列表
// 接口路径: GET /api/users/{userId}/works
// 请求方法: GET
// 请求头: Authorization: Bearer {token} (必填从AuthStore获取)
// 路径参数:
// - userId: String (必填) - 当前用户ID从token中解析获取
// 请求参数Query:
// - page: int (可选默认1) - 页码
// - pageSize: int (可选默认20) - 每页数量
// 返回数据格式: ApiResponse<PageResult<WorkItem>>
// 实现步骤:
// 1. 从AuthStore获取token解析userId或从用户信息中获取
// 2. 调用接口获取作品列表
// 3. 更新UI显示作品列表或空状态
// 4. 处理错误情况(网络错误、未登录等)
// 注意: 此方法在onResume时也会调用需要避免重复请求
// 临时:从本地存储加载(等待后端接口)
List<WorkItem> works = WorkManager.getAllWorks(this);
if (works != null && !works.isEmpty()) {
binding.worksRecycler.setVisibility(View.VISIBLE);
binding.worksEmptyState.setVisibility(View.GONE);
worksAdapter.submitList(works);
} else {
binding.worksRecycler.setVisibility(View.GONE);
binding.worksEmptyState.setVisibility(View.VISIBLE);
}
}
private void showTab(int index) {
2025-12-23 18:09:56 +08:00
// TODO: 接入后端接口 - 获取用户作品列表
// 接口路径: GET /api/users/{userId}/works
// 请求参数:
// - userId: 用户ID从token中获取
// - page (可选): 页码
// - pageSize (可选): 每页数量
// 返回数据格式: ApiResponse<List<WorkItem>>
// WorkItem对象应包含: id, title, coverUrl, likeCount, viewCount, publishTime等字段
// TODO: 接入后端接口 - 获取用户收藏列表
// 接口路径: GET /api/users/{userId}/favorites
// 请求参数:
// - userId: 用户ID从token中获取
// - page (可选): 页码
// - pageSize (可选): 每页数量
// 返回数据格式: ApiResponse<List<WorkItem>>
// TODO: 接入后端接口 - 获取用户赞过的作品列表
// 接口路径: GET /api/users/{userId}/liked
// 请求参数:
// - userId: 用户ID从token中获取
// - page (可选): 页码
// - pageSize (可选): 每页数量
// 返回数据格式: ApiResponse<List<WorkItem>>
// 标签页顺序0-作品, 1-收藏, 2-赞过
binding.tabWorks.setVisibility(index == 0 ? View.VISIBLE : View.GONE);
binding.tabFavorites.setVisibility(index == 1 ? View.VISIBLE : View.GONE);
binding.tabLiked.setVisibility(index == 2 ? View.VISIBLE : View.GONE);
// 当切换到作品标签页时,重新加载作品列表
if (index == 0) {
loadWorks();
}
// "资料"标签页已移除
}
2025-12-18 14:20:41 +08:00
private interface OnTextSaved {
void onSaved(String text);
}
private void showEditDialog(String title, String initialValue, OnTextSaved onSaved) {
EditText editText = new EditText(this);
editText.setText(initialValue != null ? initialValue : "");
editText.setSelection(editText.getText() != null ? editText.getText().length() : 0);
2025-12-19 10:50:13 +08:00
editText.setTextColor(0xFF111111);
editText.setHintTextColor(0xFF999999);
if ("编辑签名".equals(title)) {
editText.setHint(BIO_HINT_TEXT);
}
2025-12-18 14:20:41 +08:00
int pad = (int) (16 * getResources().getDisplayMetrics().density);
editText.setPadding(pad, pad, pad, pad);
new AlertDialog.Builder(this)
.setTitle(title)
.setView(editText)
.setNegativeButton("取消", null)
.setPositiveButton("保存", (d, w) -> {
String t = editText.getText() != null ? editText.getText().toString().trim() : "";
if (onSaved != null) onSaved.onSaved(t);
})
.show();
}
2025-12-17 15:38:00 +08:00
@Override
protected void onResume() {
super.onResume();
if (binding != null) {
2025-12-18 14:20:41 +08:00
loadProfileFromPrefs();
loadAndDisplayTags();
loadProfileInfo();
loadFollowStats(); // 刷新关注统计
loadWorks(); // 重新加载作品列表
BottomNavigationView bottomNav = binding.bottomNavInclude.bottomNavigation;
bottomNav.setSelectedItemId(R.id.nav_profile);
// 更新未读消息徽章
UnreadMessageManager.updateBadge(bottomNav);
// 检查主播状态并显示/隐藏主播中心按钮
checkAndUpdateStreamerButton();
}
}
/**
* 检查主播状态并更新主播中心按钮的显示
*/
private void checkAndUpdateStreamerButton() {
// 如果用户未登录,隐藏主播中心按钮
if (!AuthHelper.isLoggedIn(this)) {
if (binding.streamerCenterBtn != null) {
binding.streamerCenterBtn.setVisibility(View.GONE);
}
return;
}
// 检查主播资格
ApiClient.getService(getApplicationContext()).checkStreamerStatus()
.enqueue(new Callback<ApiResponse<java.util.Map<String, Object>>>() {
@Override
public void onResponse(Call<ApiResponse<java.util.Map<String, Object>>> call,
Response<ApiResponse<java.util.Map<String, Object>>> response) {
if (!response.isSuccessful() || response.body() == null) {
// 接口调用失败,隐藏按钮
if (binding.streamerCenterBtn != null) {
binding.streamerCenterBtn.setVisibility(View.GONE);
}
return;
}
ApiResponse<java.util.Map<String, Object>> body = response.body();
if (body.getCode() != 200 || body.getData() == null) {
// 接口返回错误,隐藏按钮
if (binding.streamerCenterBtn != null) {
binding.streamerCenterBtn.setVisibility(View.GONE);
}
return;
}
java.util.Map<String, Object> data = body.getData();
Boolean isStreamer = data.get("isStreamer") != null && (Boolean) data.get("isStreamer");
Boolean isBanned = data.get("isBanned") != null && (Boolean) data.get("isBanned");
// 只有认证主播且未被封禁才显示主播中心按钮
if (isStreamer && !isBanned && binding.streamerCenterBtn != null) {
binding.streamerCenterBtn.setVisibility(View.VISIBLE);
} else if (binding.streamerCenterBtn != null) {
binding.streamerCenterBtn.setVisibility(View.GONE);
}
}
@Override
public void onFailure(Call<ApiResponse<java.util.Map<String, Object>>> call, Throwable t) {
// 网络错误,隐藏按钮
if (binding.streamerCenterBtn != null) {
binding.streamerCenterBtn.setVisibility(View.GONE);
}
}
});
}
private void loadAndDisplayTags() {
String location = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_LOCATION, "");
String gender = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_GENDER, "");
String birthday = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_BIRTHDAY, "");
// 设置所在地标签 - 支持"省份-城市"格式
if (!TextUtils.isEmpty(location)) {
// 将"省份-城市"格式转换为"省份·城市"显示
String displayLocation = location.replace("-", "·");
binding.tagLocation.setText("IP" + displayLocation);
binding.tagLocation.setVisibility(View.VISIBLE);
} else {
binding.tagLocation.setText("IP广西");
binding.tagLocation.setVisibility(View.VISIBLE);
}
// 设置性别标签
if (!TextUtils.isEmpty(gender)) {
if (gender.contains("")) {
binding.tagGender.setText("");
} else if (gender.contains("")) {
binding.tagGender.setText("");
} else {
binding.tagGender.setText("H");
}
binding.tagGender.setVisibility(View.VISIBLE);
} else {
binding.tagGender.setText("H");
binding.tagGender.setVisibility(View.VISIBLE);
}
// 计算并设置年龄标签
if (!TextUtils.isEmpty(birthday)) {
int age = calculateAge(birthday);
if (age > 0) {
binding.tagAge.setText(age + "");
binding.tagAge.setVisibility(View.VISIBLE);
} else {
binding.tagAge.setVisibility(View.GONE);
}
} else {
binding.tagAge.setVisibility(View.GONE);
}
// 计算并设置星座标签
if (!TextUtils.isEmpty(birthday)) {
String constellation = calculateConstellation(birthday);
if (!TextUtils.isEmpty(constellation)) {
binding.tagConstellation.setText(constellation);
binding.tagConstellation.setVisibility(View.VISIBLE);
} else {
binding.tagConstellation.setVisibility(View.GONE);
}
} else {
binding.tagConstellation.setVisibility(View.GONE);
}
}
private void loadProfileInfo() {
String name = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_NAME, "爱你");
String location = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_LOCATION, "广西");
String bio = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).getString(KEY_BIO, null);
if (binding.profileInfoLine1 != null) {
binding.profileInfoLine1.setText("昵称:" + name);
}
if (binding.profileInfoLine2 != null) {
String locationText = !TextUtils.isEmpty(location) ? location : "广西";
binding.profileInfoLine2.setText("地区:" + locationText);
}
if (binding.profileInfoLine3 != null) {
String bioText = (!TextUtils.isEmpty(bio) && !BIO_HINT_TEXT.equals(bio)) ? bio : "填写个人签名更容易获得关注";
binding.profileInfoLine3.setText("签名:" + bioText);
}
}
private int calculateAge(String birthdayStr) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
Date birthDate = sdf.parse(birthdayStr);
if (birthDate == null) return 0;
Calendar birth = Calendar.getInstance();
birth.setTime(birthDate);
Calendar now = Calendar.getInstance();
int age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
age--;
}
return age;
} catch (ParseException e) {
return 0;
}
}
private String calculateConstellation(String birthdayStr) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
Date birthDate = sdf.parse(birthdayStr);
if (birthDate == null) return "";
Calendar cal = Calendar.getInstance();
cal.setTime(birthDate);
int month = cal.get(Calendar.MONTH) + 1; // Calendar.MONTH 从0开始
int day = cal.get(Calendar.DAY_OF_MONTH);
// 星座计算
if ((month == 3 && day >= 21) || (month == 4 && day <= 19)) {
return "白羊座";
} else if ((month == 4 && day >= 20) || (month == 5 && day <= 20)) {
return "金牛座";
} else if ((month == 5 && day >= 21) || (month == 6 && day <= 21)) {
return "双子座";
} else if ((month == 6 && day >= 22) || (month == 7 && day <= 22)) {
return "巨蟹座";
} else if ((month == 7 && day >= 23) || (month == 8 && day <= 22)) {
return "狮子座";
} else if ((month == 8 && day >= 23) || (month == 9 && day <= 22)) {
return "处女座";
} else if ((month == 9 && day >= 23) || (month == 10 && day <= 23)) {
return "天秤座";
} else if ((month == 10 && day >= 24) || (month == 11 && day <= 22)) {
return "天蝎座";
} else if ((month == 11 && day >= 23) || (month == 12 && day <= 21)) {
return "射手座";
} else if ((month == 12 && day >= 22) || (month == 1 && day <= 19)) {
return "摩羯座";
} else if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) {
return "水瓶座";
} else if ((month == 2 && day >= 19) || (month == 3 && day <= 20)) {
return "双鱼座";
}
return "";
} catch (ParseException e) {
return "";
2025-12-17 15:38:00 +08:00
}
}
2025-12-23 12:39:14 +08:00
/**
* 显示分享个人主页对话框
*/
private void showShareProfileDialog() {
// 获取用户ID
String idText = binding.idLine.getText() != null ? binding.idLine.getText().toString() : "";
String digits = !TextUtils.isEmpty(idText) ? idText.replaceAll("\\D+", "") : "";
if (TextUtils.isEmpty(digits)) {
digits = "24187196"; // 默认ID
}
// 直接生成分享链接
String shareLink = ShareUtils.generateProfileShareLink(digits);
ShareUtils.shareLink(this, shareLink, "个人主页", "来看看我的主页吧");
}
/**
* 加载关注统计数据
*/
private void loadFollowStats() {
com.example.livestreaming.net.ApiService apiService =
2025-12-30 09:31:15 +08:00
com.example.livestreaming.net.ApiClient.getService(this);
retrofit2.Call<com.example.livestreaming.net.ApiResponse<java.util.Map<String, Object>>> call =
apiService.getFollowStats(null); // null表示查询当前用户
call.enqueue(new retrofit2.Callback<com.example.livestreaming.net.ApiResponse<java.util.Map<String, Object>>>() {
@Override
public void onResponse(retrofit2.Call<com.example.livestreaming.net.ApiResponse<java.util.Map<String, Object>>> call,
retrofit2.Response<com.example.livestreaming.net.ApiResponse<java.util.Map<String, Object>>> response) {
if (response.isSuccessful() && response.body() != null) {
com.example.livestreaming.net.ApiResponse<java.util.Map<String, Object>> apiResponse = response.body();
if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
java.util.Map<String, Object> stats = apiResponse.getData();
// 更新关注数
Object followingCount = stats.get("followingCount");
if (followingCount != null) {
int count = 0;
if (followingCount instanceof Number) {
count = ((Number) followingCount).intValue();
}
binding.following.setText(count + "\n关注");
2026-01-03 17:01:58 +08:00
// 更新快捷操作区域的关注数
android.widget.TextView followingCountText = findViewById(R.id.followingCount);
if (followingCountText != null) {
followingCountText.setText(count + "");
}
}
// 更新粉丝数
Object followersCount = stats.get("followersCount");
if (followersCount != null) {
int count = 0;
if (followersCount instanceof Number) {
count = ((Number) followersCount).intValue();
}
binding.followers.setText(count + "\n粉丝");
}
}
}
}
@Override
public void onFailure(retrofit2.Call<com.example.livestreaming.net.ApiResponse<java.util.Map<String, Object>>> call, Throwable t) {
// 忽略错误,使用默认显示
}
});
2026-01-03 17:01:58 +08:00
// 加载收藏数(点赞的直播间数量)
loadLikedRoomsCount();
}
/**
* 加载收藏数点赞的直播间数量
*/
private void loadLikedRoomsCount() {
com.example.livestreaming.net.ApiService apiService =
com.example.livestreaming.net.ApiClient.getService(this);
retrofit2.Call<com.example.livestreaming.net.ApiResponse<com.example.livestreaming.net.PageResponse<java.util.Map<String, Object>>>> call =
apiService.getMyLikedRooms(1, 1); // 只获取第一页,用于获取总数
call.enqueue(new retrofit2.Callback<com.example.livestreaming.net.ApiResponse<com.example.livestreaming.net.PageResponse<java.util.Map<String, Object>>>>() {
@Override
public void onResponse(retrofit2.Call<com.example.livestreaming.net.ApiResponse<com.example.livestreaming.net.PageResponse<java.util.Map<String, Object>>>> call,
retrofit2.Response<com.example.livestreaming.net.ApiResponse<com.example.livestreaming.net.PageResponse<java.util.Map<String, Object>>>> response) {
if (response.isSuccessful() && response.body() != null) {
com.example.livestreaming.net.ApiResponse<com.example.livestreaming.net.PageResponse<java.util.Map<String, Object>>> apiResponse = response.body();
if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
com.example.livestreaming.net.PageResponse<java.util.Map<String, Object>> pageData = apiResponse.getData();
int total = pageData.getTotal();
// 更新快捷操作区域的收藏数
android.widget.TextView likedRoomsCountText = findViewById(R.id.likedRoomsCount);
if (likedRoomsCountText != null) {
likedRoomsCountText.setText(total + "个直播间");
}
}
}
}
@Override
public void onFailure(retrofit2.Call<com.example.livestreaming.net.ApiResponse<com.example.livestreaming.net.PageResponse<java.util.Map<String, Object>>>> call, Throwable t) {
// 忽略错误,使用默认显示
}
});
}
2025-12-17 15:38:00 +08:00
}