diff --git a/Screenshot_20260114_182156.png b/Screenshot_20260114_182156.png
new file mode 100644
index 0000000..eae64e9
Binary files /dev/null and b/Screenshot_20260114_182156.png differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 663a763..4b1e167 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,23 +1,28 @@
-
+
+
+
+ tools:targetApi="31">
+
+ android:windowSoftInputMode="adjustResize|stateHidden"
+ tools:ignore="Instantiatable" />
@@ -33,7 +38,6 @@
-
\ No newline at end of file
diff --git a/app/src/main/java/com/example/gallery/LoginActivity.java b/app/src/main/java/com/example/gallery/LoginActivity.java
index 5c34323..1091410 100644
--- a/app/src/main/java/com/example/gallery/LoginActivity.java
+++ b/app/src/main/java/com/example/gallery/LoginActivity.java
@@ -20,7 +20,8 @@ import retrofit2.Response;
public class LoginActivity extends AppCompatActivity {
- private EditText usernameEdit, passwordEdit;
+ private EditText usernameEdit;
+ private EditText passwordEdit;
private Button loginBtn;
private TextView registerTV;
@@ -29,12 +30,19 @@ public class LoginActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
+ // Views
usernameEdit = findViewById(R.id.usernameTxt);
passwordEdit = findViewById(R.id.userpasswordTxt);
loginBtn = findViewById(R.id.btnLogin);
registerTV = findViewById(R.id.registerTV);
+ // Login button
loginBtn.setOnClickListener(v -> login());
+
+ // Register text → RegisterActivity
+ registerTV.setOnClickListener(v -> {
+ startActivity(new Intent(LoginActivity.this, RegisterActivity.class));
+ });
}
private void login() {
@@ -52,27 +60,33 @@ public class LoginActivity extends AppCompatActivity {
apiService.login(request).enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
+
if (response.isSuccessful() && response.body() != null) {
- // 🔑 STORE RAW TOKEN ONLY
+ // ✅ Save auth state
getSharedPreferences("MyAppPrefs", MODE_PRIVATE)
.edit()
.putString("authToken", response.body().getToken())
.putBoolean("isLoggedIn", true)
.apply();
- Toast.makeText(LoginActivity.this, "Login successful", Toast.LENGTH_SHORT).show();
+ Toast.makeText(LoginActivity.this,
+ "Login successful", Toast.LENGTH_SHORT).show();
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
+
} else {
- Toast.makeText(LoginActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
+ Toast.makeText(LoginActivity.this,
+ "Invalid username or password", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call call, Throwable t) {
- Toast.makeText(LoginActivity.this, "Server error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
+ Toast.makeText(LoginActivity.this,
+ "Server error: " + t.getMessage(),
+ Toast.LENGTH_SHORT).show();
}
});
}
diff --git a/app/src/main/java/com/example/gallery/MainActivity.java b/app/src/main/java/com/example/gallery/MainActivity.java
index 63610ae..61395e9 100644
--- a/app/src/main/java/com/example/gallery/MainActivity.java
+++ b/app/src/main/java/com/example/gallery/MainActivity.java
@@ -4,6 +4,9 @@ import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
@@ -28,111 +31,173 @@ public class MainActivity extends AppCompatActivity {
private Button loginBtn, registerBtn, logoutBtn, newPostBtn;
private RecyclerView recyclerView;
private PostsAdapter postsAdapter;
+ private ImageButton burgerMenuBtn;
+ private LinearLayout dropdownMenu;
+ private TextView menuLogout, menuNewPost;
+ private ImageButton filterBtnToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- // Initialize all views BEFORE using them
loginBtn = findViewById(R.id.Loginbtn);
registerBtn = findViewById(R.id.Registerbtn);
logoutBtn = findViewById(R.id.btnLogout);
newPostBtn = findViewById(R.id.newPostBtn);
recyclerView = findViewById(R.id.postsRecyclerView);
+ burgerMenuBtn = findViewById(R.id.burgerMenuBtn);
+ dropdownMenu = findViewById(R.id.dropdownMenu);
+ menuLogout = findViewById(R.id.menuLogout);
+ menuNewPost = findViewById(R.id.menuNewPost);
+ filterBtnToolbar = findViewById(R.id.filterBtnToolbar);
- // RecyclerView setup
recyclerView.setLayoutManager(new LinearLayoutManager(this));
- postsAdapter = new PostsAdapter(new ArrayList<>());
+
+ boolean isLoggedIn = getSharedPreferences("MyAppPrefs", MODE_PRIVATE)
+ .getBoolean("isLoggedIn", false);
+
+ postsAdapter = new PostsAdapter(this, new ArrayList<>(), isLoggedIn);
recyclerView.setAdapter(postsAdapter);
setupButtons();
+ setupDropdownMenu();
updateAuthUI();
loadPublications();
+ setupFilterButton();
}
private void setupButtons() {
- if (loginBtn != null) {
- loginBtn.setOnClickListener(v ->
- startActivity(new Intent(MainActivity.this, LoginActivity.class))
- );
- }
+ loginBtn.setOnClickListener(v ->
+ startActivity(new Intent(this, LoginActivity.class)));
- if (registerBtn != null) {
- registerBtn.setOnClickListener(v ->
- startActivity(new Intent(MainActivity.this, RegisterActivity.class))
- );
- }
+ registerBtn.setOnClickListener(v ->
+ startActivity(new Intent(this, RegisterActivity.class)));
- if (logoutBtn != null) {
- logoutBtn.setOnClickListener(v -> {
- getSharedPreferences("MyAppPrefs", MODE_PRIVATE).edit().clear().apply();
- updateAuthUI();
- Toast.makeText(MainActivity.this, "Logged out", Toast.LENGTH_SHORT).show();
- });
- }
+ logoutBtn.setOnClickListener(v -> {
+ getSharedPreferences("MyAppPrefs", MODE_PRIVATE)
+ .edit().clear().apply();
+ updateAuthUI();
+ Toast.makeText(this, "Logged out", Toast.LENGTH_SHORT).show();
+ });
- if (newPostBtn != null) {
- newPostBtn.setOnClickListener(v ->
- startActivityForResult(
- new Intent(MainActivity.this, NewPostActivity.class), 100)
- );
- }
+ newPostBtn.setOnClickListener(v ->
+ startActivityForResult(
+ new Intent(this, NewPostActivity.class), 100));
}
+ private void setupDropdownMenu() {
+ burgerMenuBtn.setOnClickListener(v ->
+ dropdownMenu.setVisibility(
+ dropdownMenu.getVisibility() == View.VISIBLE
+ ? View.GONE : View.VISIBLE));
+ menuLogout.setOnClickListener(v -> {
+ getSharedPreferences("MyAppPrefs", MODE_PRIVATE)
+ .edit().clear().apply();
+ updateAuthUI();
+ dropdownMenu.setVisibility(View.GONE);
+ });
+
+ menuNewPost.setOnClickListener(v -> {
+ startActivityForResult(
+ new Intent(this, NewPostActivity.class), 100);
+ dropdownMenu.setVisibility(View.GONE);
+ });
+ }
+ //Sortiranje i filtriranje.
+ private void setupFilterButton() {
+
+ filterBtnToolbar.setOnClickListener(v -> {
+
+ String[] options = {
+ "Show all posts",
+ "Only pinned",
+ "Not pinned",
+ "Only images",
+ "Only videos",
+ "Sort by newest",
+ "Sort by rating"
+ };
+ new androidx.appcompat.app.AlertDialog.Builder(this)
+ .setTitle("Filter & Sort")
+ .setItems(options, (dialog, which) -> {
+
+ switch (which) {
+
+ case 0: //All.
+ postsAdapter.filterPinned(null);
+ postsAdapter.filterContentType(null);
+ break;
+
+ case 1: //Pinned.
+ postsAdapter.filterPinned(true);
+ break;
+
+ case 2: //Not pinned.
+ postsAdapter.filterPinned(false);
+ break;
+
+ case 3: // images
+ postsAdapter.filterContentType("image");
+ break;
+
+ case 4: // videos
+ postsAdapter.filterContentType("video");
+ break;
+
+ case 5: // newest
+ postsAdapter.sortBy(PostsAdapter.SortMode.TIME);
+ break;
+
+ case 6: // rating
+ postsAdapter.sortBy(PostsAdapter.SortMode.RATING);
+ break;
+ }
+ })
+ .show();
+ });
+ }
private void updateAuthUI() {
boolean isLoggedIn = getSharedPreferences("MyAppPrefs", MODE_PRIVATE)
.getBoolean("isLoggedIn", false);
- if (loginBtn != null) loginBtn.setVisibility(isLoggedIn ? View.GONE : View.VISIBLE);
- if (registerBtn != null) registerBtn.setVisibility(isLoggedIn ? View.GONE : View.VISIBLE);
- if (logoutBtn != null) logoutBtn.setVisibility(isLoggedIn ? View.VISIBLE : View.GONE);
- if (newPostBtn != null) newPostBtn.setVisibility(isLoggedIn ? View.VISIBLE : View.GONE);
+ loginBtn.setVisibility(isLoggedIn ? View.GONE : View.VISIBLE);
+ registerBtn.setVisibility(isLoggedIn ? View.GONE : View.VISIBLE);
+ logoutBtn.setVisibility(isLoggedIn ? View.VISIBLE : View.GONE);
+ newPostBtn.setVisibility(isLoggedIn ? View.VISIBLE : View.GONE);
}
-
- private void loadPublications() {
- ApiService apiService = ApiClient.getClient().create(ApiService.class);
-
+ public void loadPublications() {
+ ApiService api = ApiClient.getClient().create(ApiService.class);
String token = getSharedPreferences("MyAppPrefs", MODE_PRIVATE)
.getString("authToken", null);
String authHeader = token != null ? "Token " + token : null;
-
- Call call = apiService.getPublications(authHeader);
- call.enqueue(new Callback() {
+ api.getPublications(authHeader).enqueue(new Callback() {
@Override
- public void onResponse(Call call, Response response) {
+ public void onResponse(Call call,
+ Response response) {
if (response.isSuccessful() && response.body() != null) {
- List posts = response.body().results;
- Toast.makeText(MainActivity.this,
- "Posts loaded: " + posts.size(),
- Toast.LENGTH_SHORT).show();
- postsAdapter.updateData(posts);
+ List publications = response.body().results;
+
+ // Pass the fully populated list to adapter
+ postsAdapter.setPosts(publications);
} else {
Toast.makeText(MainActivity.this,
- "Failed to load publications: " + response.code(), Toast.LENGTH_SHORT).show();
+ "Failed to load posts",
+ Toast.LENGTH_SHORT).show();
}
}
-
@Override
public void onFailure(Call call, Throwable t) {
Toast.makeText(MainActivity.this,
- "Failed to load publications: " + t.getMessage(), Toast.LENGTH_SHORT).show();
+ "Network error",
+ Toast.LENGTH_SHORT).show();
}
});
}
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == 100 && resultCode == RESULT_OK) {
- loadPublications(); // reload feed after new post
- }
- }
-
@Override
protected void onResume() {
super.onResume();
updateAuthUI();
loadPublications();
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/gallery/RegisterActivity.java b/app/src/main/java/com/example/gallery/RegisterActivity.java
index 5b8b555..009b21d 100644
--- a/app/src/main/java/com/example/gallery/RegisterActivity.java
+++ b/app/src/main/java/com/example/gallery/RegisterActivity.java
@@ -5,6 +5,7 @@ import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
@@ -22,6 +23,7 @@ public class RegisterActivity extends AppCompatActivity {
EditText username, email, ime, prezime, index, password;
Button btnRegister;
+ TextView loginTV;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -35,9 +37,14 @@ public class RegisterActivity extends AppCompatActivity {
index = findViewById(R.id.indexEditText);
password = findViewById(R.id.passwordEditText);
btnRegister = findViewById(R.id.btnRegister);
+ loginTV = findViewById(R.id.loginTV);
Toast.makeText(this, "RegisterActivity loaded", Toast.LENGTH_SHORT).show();
+loginTV.setOnClickListener(v -> {
+ startActivity(new Intent(RegisterActivity.this, LoginActivity.class));
+ });
+
btnRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -48,9 +55,7 @@ public class RegisterActivity extends AppCompatActivity {
String s = index.getText().toString().trim();
String p = password.getText().toString().trim();
- // ---------------------------
- // ✅ FRONTEND VALIDATIONS
- // ---------------------------
+
if (u.isEmpty() || u.length() > 150) {
username.setError("Username must be 1-150 characters");
return;
diff --git a/app/src/main/java/com/example/gallery/VideoPlayerActivity.java b/app/src/main/java/com/example/gallery/VideoPlayerActivity.java
new file mode 100644
index 0000000..e00d3a8
--- /dev/null
+++ b/app/src/main/java/com/example/gallery/VideoPlayerActivity.java
@@ -0,0 +1,32 @@
+package com.example.gallery;
+
+import android.net.Uri;
+import android.os.Bundle;
+import android.widget.MediaController;
+import android.widget.VideoView;
+import androidx.appcompat.app.AppCompatActivity;
+
+public class VideoPlayerActivity extends AppCompatActivity {
+
+ private VideoView videoView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_video_player);
+
+ videoView = findViewById(R.id.videoView);
+
+ String videoUrl = getIntent().getStringExtra("videoUrl");
+ if (videoUrl != null) {
+ Uri videoUri = Uri.parse(videoUrl);
+ videoView.setVideoURI(videoUri);
+
+ MediaController mediaController = new MediaController(this);
+ mediaController.setAnchorView(videoView);
+ videoView.setMediaController(mediaController);
+
+ videoView.start();
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/gallery/adapters/PostsAdapter.java b/app/src/main/java/com/example/gallery/adapters/PostsAdapter.java
index a3a72ac..92dca03 100644
--- a/app/src/main/java/com/example/gallery/adapters/PostsAdapter.java
+++ b/app/src/main/java/com/example/gallery/adapters/PostsAdapter.java
@@ -1,104 +1,244 @@
package com.example.gallery.adapters;
-import android.util.Log;
+import android.content.Context;
+import android.content.Intent;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.RatingBar;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.gallery.R;
+import com.example.gallery.VideoPlayerActivity;
import com.example.gallery.api.ApiClient;
+import com.example.gallery.api.ApiService;
import com.example.gallery.models.Publication;
+import com.example.gallery.models.RatingRequest;
+import com.example.gallery.models.RatingResponse;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
public class PostsAdapter extends RecyclerView.Adapter {
- private final List publications;
+ private final Context context;
+ private final ApiService apiService;
+ private final boolean isLoggedIn;
- public PostsAdapter(List publications) {
- this.publications = publications;
+ private final List allPosts = new ArrayList<>();
+ private final List visiblePosts = new ArrayList<>();
+
+ private Boolean pinnedFilter = null;
+ private String contentTypeFilter = null;
+ private SortMode sortMode = SortMode.TIME;
+
+ public enum SortMode { TIME, RATING }
+
+ public PostsAdapter(Context context, List posts, boolean isLoggedIn) {
+ this.context = context;
+ this.isLoggedIn = isLoggedIn;
+ this.apiService = ApiClient.getClient().create(ApiService.class);
+ setPosts(posts);
}
- public void updateData(List newData) {
- publications.clear();
- publications.addAll(newData);
+ public void setPosts(List posts) {
+ allPosts.clear();
+ if (posts != null) allPosts.addAll(posts);
+ applyFilters();
+ }
+
+ public void filterPinned(Boolean pinned) {
+ pinnedFilter = pinned;
+ applyFilters();
+ }
+
+ public void filterContentType(String type) {
+ contentTypeFilter = type;
+ applyFilters();
+ }
+
+ public void sortBy(SortMode mode) {
+ sortMode = mode;
+ applyFilters();
+ }
+
+ private void applyFilters() {
+ visiblePosts.clear();
+
+ for (Publication p : allPosts) {
+ if (pinnedFilter != null && p.is_pinned != pinnedFilter) continue;
+ if (contentTypeFilter != null &&
+ !contentTypeFilter.equalsIgnoreCase(p.content_type)) continue;
+ visiblePosts.add(p);
+ }
+
+ if (sortMode == SortMode.TIME) {
+ Collections.sort(visiblePosts,
+ (a, b) -> b.time_created.compareTo(a.time_created));
+ } else {
+ Collections.sort(visiblePosts,
+ (a, b) -> Float.compare(b.average_score, a.average_score));
+ }
+
notifyDataSetChanged();
}
@NonNull
@Override
public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext())
+ View view = LayoutInflater.from(context)
.inflate(R.layout.item_post, parent, false);
return new PostViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull PostViewHolder holder, int position) {
- Publication pub = publications.get(position);
- holder.descriptionTV.setText(
- pub.description != null ? pub.description : ""
- );
+ Publication post = visiblePosts.get(position);
+ // ---------- USER SCORE ----------
+ int userScore = post.user_score != null ? post.user_score : 0;
+ holder.userRatingBar.setOnRatingBarChangeListener(null);
+ holder.userRatingBar.setRating(userScore);
+ holder.yourRating.setText(String.valueOf(userScore));
+
+ // ---------- TEXT ----------
+ holder.postDescription.setText(post.description == null ? "" : post.description);
+ holder.postUserName.setText(post.username == null ? "User" : post.username);
holder.mediaTypeBadge.setText(
- pub.content_type != null ? pub.content_type.toUpperCase() : ""
- );
+ post.content_type == null ? "MEDIA" : post.content_type.toUpperCase());
- String mediaPath = null;
+ // ---------- MEDIA ----------
+ if ("video".equalsIgnoreCase(post.content_type)) {
+ Glide.with(context).asBitmap().load(post.video).into(holder.postImage);
+ holder.videoPlayButton.setVisibility(View.VISIBLE);
- if ("image".equals(pub.content_type)) {
- mediaPath = pub.image;
- } else if ("video".equals(pub.content_type)) {
- mediaPath = pub.video;
- }
-
- if (mediaPath != null && !mediaPath.isEmpty()) {
-
- String fullUrl;
-
- // ✅ CRITICAL FIX: handle both relative & absolute URLs
- if (mediaPath.startsWith("http")) {
- fullUrl = mediaPath;
- } else {
- fullUrl = ApiClient.BASE_URL + mediaPath;
- }
-
- Log.d("POST_IMAGE_URL", fullUrl);
-
- Glide.with(holder.itemView.getContext())
- .load(fullUrl)
- .placeholder(R.drawable.image_placeholder_background)
- .error(R.drawable.image_placeholder_background)
- .centerCrop()
- .into(holder.mediaIV);
+ View.OnClickListener play = v -> {
+ Intent i = new Intent(context, VideoPlayerActivity.class);
+ i.putExtra("videoUrl", post.video);
+ context.startActivity(i);
+ };
+ holder.postImage.setOnClickListener(play);
+ holder.videoPlayButton.setOnClickListener(play);
} else {
- holder.mediaIV.setImageResource(R.drawable.image_placeholder_background);
+ holder.videoPlayButton.setVisibility(View.GONE);
+ Glide.with(context).load(post.image).into(holder.postImage);
}
+
+ // ---------- AVERAGE ----------
+ holder.txtAverageValue.setText(String.format("%.1f", post.average_score));
+ holder.averageRatingBar.setRating(post.average_score);
+
+ if (!isLoggedIn) {
+ holder.userRatingBar.setIsIndicator(true);
+ return;
+ }
+
+ holder.userRatingBar.setIsIndicator(false);
+
+ holder.userRatingBar.setOnRatingBarChangeListener((bar, rating, fromUser) -> {
+ if (!fromUser) return;
+
+ int score = Math.round(rating);
+ int adapterPosition = holder.getAdapterPosition();
+ if (adapterPosition == RecyclerView.NO_POSITION) return;
+
+ Publication current = visiblePosts.get(adapterPosition);
+
+ String token = context.getSharedPreferences("MyAppPrefs", Context.MODE_PRIVATE)
+ .getString("authToken", null);
+
+ apiService.ratePublication("Token " + token,
+ new RatingRequest(current.pk, score))
+ .enqueue(new Callback() {
+ @Override
+ public void onResponse(@NonNull Call call,
+ @NonNull Response response) {
+
+ if (!response.isSuccessful() || response.body() == null) return;
+
+ RatingResponse body = response.body();
+
+ current.user_score = score;
+
+ if (body.average_score != null) {
+ current.average_score = body.average_score;
+ }
+
+ for (Publication p : allPosts) {
+ if (p.pk == current.pk) {
+ p.user_score = current.user_score;
+ p.average_score = current.average_score;
+ break;
+ }
+ }
+
+ holder.yourRating.setText(String.valueOf(current.user_score));
+ holder.averageRatingBar.setRating(current.average_score);
+ holder.txtAverageValue.setText(
+ String.format("%.1f", current.average_score)
+ );
+
+ notifyItemChanged(adapterPosition);
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call,
+ @NonNull Throwable t) {
+ Toast.makeText(context,
+ "Network error", Toast.LENGTH_SHORT).show();
+ }
+ });
+ });
}
@Override
public int getItemCount() {
- return publications.size();
+ return visiblePosts.size();
}
static class PostViewHolder extends RecyclerView.ViewHolder {
- TextView descriptionTV;
- TextView mediaTypeBadge;
- ImageView mediaIV;
- public PostViewHolder(@NonNull View itemView) {
+ RatingBar averageRatingBar, userRatingBar;
+ TextView txtAverageValue, yourRating, postDescription, postUserName, mediaTypeBadge;
+ ImageView postImage, videoPlayButton;
+
+ PostViewHolder(View itemView) {
super(itemView);
- descriptionTV = itemView.findViewById(R.id.postDescription);
- mediaIV = itemView.findViewById(R.id.postImage);
+
+ averageRatingBar = itemView.findViewById(R.id.averageRatingBar);
+ userRatingBar = itemView.findViewById(R.id.userRatingBar);
+ txtAverageValue = itemView.findViewById(R.id.averageRatingText);
+ yourRating = itemView.findViewById(R.id.yourRating);
+ postDescription = itemView.findViewById(R.id.postDescription);
+ postUserName = itemView.findViewById(R.id.postUserName);
mediaTypeBadge = itemView.findViewById(R.id.mediaTypeBadge);
+ postImage = itemView.findViewById(R.id.postImage);
+
+ FrameLayout parent = (FrameLayout) postImage.getParent();
+ videoPlayButton = new ImageView(itemView.getContext());
+ videoPlayButton.setImageResource(R.drawable.ic_launcher_background);
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT
+ );
+ params.gravity = Gravity.CENTER;
+ parent.addView(videoPlayButton);
+ videoPlayButton.setVisibility(View.GONE);
}
}
}
diff --git a/app/src/main/java/com/example/gallery/api/ApiService.java b/app/src/main/java/com/example/gallery/api/ApiService.java
index e63aaca..b0e34ed 100644
--- a/app/src/main/java/com/example/gallery/api/ApiService.java
+++ b/app/src/main/java/com/example/gallery/api/ApiService.java
@@ -5,6 +5,8 @@ import com.example.gallery.models.LoginRequest;
import com.example.gallery.models.LoginResponse;
import com.example.gallery.models.Publication;
import com.example.gallery.models.PublicationListResponse;
+import com.example.gallery.models.RatingRequest;
+import com.example.gallery.models.RatingResponse;
import com.example.gallery.models.RegisterRequest;
import com.example.gallery.models.RegisterResponse;
@@ -17,11 +19,11 @@ import retrofit2.http.Header;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
+import retrofit2.http.Path;
public interface ApiService {
- /* ===================== AUTH ===================== */
-
+ /* ===================== AUTHENTICATION ===================== */
@POST("api/auth/register/")
Call register(@Body RegisterRequest request);
@@ -32,12 +34,10 @@ public interface ApiService {
Call getMe(@Header("Authorization") String token);
/* ================== PUBLICATIONS ================= */
-
@GET("api/publications/")
Call getPublications(
@Header("Authorization") String token
);
-
@Multipart
@POST("api/publications/")
Call createPublication(
@@ -48,4 +48,10 @@ public interface ApiService {
@Part("category") RequestBody category,
@Part MultipartBody.Part file
);
+ /* ================== RATING ================= */
+ @POST("api/publications/rate/")
+ Call ratePublication(
+ @Header("Authorization") String authHeader,
+ @Body RatingRequest request
+ );
}
diff --git a/app/src/main/java/com/example/gallery/models/Publication.java b/app/src/main/java/com/example/gallery/models/Publication.java
index c21537e..94f5036 100644
--- a/app/src/main/java/com/example/gallery/models/Publication.java
+++ b/app/src/main/java/com/example/gallery/models/Publication.java
@@ -1,11 +1,20 @@
package com.example.gallery.models;
-public class Publication {
+import java.io.Serializable;
+
+public class Publication implements Serializable {
+
public int pk;
+ public String description;
public String image;
public String video;
public String content_type;
- public String description;
+
+ public boolean is_pinned;
+
+ public Float average_score;
+ public Integer user_score;
+
+ public String username;
public String time_created;
}
-
diff --git a/app/src/main/java/com/example/gallery/models/Rating.java b/app/src/main/java/com/example/gallery/models/Rating.java
new file mode 100644
index 0000000..47e6e0c
--- /dev/null
+++ b/app/src/main/java/com/example/gallery/models/Rating.java
@@ -0,0 +1,6 @@
+package com.example.gallery.models;
+
+public class Rating {
+ public float score;
+ public String user;
+}
diff --git a/app/src/main/java/com/example/gallery/models/RatingRequest.java b/app/src/main/java/com/example/gallery/models/RatingRequest.java
new file mode 100644
index 0000000..3f1fa0e
--- /dev/null
+++ b/app/src/main/java/com/example/gallery/models/RatingRequest.java
@@ -0,0 +1,10 @@
+package com.example.gallery.models;
+public class RatingRequest {
+ public int publication;
+ public float score;
+
+ public RatingRequest(int publication, float score) {
+ this.publication = publication;
+ this.score = score;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/gallery/models/RatingResponse.java b/app/src/main/java/com/example/gallery/models/RatingResponse.java
new file mode 100644
index 0000000..48c51e7
--- /dev/null
+++ b/app/src/main/java/com/example/gallery/models/RatingResponse.java
@@ -0,0 +1,7 @@
+package com.example.gallery.models;
+
+public class RatingResponse {
+ public String detail;
+ public Float average_score;
+ public Float user_score;
+}
diff --git a/app/src/main/res/layout/activity_video_player.xml b/app/src/main/res/layout/activity_video_player.xml
new file mode 100644
index 0000000..33bd9f2
--- /dev/null
+++ b/app/src/main/res/layout/activity_video_player.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_post.xml b/app/src/main/res/layout/item_post.xml
index 653e2c3..2708203 100644
--- a/app/src/main/res/layout/item_post.xml
+++ b/app/src/main/res/layout/item_post.xml
@@ -40,7 +40,6 @@
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#011f4b"/>
-
@@ -57,7 +56,6 @@
android:paddingEnd="14dp"
android:paddingTop="6dp"
android:paddingBottom="6dp"/>
-
@@ -67,6 +65,9 @@
android:background="#b3cde0"
android:layout_marginBottom="16dp"/>
+
-
-
+
+ android:orientation="horizontal">
+ android:secondaryProgressTint="#aaccee"/>
-
+ android:textStyle="bold"/>
-
+ android:orientation="horizontal"
+ android:layout_marginBottom="12dp"
+ android:gravity="center_vertical">
+
+
+
+
+
-
+ android:progressTint="#005b96"
+ android:secondaryProgressTint="#aaccee"/>
-
\ No newline at end of file
+