diff --git a/android-app/.gradle/8.1/checksums/checksums.lock b/android-app/.gradle/8.1/checksums/checksums.lock index 0375b173..600cca4e 100644 Binary files a/android-app/.gradle/8.1/checksums/checksums.lock and b/android-app/.gradle/8.1/checksums/checksums.lock differ diff --git a/android-app/.gradle/8.1/checksums/md5-checksums.bin b/android-app/.gradle/8.1/checksums/md5-checksums.bin index e1a66591..6269323a 100644 Binary files a/android-app/.gradle/8.1/checksums/md5-checksums.bin and b/android-app/.gradle/8.1/checksums/md5-checksums.bin differ diff --git a/android-app/.gradle/8.1/checksums/sha1-checksums.bin b/android-app/.gradle/8.1/checksums/sha1-checksums.bin index 21a291aa..b2f0db5d 100644 Binary files a/android-app/.gradle/8.1/checksums/sha1-checksums.bin and b/android-app/.gradle/8.1/checksums/sha1-checksums.bin differ diff --git a/android-app/.gradle/8.1/executionHistory/executionHistory.bin b/android-app/.gradle/8.1/executionHistory/executionHistory.bin index 0e39a399..e0f609a2 100644 Binary files a/android-app/.gradle/8.1/executionHistory/executionHistory.bin and b/android-app/.gradle/8.1/executionHistory/executionHistory.bin differ diff --git a/android-app/.gradle/8.1/executionHistory/executionHistory.lock b/android-app/.gradle/8.1/executionHistory/executionHistory.lock index c9c16772..ddc8c3a2 100644 Binary files a/android-app/.gradle/8.1/executionHistory/executionHistory.lock and b/android-app/.gradle/8.1/executionHistory/executionHistory.lock differ diff --git a/android-app/.gradle/8.1/fileHashes/fileHashes.bin b/android-app/.gradle/8.1/fileHashes/fileHashes.bin index 580ace12..15cb7df5 100644 Binary files a/android-app/.gradle/8.1/fileHashes/fileHashes.bin and b/android-app/.gradle/8.1/fileHashes/fileHashes.bin differ diff --git a/android-app/.gradle/8.1/fileHashes/fileHashes.lock b/android-app/.gradle/8.1/fileHashes/fileHashes.lock index 8ddce006..cbd13d8c 100644 Binary files a/android-app/.gradle/8.1/fileHashes/fileHashes.lock and b/android-app/.gradle/8.1/fileHashes/fileHashes.lock differ diff --git a/android-app/.gradle/8.1/fileHashes/resourceHashesCache.bin b/android-app/.gradle/8.1/fileHashes/resourceHashesCache.bin index 639b62fa..efbaed62 100644 Binary files a/android-app/.gradle/8.1/fileHashes/resourceHashesCache.bin and b/android-app/.gradle/8.1/fileHashes/resourceHashesCache.bin differ diff --git a/android-app/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/android-app/.gradle/buildOutputCleanup/buildOutputCleanup.lock index c2f8b135..9793642f 100644 Binary files a/android-app/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/android-app/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/android-app/.gradle/buildOutputCleanup/outputFiles.bin b/android-app/.gradle/buildOutputCleanup/outputFiles.bin index f219c029..ebbd7cc8 100644 Binary files a/android-app/.gradle/buildOutputCleanup/outputFiles.bin and b/android-app/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/android-app/.gradle/file-system.probe b/android-app/.gradle/file-system.probe index aa2336d6..b3285246 100644 Binary files a/android-app/.gradle/file-system.probe and b/android-app/.gradle/file-system.probe differ diff --git a/android-app/app/build.gradle.kts b/android-app/app/build.gradle.kts index 05ead42b..2499ba47 100644 --- a/android-app/app/build.gradle.kts +++ b/android-app/app/build.gradle.kts @@ -41,8 +41,13 @@ dependencies { implementation("androidx.core:core:1.12.0") implementation("androidx.appcompat:appcompat:1.6.1") implementation("com.google.android.material:material:1.11.0") + implementation("androidx.coordinatorlayout:coordinatorlayout:1.2.0") implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("androidx.recyclerview:recyclerview:1.3.2") + implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") + + implementation("com.github.bumptech.glide:glide:4.16.0") + annotationProcessor("com.github.bumptech.glide:compiler:4.16.0") implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") diff --git a/android-app/app/src/main/AndroidManifest.xml b/android-app/app/src/main/AndroidManifest.xml index f56514d3..1a521b97 100644 --- a/android-app/app/src/main/AndroidManifest.xml +++ b/android-app/app/src/main/AndroidManifest.xml @@ -11,6 +11,22 @@ android:theme="@style/Theme.LiveStreaming" android:usesCleartextTraffic="true"> + + + + + + + + diff --git a/android-app/app/src/main/assets/img/.keep b/android-app/app/src/main/assets/img/.keep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/android-app/app/src/main/assets/img/.keep @@ -0,0 +1 @@ + diff --git a/android-app/app/src/main/java/com/example/livestreaming/FishPondActivity.java b/android-app/app/src/main/java/com/example/livestreaming/FishPondActivity.java new file mode 100644 index 00000000..68a5ca22 --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/FishPondActivity.java @@ -0,0 +1,56 @@ +package com.example.livestreaming; + +import android.content.Intent; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; + +import com.example.livestreaming.databinding.ActivityFishPondBinding; +import com.google.android.material.bottomnavigation.BottomNavigationView; + +public class FishPondActivity extends AppCompatActivity { + + private ActivityFishPondBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityFishPondBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + BottomNavigationView bottomNavigation = binding.bottomNavInclude.bottomNavigation; + bottomNavigation.setSelectedItemId(R.id.nav_friends); + 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_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) { + ProfileActivity.start(this); + finish(); + return true; + } + return true; + }); + } + + @Override + protected void onResume() { + super.onResume(); + if (binding != null) { + binding.bottomNavInclude.bottomNavigation.setSelectedItemId(R.id.nav_friends); + } + } +} diff --git a/android-app/app/src/main/java/com/example/livestreaming/MainActivity.java b/android-app/app/src/main/java/com/example/livestreaming/MainActivity.java index b75f026b..e631bc3d 100644 --- a/android-app/app/src/main/java/com/example/livestreaming/MainActivity.java +++ b/android-app/app/src/main/java/com/example/livestreaming/MainActivity.java @@ -1,5 +1,6 @@ package com.example.livestreaming; +import android.content.res.AssetManager; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Intent; @@ -11,17 +12,23 @@ import android.text.TextUtils; import android.view.View; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.example.livestreaming.databinding.ActivityMainBinding; import com.example.livestreaming.databinding.DialogCreateRoomBinding; +import com.google.android.material.bottomnavigation.BottomNavigationView; import com.example.livestreaming.net.ApiClient; import com.example.livestreaming.net.ApiResponse; import com.example.livestreaming.net.CreateRoomRequest; import com.example.livestreaming.net.Room; +import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -37,6 +44,9 @@ public class MainActivity extends AppCompatActivity { private final Handler handler = new Handler(Looper.getMainLooper()); private Runnable pollRunnable; + private boolean isFetching; + private long lastFetchMs; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -50,10 +60,79 @@ public class MainActivity extends AppCompatActivity { startActivity(intent); }); - binding.roomsRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + StaggeredGridLayoutManager glm = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); + glm.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS); + binding.roomsRecyclerView.setLayoutManager(glm); binding.roomsRecyclerView.setAdapter(adapter); - binding.startLiveButton.setOnClickListener(v -> showCreateRoomDialog()); + loadCoverAssets(); + + binding.swipeRefresh.setOnRefreshListener(this::fetchRooms); + + binding.roomsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + if (dy <= 0) return; + RecyclerView.LayoutManager lm = recyclerView.getLayoutManager(); + if (!(lm instanceof StaggeredGridLayoutManager)) return; + StaggeredGridLayoutManager sglm = (StaggeredGridLayoutManager) lm; + int total = sglm.getItemCount(); + int[] last = sglm.findLastVisibleItemPositions(null); + int lastVisible = -1; + if (last != null) { + for (int v : last) { + if (v > lastVisible) lastVisible = v; + } + } + if (total <= 0) return; + + if (lastVisible >= total - 4) { + long now = System.currentTimeMillis(); + if (!isFetching && now - lastFetchMs > 1500) { + fetchRooms(); + } + } + } + }); + + BottomNavigationView bottomNavigation = binding.bottomNavInclude.bottomNavigation; + bottomNavigation.setSelectedItemId(R.id.nav_home); + bottomNavigation.setOnItemSelectedListener(item -> { + int id = item.getItemId(); + if (id == R.id.nav_home) { + 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) { + ProfileActivity.start(this); + finish(); + return true; + } + return true; + }); + } + + @Override + protected void onResume() { + super.onResume(); + if (binding != null) { + BottomNavigationView bottomNavigation = binding.bottomNavInclude.bottomNavigation; + bottomNavigation.setSelectedItemId(R.id.nav_home); + } } @Override @@ -200,22 +279,64 @@ public class MainActivity extends AppCompatActivity { } private void fetchRooms() { + isFetching = true; + lastFetchMs = System.currentTimeMillis(); binding.loading.setVisibility(View.VISIBLE); ApiClient.getService().getRooms().enqueue(new Callback>>() { @Override public void onResponse(Call>> call, Response>> response) { binding.loading.setVisibility(View.GONE); + binding.swipeRefresh.setRefreshing(false); + isFetching = false; ApiResponse> body = response.body(); List rooms = body != null && body.getData() != null ? body.getData() : Collections.emptyList(); + if (rooms == null || rooms.isEmpty()) { + rooms = buildDemoRooms(12); + } adapter.submitList(rooms); + adapter.bumpCoverOffset(); } @Override public void onFailure(Call>> call, Throwable t) { binding.loading.setVisibility(View.GONE); - adapter.submitList(Collections.emptyList()); + binding.swipeRefresh.setRefreshing(false); + isFetching = false; + adapter.submitList(buildDemoRooms(12)); + adapter.bumpCoverOffset(); } }); } + + private List buildDemoRooms(int count) { + List list = new ArrayList<>(); + for (int i = 0; i < count; i++) { + String id = "demo-" + i; + String title = "王者荣耀陪练" + (i + 1); + String streamer = "虚拟主播" + (i + 1); + boolean live = i % 3 != 0; + list.add(new Room(id, title, streamer, live)); + } + return list; + } + + private void loadCoverAssets() { + AssetManager am = getAssets(); + List files = new ArrayList<>(); + try { + String[] list = am.list("img"); + if (list != null) { + for (String f : list) { + if (f == null) continue; + String lower = f.toLowerCase(); + if (lower.endsWith(".png") || lower.endsWith(".jpg") || lower.endsWith(".jpeg") || lower.endsWith(".webp") || lower.endsWith(".gif")) { + files.add(f); + } + } + } + } catch (IOException ignored) { + } + adapter.setCoverAssetFiles(files); + } } diff --git a/android-app/app/src/main/java/com/example/livestreaming/MainActivity.kt b/android-app/app/src/main/java/com/example/livestreaming/MainActivity.kt deleted file mode 100644 index 4da28947..00000000 --- a/android-app/app/src/main/java/com/example/livestreaming/MainActivity.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.livestreaming - diff --git a/android-app/app/src/main/java/com/example/livestreaming/MessagesActivity.java b/android-app/app/src/main/java/com/example/livestreaming/MessagesActivity.java new file mode 100644 index 00000000..ea041a40 --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/MessagesActivity.java @@ -0,0 +1,65 @@ +package com.example.livestreaming; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; + +import com.example.livestreaming.databinding.ActivityMessagesBinding; +import com.google.android.material.bottomnavigation.BottomNavigationView; + +public class MessagesActivity extends AppCompatActivity { + + private ActivityMessagesBinding binding; + + public static void start(Context context) { + Intent intent = new Intent(context, MessagesActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityMessagesBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + BottomNavigationView bottomNavigation = binding.bottomNavInclude.bottomNavigation; + bottomNavigation.setSelectedItemId(R.id.nav_messages); + bottomNavigation.setOnItemSelectedListener(item -> { + int id = item.getItemId(); + if (id == R.id.nav_messages) { + return true; + } + 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_profile) { + ProfileActivity.start(this); + finish(); + return true; + } + return true; + }); + } + + @Override + protected void onResume() { + super.onResume(); + if (binding != null) { + binding.bottomNavInclude.bottomNavigation.setSelectedItemId(R.id.nav_messages); + } + } +} diff --git a/android-app/app/src/main/java/com/example/livestreaming/PlayerActivity.kt b/android-app/app/src/main/java/com/example/livestreaming/PlayerActivity.kt deleted file mode 100644 index 4da28947..00000000 --- a/android-app/app/src/main/java/com/example/livestreaming/PlayerActivity.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.livestreaming - diff --git a/android-app/app/src/main/java/com/example/livestreaming/ProfileActivity.java b/android-app/app/src/main/java/com/example/livestreaming/ProfileActivity.java new file mode 100644 index 00000000..89e53492 --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/ProfileActivity.java @@ -0,0 +1,62 @@ +package com.example.livestreaming; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; + +import com.example.livestreaming.databinding.ActivityProfileBinding; +import com.google.android.material.bottomnavigation.BottomNavigationView; + +public class ProfileActivity extends AppCompatActivity { + + private ActivityProfileBinding binding; + + 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()); + + BottomNavigationView bottomNavigation = binding.bottomNavInclude.bottomNavigation; + bottomNavigation.setSelectedItemId(R.id.nav_profile); + 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; + } + return true; + }); + } + + @Override + protected void onResume() { + super.onResume(); + if (binding != null) { + binding.bottomNavInclude.bottomNavigation.setSelectedItemId(R.id.nav_profile); + } + } +} diff --git a/android-app/app/src/main/java/com/example/livestreaming/RoomsAdapter.java b/android-app/app/src/main/java/com/example/livestreaming/RoomsAdapter.java index 7e4bb51a..1b3ea23a 100644 --- a/android-app/app/src/main/java/com/example/livestreaming/RoomsAdapter.java +++ b/android-app/app/src/main/java/com/example/livestreaming/RoomsAdapter.java @@ -5,14 +5,19 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.RecyclerView; +import com.bumptech.glide.Glide; import com.example.livestreaming.databinding.ItemRoomBinding; import com.example.livestreaming.net.Room; +import java.util.ArrayList; +import java.util.List; + public class RoomsAdapter extends ListAdapter { public interface OnRoomClickListener { @@ -21,11 +26,25 @@ public class RoomsAdapter extends ListAdapter { private final OnRoomClickListener onRoomClick; + private final List coverAssetFiles = new ArrayList<>(); + private int coverOffset; + public RoomsAdapter(OnRoomClickListener onRoomClick) { super(DIFF); this.onRoomClick = onRoomClick; } + public void setCoverAssetFiles(List files) { + coverAssetFiles.clear(); + if (files != null) coverAssetFiles.addAll(files); + notifyDataSetChanged(); + } + + public void bumpCoverOffset() { + coverOffset++; + notifyDataSetChanged(); + } + @NonNull @Override public RoomVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { @@ -53,6 +72,64 @@ public class RoomsAdapter extends ListAdapter { binding.roomTitle.setText(room != null && room.getTitle() != null ? room.getTitle() : "(Untitled)"); binding.streamerName.setText(room != null && room.getStreamerName() != null ? room.getStreamerName() : ""); + try { + String seed = room != null && room.getId() != null ? room.getId() : String.valueOf(getBindingAdapterPosition()); + int h = Math.abs(seed.hashCode()); + int likes = (h % 980) + 20; + binding.likeCount.setText(String.valueOf(likes)); + binding.likeIcon.setVisibility(View.VISIBLE); + binding.likeCount.setVisibility(View.VISIBLE); + } catch (Exception ignored) { + } + + try { + String seed = room != null && room.getId() != null ? room.getId() : String.valueOf(getBindingAdapterPosition()); + int h = Math.abs(seed.hashCode()); + int mode = h % 3; + String ratio; + if (mode == 0) { + ratio = "H,3:4"; + } else if (mode == 1) { + ratio = "H,4:3"; + } else { + ratio = "H,1:1"; + } + ViewGroup.LayoutParams lp = binding.coverImage.getLayoutParams(); + if (lp instanceof ConstraintLayout.LayoutParams) { + ConstraintLayout.LayoutParams clp = (ConstraintLayout.LayoutParams) lp; + if (clp.dimensionRatio == null || !clp.dimensionRatio.equals(ratio)) { + clp.dimensionRatio = ratio; + binding.coverImage.setLayoutParams(clp); + } + } + } catch (Exception ignored) { + } + + RoomsAdapter a = (RoomsAdapter) getBindingAdapter(); + String assetFile = null; + if (a != null && !a.coverAssetFiles.isEmpty()) { + int pos = getBindingAdapterPosition(); + if (pos < 0) pos = 0; + int idx = Math.abs(pos + a.coverOffset) % a.coverAssetFiles.size(); + assetFile = a.coverAssetFiles.get(idx); + } + + Object model; + if (assetFile != null) { + model = "file:///android_asset/img/" + assetFile; + } else { + String seed = room != null && room.getId() != null ? room.getId() : String.valueOf(getBindingAdapterPosition()); + int h = Math.abs(seed.hashCode()); + int imageId = (h % 1000) + 1; + model = "https://picsum.photos/id/" + imageId + "/600/450"; + } + + Glide.with(binding.coverImage) + .load(model) + .placeholder(R.drawable.bg_cover_placeholder) + .centerCrop() + .into(binding.coverImage); + if (room != null && room.isLive()) { binding.liveBadge.setVisibility(View.VISIBLE); binding.liveBadge.setBackgroundColor(ContextCompat.getColor(binding.getRoot().getContext(), R.color.live_red)); diff --git a/android-app/app/src/main/java/com/example/livestreaming/RoomsAdapter.kt b/android-app/app/src/main/java/com/example/livestreaming/RoomsAdapter.kt deleted file mode 100644 index 4da28947..00000000 --- a/android-app/app/src/main/java/com/example/livestreaming/RoomsAdapter.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.livestreaming - diff --git a/android-app/app/src/main/java/com/example/livestreaming/WishTreeActivity.java b/android-app/app/src/main/java/com/example/livestreaming/WishTreeActivity.java new file mode 100644 index 00000000..00f4c47c --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/WishTreeActivity.java @@ -0,0 +1,65 @@ +package com.example.livestreaming; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; + +import com.example.livestreaming.databinding.ActivityWishTreeBinding; +import com.google.android.material.bottomnavigation.BottomNavigationView; + +public class WishTreeActivity extends AppCompatActivity { + + private ActivityWishTreeBinding binding; + + public static void start(Context context) { + Intent intent = new Intent(context, WishTreeActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityWishTreeBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + BottomNavigationView bottomNavigation = binding.bottomNavInclude.bottomNavigation; + bottomNavigation.setSelectedItemId(R.id.nav_wish_tree); + bottomNavigation.setOnItemSelectedListener(item -> { + int id = item.getItemId(); + if (id == R.id.nav_wish_tree) { + return true; + } + 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_messages) { + MessagesActivity.start(this); + finish(); + return true; + } + if (id == R.id.nav_profile) { + ProfileActivity.start(this); + finish(); + return true; + } + return true; + }); + } + + @Override + protected void onResume() { + super.onResume(); + if (binding != null) { + binding.bottomNavInclude.bottomNavigation.setSelectedItemId(R.id.nav_wish_tree); + } + } +} diff --git a/android-app/app/src/main/java/com/example/livestreaming/net/Room.java b/android-app/app/src/main/java/com/example/livestreaming/net/Room.java index 0ce9de69..e8817447 100644 --- a/android-app/app/src/main/java/com/example/livestreaming/net/Room.java +++ b/android-app/app/src/main/java/com/example/livestreaming/net/Room.java @@ -24,6 +24,40 @@ public class Room { @SerializedName("streamUrls") private StreamUrls streamUrls; + public Room() { + } + + public Room(String id, String title, String streamerName, boolean isLive) { + this.id = id; + this.title = title; + this.streamerName = streamerName; + this.isLive = isLive; + } + + public void setId(String id) { + this.id = id; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setStreamerName(String streamerName) { + this.streamerName = streamerName; + } + + public void setLive(boolean live) { + isLive = live; + } + + public void setStreamKey(String streamKey) { + this.streamKey = streamKey; + } + + public void setStreamUrls(StreamUrls streamUrls) { + this.streamUrls = streamUrls; + } + public String getId() { return id; } diff --git a/android-app/app/src/main/res/color/bottom_nav_item_color.xml b/android-app/app/src/main/res/color/bottom_nav_item_color.xml new file mode 100644 index 00000000..8e977b20 --- /dev/null +++ b/android-app/app/src/main/res/color/bottom_nav_item_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_avatar_circle.xml b/android-app/app/src/main/res/drawable/bg_avatar_circle.xml new file mode 100644 index 00000000..d3b2957e --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_avatar_circle.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/bg_avatar_ring.xml b/android-app/app/src/main/res/drawable/bg_avatar_ring.xml new file mode 100644 index 00000000..0391e3b9 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_avatar_ring.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_chip_purple.xml b/android-app/app/src/main/res/drawable/bg_chip_purple.xml new file mode 100644 index 00000000..8eadbd5e --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_chip_purple.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_chip_yellow.xml b/android-app/app/src/main/res/drawable/bg_chip_yellow.xml new file mode 100644 index 00000000..dc12d928 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_chip_yellow.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_circle_white_60.xml b/android-app/app/src/main/res/drawable/bg_circle_white_60.xml new file mode 100644 index 00000000..f0535c99 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_circle_white_60.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/bg_cover_placeholder.xml b/android-app/app/src/main/res/drawable/bg_cover_placeholder.xml new file mode 100644 index 00000000..a6143ed6 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_cover_placeholder.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/bg_diamond_rounded.xml b/android-app/app/src/main/res/drawable/bg_diamond_rounded.xml new file mode 100644 index 00000000..0333e580 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_diamond_rounded.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_fishpond_gradient.xml b/android-app/app/src/main/res/drawable/bg_fishpond_gradient.xml new file mode 100644 index 00000000..9813730a --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_fishpond_gradient.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/bg_gray_12.xml b/android-app/app/src/main/res/drawable/bg_gray_12.xml new file mode 100644 index 00000000..05846031 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_gray_12.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_orbit_ring.xml b/android-app/app/src/main/res/drawable/bg_orbit_ring.xml new file mode 100644 index 00000000..7632b5bb --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_orbit_ring.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_pill_left.xml b/android-app/app/src/main/res/drawable/bg_pill_left.xml new file mode 100644 index 00000000..a8e36923 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_pill_left.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_pill_right.xml b/android-app/app/src/main/res/drawable/bg_pill_right.xml new file mode 100644 index 00000000..a8e36923 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_pill_right.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_profile_header_gradient.xml b/android-app/app/src/main/res/drawable/bg_profile_header_gradient.xml new file mode 100644 index 00000000..7bd1fc86 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_profile_header_gradient.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/bg_purple_20.xml b/android-app/app/src/main/res/drawable/bg_purple_20.xml new file mode 100644 index 00000000..ca9c17ff --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_purple_20.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_purple_circle.xml b/android-app/app/src/main/res/drawable/bg_purple_circle.xml new file mode 100644 index 00000000..b6ac5fe8 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_purple_circle.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/bg_search.xml b/android-app/app/src/main/res/drawable/bg_search.xml new file mode 100644 index 00000000..fd063457 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_search.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_white_16.xml b/android-app/app/src/main/res/drawable/bg_white_16.xml new file mode 100644 index 00000000..6d2cc53e --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_white_16.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_white_circle.xml b/android-app/app/src/main/res/drawable/bg_white_circle.xml new file mode 100644 index 00000000..bf1b2591 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_white_circle.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_account_circle_24.xml b/android-app/app/src/main/res/drawable/ic_account_circle_24.xml new file mode 100644 index 00000000..680b21cb --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_account_circle_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_add_24.xml b/android-app/app/src/main/res/drawable/ic_add_24.xml new file mode 100644 index 00000000..5fb4a37b --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_add_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_bottle_24.xml b/android-app/app/src/main/res/drawable/ic_bottle_24.xml new file mode 100644 index 00000000..58183304 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_bottle_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_chat_24.xml b/android-app/app/src/main/res/drawable/ic_chat_24.xml new file mode 100644 index 00000000..b5a652ea --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_chat_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_copy_24.xml b/android-app/app/src/main/res/drawable/ic_copy_24.xml new file mode 100644 index 00000000..4f16bf64 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_copy_24.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/ic_crosshair_24.xml b/android-app/app/src/main/res/drawable/ic_crosshair_24.xml new file mode 100644 index 00000000..5c336de6 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_crosshair_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_crown_16.xml b/android-app/app/src/main/res/drawable/ic_crown_16.xml new file mode 100644 index 00000000..3a476faf --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_crown_16.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/ic_fullscreen_24.xml b/android-app/app/src/main/res/drawable/ic_fullscreen_24.xml new file mode 100644 index 00000000..77fbf562 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_fullscreen_24.xml @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/android-app/app/src/main/res/drawable/ic_game_24.xml b/android-app/app/src/main/res/drawable/ic_game_24.xml new file mode 100644 index 00000000..fe83efec --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_game_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_grid_24.xml b/android-app/app/src/main/res/drawable/ic_grid_24.xml new file mode 100644 index 00000000..ed653833 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_grid_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_heart_24.xml b/android-app/app/src/main/res/drawable/ic_heart_24.xml new file mode 100644 index 00000000..1dd6ebf5 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_heart_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_home_24.xml b/android-app/app/src/main/res/drawable/ic_home_24.xml new file mode 100644 index 00000000..a7870441 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_home_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_ktv_24.xml b/android-app/app/src/main/res/drawable/ic_ktv_24.xml new file mode 100644 index 00000000..7d72690b --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_ktv_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_male_16.xml b/android-app/app/src/main/res/drawable/ic_male_16.xml new file mode 100644 index 00000000..67f0c41f --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_male_16.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_menu_24.xml b/android-app/app/src/main/res/drawable/ic_menu_24.xml new file mode 100644 index 00000000..021b0c8a --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_menu_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_mic_24.xml b/android-app/app/src/main/res/drawable/ic_mic_24.xml new file mode 100644 index 00000000..73d0a5e1 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_mic_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_notifications_24.xml b/android-app/app/src/main/res/drawable/ic_notifications_24.xml new file mode 100644 index 00000000..ad321d8d --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_notifications_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_palette_24.xml b/android-app/app/src/main/res/drawable/ic_palette_24.xml new file mode 100644 index 00000000..8b60f55c --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_palette_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_people_24.xml b/android-app/app/src/main/res/drawable/ic_people_24.xml new file mode 100644 index 00000000..dc5004e1 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_people_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_person_24.xml b/android-app/app/src/main/res/drawable/ic_person_24.xml new file mode 100644 index 00000000..d356bee7 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_person_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_search_24.xml b/android-app/app/src/main/res/drawable/ic_search_24.xml new file mode 100644 index 00000000..03dd1249 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_search_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_tree_24.xml b/android-app/app/src/main/res/drawable/ic_tree_24.xml new file mode 100644 index 00000000..113c2306 --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_tree_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/drawable/ic_voice_24.xml b/android-app/app/src/main/res/drawable/ic_voice_24.xml new file mode 100644 index 00000000..a78e5bdd --- /dev/null +++ b/android-app/app/src/main/res/drawable/ic_voice_24.xml @@ -0,0 +1,10 @@ + + + + diff --git a/android-app/app/src/main/res/layout/activity_fish_pond.xml b/android-app/app/src/main/res/layout/activity_fish_pond.xml new file mode 100644 index 00000000..e3e53edc --- /dev/null +++ b/android-app/app/src/main/res/layout/activity_fish_pond.xml @@ -0,0 +1,563 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-app/app/src/main/res/layout/activity_main.xml b/android-app/app/src/main/res/layout/activity_main.xml index 5f70914e..3a6a56c6 100644 --- a/android-app/app/src/main/res/layout/activity_main.xml +++ b/android-app/app/src/main/res/layout/activity_main.xml @@ -1,49 +1,222 @@ - - + android:background="@android:color/white"> - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /> - + + + diff --git a/android-app/app/src/main/res/layout/activity_messages.xml b/android-app/app/src/main/res/layout/activity_messages.xml new file mode 100644 index 00000000..7767de06 --- /dev/null +++ b/android-app/app/src/main/res/layout/activity_messages.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/android-app/app/src/main/res/layout/activity_profile.xml b/android-app/app/src/main/res/layout/activity_profile.xml new file mode 100644 index 00000000..1bb074c5 --- /dev/null +++ b/android-app/app/src/main/res/layout/activity_profile.xml @@ -0,0 +1,688 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-app/app/src/main/res/layout/activity_wish_tree.xml b/android-app/app/src/main/res/layout/activity_wish_tree.xml new file mode 100644 index 00000000..6e091d49 --- /dev/null +++ b/android-app/app/src/main/res/layout/activity_wish_tree.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/android-app/app/src/main/res/layout/include_bottom_nav.xml b/android-app/app/src/main/res/layout/include_bottom_nav.xml new file mode 100644 index 00000000..da3ef4e5 --- /dev/null +++ b/android-app/app/src/main/res/layout/include_bottom_nav.xml @@ -0,0 +1,26 @@ + + + + + + + diff --git a/android-app/app/src/main/res/layout/item_room.xml b/android-app/app/src/main/res/layout/item_room.xml index e502de12..4136b8ab 100644 --- a/android-app/app/src/main/res/layout/item_room.xml +++ b/android-app/app/src/main/res/layout/item_room.xml @@ -3,23 +3,22 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginHorizontal="16dp" - android:layout_marginTop="12dp" - app:cardCornerRadius="12dp"> + android:layout_margin="6dp" + app:cardCornerRadius="12dp" + app:cardElevation="0dp"> + android:layout_height="wrap_content"> - @@ -27,25 +26,93 @@ android:id="@+id/liveBadge" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingHorizontal="10dp" - android:paddingVertical="4dp" + android:layout_marginStart="8dp" + android:layout_marginTop="8dp" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:paddingTop="4dp" + android:paddingBottom="4dp" android:text="LIVE" android:textColor="@android:color/white" - android:textSize="12sp" + android:textSize="11sp" android:visibility="gone" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintStart_toStartOf="@id/coverImage" + app:layout_constraintTop_toTopOf="@id/coverImage" /> - + app:layout_constraintTop_toBottomOf="@id/coverImage"> + + + + + + + + + + + + diff --git a/android-app/app/src/main/res/menu/bottom_nav_main.xml b/android-app/app/src/main/res/menu/bottom_nav_main.xml new file mode 100644 index 00000000..37936401 --- /dev/null +++ b/android-app/app/src/main/res/menu/bottom_nav_main.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/android-app/img/u=1135031286,4059181091&fm=253&fmt=auto&app=138&f=JPEG.webp b/android-app/img/u=1135031286,4059181091&fm=253&fmt=auto&app=138&f=JPEG.webp new file mode 100644 index 00000000..b7ea66b0 Binary files /dev/null and b/android-app/img/u=1135031286,4059181091&fm=253&fmt=auto&app=138&f=JPEG.webp differ diff --git a/android-app/img/u=1180411554,747619371&fm=253&fmt=auto&app=120&f=JPEG.webp b/android-app/img/u=1180411554,747619371&fm=253&fmt=auto&app=120&f=JPEG.webp new file mode 100644 index 00000000..f30ef39d Binary files /dev/null and b/android-app/img/u=1180411554,747619371&fm=253&fmt=auto&app=120&f=JPEG.webp differ diff --git a/android-app/img/u=1692132544,3667818640&fm=253&fmt=auto&app=138&f=JPEG.webp b/android-app/img/u=1692132544,3667818640&fm=253&fmt=auto&app=138&f=JPEG.webp new file mode 100644 index 00000000..e1835fa6 Binary files /dev/null and b/android-app/img/u=1692132544,3667818640&fm=253&fmt=auto&app=138&f=JPEG.webp differ diff --git a/android-app/img/u=2710633049,1623216843&fm=253&fmt=auto&app=120&f=JPEG.webp b/android-app/img/u=2710633049,1623216843&fm=253&fmt=auto&app=120&f=JPEG.webp new file mode 100644 index 00000000..a61c4b18 Binary files /dev/null and b/android-app/img/u=2710633049,1623216843&fm=253&fmt=auto&app=120&f=JPEG.webp differ diff --git a/android-app/img/u=398795517,2983631819&fm=253&fmt=auto&app=120&f=JPEG.webp b/android-app/img/u=398795517,2983631819&fm=253&fmt=auto&app=120&f=JPEG.webp new file mode 100644 index 00000000..eaaa5a1a Binary files /dev/null and b/android-app/img/u=398795517,2983631819&fm=253&fmt=auto&app=120&f=JPEG.webp differ diff --git a/android-app/img/u=4084188214,1357286578&fm=253&fmt=auto&app=138&f=JPEG.webp b/android-app/img/u=4084188214,1357286578&fm=253&fmt=auto&app=138&f=JPEG.webp new file mode 100644 index 00000000..8385a06f Binary files /dev/null and b/android-app/img/u=4084188214,1357286578&fm=253&fmt=auto&app=138&f=JPEG.webp differ diff --git a/android-app/img/u=4202473567,2071152575&fm=253&fmt=auto.webp b/android-app/img/u=4202473567,2071152575&fm=253&fmt=auto.webp new file mode 100644 index 00000000..f3475700 Binary files /dev/null and b/android-app/img/u=4202473567,2071152575&fm=253&fmt=auto.webp differ diff --git a/android-app/img/v2-874766ff82f5e940d082f66db70daaca_1440w.jpg b/android-app/img/v2-874766ff82f5e940d082f66db70daaca_1440w.jpg new file mode 100644 index 00000000..bed84e1f Binary files /dev/null and b/android-app/img/v2-874766ff82f5e940d082f66db70daaca_1440w.jpg differ