diff --git a/ProbnaSlika.png b/ProbnaSlika.png new file mode 100644 index 0000000..02be370 Binary files /dev/null and b/ProbnaSlika.png differ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index da8f44d..e61290a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -40,6 +40,8 @@ dependencies { implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") + implementation ("com.github.bumptech.glide:glide:4.16.0") + annotationProcessor ("com.github.bumptech.glide:compiler:4.16.0") testImplementation(libs.junit) androidTestImplementation(libs.ext.junit) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce85111..663a763 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,7 +16,8 @@ + tools:ignore="Instantiatable" + android:windowSoftInputMode="adjustResize|stateHidden"/> diff --git a/app/src/main/java/com/example/gallery/LoginActivity.java b/app/src/main/java/com/example/gallery/LoginActivity.java index 9f5cdd1..5c34323 100644 --- a/app/src/main/java/com/example/gallery/LoginActivity.java +++ b/app/src/main/java/com/example/gallery/LoginActivity.java @@ -4,6 +4,7 @@ import android.content.Intent; import android.os.Bundle; import android.widget.Button; import android.widget.EditText; +import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; @@ -12,7 +13,6 @@ import com.example.gallery.api.ApiClient; import com.example.gallery.api.ApiService; import com.example.gallery.models.LoginRequest; import com.example.gallery.models.LoginResponse; -import com.example.gallery.UserResponse; import retrofit2.Call; import retrofit2.Callback; @@ -20,84 +20,60 @@ import retrofit2.Response; public class LoginActivity extends AppCompatActivity { - EditText usernameEdit, passwordEdit; - Button loginBtn; + private EditText usernameEdit, passwordEdit; + private Button loginBtn; + private TextView registerTV; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); - // Updated ids from your XML usernameEdit = findViewById(R.id.usernameTxt); passwordEdit = findViewById(R.id.userpasswordTxt); loginBtn = findViewById(R.id.btnLogin); + registerTV = findViewById(R.id.registerTV); - loginBtn.setOnClickListener(v -> { - String username = usernameEdit.getText().toString().trim(); - String password = passwordEdit.getText().toString().trim(); + loginBtn.setOnClickListener(v -> login()); + } - if (username.isEmpty() || password.isEmpty()) { - Toast.makeText(LoginActivity.this, "All fields are required", Toast.LENGTH_SHORT).show(); - return; + private void login() { + String username = usernameEdit.getText().toString().trim(); + String password = passwordEdit.getText().toString().trim(); + + if (username.isEmpty() || password.isEmpty()) { + Toast.makeText(this, "All fields are required", Toast.LENGTH_SHORT).show(); + return; + } + + ApiService apiService = ApiClient.getClient().create(ApiService.class); + LoginRequest request = new LoginRequest(username, password); + + apiService.login(request).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful() && response.body() != null) { + + // 🔑 STORE RAW TOKEN ONLY + getSharedPreferences("MyAppPrefs", MODE_PRIVATE) + .edit() + .putString("authToken", response.body().getToken()) + .putBoolean("isLoggedIn", true) + .apply(); + + 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(); + } } - ApiService apiService = ApiClient.getClient().create(ApiService.class); - LoginRequest request = new LoginRequest(username, password); - - // 🔹 Login API call - apiService.login(request).enqueue(new Callback() { - @Override - public void onResponse(Call call, Response response) { - if (response.isSuccessful() && response.body() != null) { - String token = "Token " + response.body().getToken(); - - // 🔹 Save token & login state in SharedPreferences - getSharedPreferences("MyAppPrefs", MODE_PRIVATE) - .edit() - .putString("authToken", token) - .putBoolean("isLoggedIn", true) - .apply(); - - Toast.makeText(LoginActivity.this, "Login successful", Toast.LENGTH_SHORT).show(); - - // 🔹 Verify token with /api/auth/me/ - apiService.getMe(token).enqueue(new Callback() { - @Override - public void onResponse(Call call, Response response) { - if (response.isSuccessful() && response.body() != null) { - Toast.makeText(LoginActivity.this, - "Welcome " + response.body().getUsername(), - Toast.LENGTH_SHORT).show(); - - // Go to MainActivity - startActivity(new Intent(LoginActivity.this, MainActivity.class)); - finish(); - } else { - Toast.makeText(LoginActivity.this, - "Failed to verify user", - Toast.LENGTH_SHORT).show(); - } - } - - @Override - public void onFailure(Call call, Throwable t) { - Toast.makeText(LoginActivity.this, - "Verification error: " + t.getMessage(), - Toast.LENGTH_SHORT).show(); - } - }); - - } else { - Toast.makeText(LoginActivity.this, "Login failed", Toast.LENGTH_SHORT).show(); - } - } - - @Override - public void onFailure(Call call, Throwable t) { - Toast.makeText(LoginActivity.this, "Server error: " + t.getMessage(), Toast.LENGTH_SHORT).show(); - } - }); + @Override + public void onFailure(Call call, Throwable t) { + 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 3611ac7..63610ae 100644 --- a/app/src/main/java/com/example/gallery/MainActivity.java +++ b/app/src/main/java/com/example/gallery/MainActivity.java @@ -4,62 +4,135 @@ import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; +import android.widget.Toast; -import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.gallery.adapters.PostsAdapter; +import com.example.gallery.api.ApiClient; +import com.example.gallery.api.ApiService; +import com.example.gallery.models.Publication; +import com.example.gallery.models.PublicationListResponse; + +import java.util.ArrayList; +import java.util.List; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; public class MainActivity extends AppCompatActivity { - Button loginBtn, registerBtn, logoutBtn; + private Button loginBtn, registerBtn, logoutBtn, newPostBtn; + private RecyclerView recyclerView; + private PostsAdapter postsAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - EdgeToEdge.enable(this); 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); - // Button listeners - loginBtn.setOnClickListener(v -> { - Intent intent = new Intent(MainActivity.this, LoginActivity.class); - startActivity(intent); - }); + // RecyclerView setup + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + postsAdapter = new PostsAdapter(new ArrayList<>()); + recyclerView.setAdapter(postsAdapter); - registerBtn.setOnClickListener(v -> { - Intent intent = new Intent(MainActivity.this, RegisterActivity.class); - startActivity(intent); - }); + setupButtons(); + updateAuthUI(); + loadPublications(); + } - // Check login state from SharedPreferences + private void setupButtons() { + if (loginBtn != null) { + loginBtn.setOnClickListener(v -> + startActivity(new Intent(MainActivity.this, LoginActivity.class)) + ); + } + + if (registerBtn != null) { + registerBtn.setOnClickListener(v -> + startActivity(new Intent(MainActivity.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(); + }); + } + + if (newPostBtn != null) { + newPostBtn.setOnClickListener(v -> + startActivityForResult( + new Intent(MainActivity.this, NewPostActivity.class), 100) + ); + } + } + + private void updateAuthUI() { boolean isLoggedIn = getSharedPreferences("MyAppPrefs", MODE_PRIVATE) .getBoolean("isLoggedIn", false); - if (isLoggedIn) { - // User is logged in → hide login/register, show logout - loginBtn.setVisibility(View.GONE); - registerBtn.setVisibility(View.GONE); - logoutBtn.setVisibility(View.VISIBLE); - } else { - // User not logged in → show login/register, hide logout - loginBtn.setVisibility(View.VISIBLE); - registerBtn.setVisibility(View.VISIBLE); - logoutBtn.setVisibility(View.GONE); - } + 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); + } - // Logout button - logoutBtn.setOnClickListener(v -> { - // Clear token and login state - getSharedPreferences("MyAppPrefs", MODE_PRIVATE) - .edit() - .remove("authToken") // remove saved token - .putBoolean("isLoggedIn", false) // set logged out - .apply(); + private void loadPublications() { + ApiService apiService = ApiClient.getClient().create(ApiService.class); - // Refresh activity to reflect state change - recreate(); + 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() { + @Override + 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); + } else { + Toast.makeText(MainActivity.this, + "Failed to load publications: " + response.code(), 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(); + } }); } -} \ No newline at end of file + + @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(); + } +} diff --git a/app/src/main/java/com/example/gallery/NewPostActivity.java b/app/src/main/java/com/example/gallery/NewPostActivity.java index d7f3cd5..a9fd17d 100644 --- a/app/src/main/java/com/example/gallery/NewPostActivity.java +++ b/app/src/main/java/com/example/gallery/NewPostActivity.java @@ -1,4 +1,175 @@ package com.example.gallery; -public class NewPostActivity { +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.widget.*; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; + +import com.example.gallery.api.ApiClient; +import com.example.gallery.api.ApiService; +import com.example.gallery.models.FileUtils; +import com.example.gallery.models.Publication; + +import java.io.File; + +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class NewPostActivity extends AppCompatActivity { + + private EditText descriptionET; + private RadioGroup mediaTypeRG; + private Spinner categorySpinner; + private Button selectMediaBtn, submitBtn, cancelBtn; + private TextView selectedFileTV; + private ImageView previewIV; + + private Uri selectedFileUri; + private String mediaType = "image"; + private int selectedCategory = 1; // default + + private final ActivityResultLauncher picker = + registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK && result.getData() != null) { + selectedFileUri = result.getData().getData(); + selectedFileTV.setText(FileUtils.getFileName(this, selectedFileUri)); + + if (mediaType.equals("image")) { + previewIV.setImageURI(selectedFileUri); + previewIV.setVisibility(ImageView.VISIBLE); + } else { + previewIV.setVisibility(ImageView.GONE); + } + } + }); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_post); + + descriptionET = findViewById(R.id.descriptionET); + mediaTypeRG = findViewById(R.id.mediaTypeRG); + selectMediaBtn = findViewById(R.id.selectMediaBtn); + submitBtn = findViewById(R.id.submitBtn); + cancelBtn = findViewById(R.id.cancelBtn); + selectedFileTV = findViewById(R.id.selectedFileTV); + previewIV = findViewById(R.id.previewIV); + + // Spinner for categories + categorySpinner = findViewById(R.id.categorySpinner); + ArrayAdapter adapter = new ArrayAdapter<>(this, + android.R.layout.simple_spinner_item, + new String[]{"nature","city","landscape","animals","people"}); // categories from API + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + categorySpinner.setAdapter(adapter); + categorySpinner.setSelection(0); + categorySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override public void onItemSelected(AdapterView parent, android.view.View view, int position, long id) { + selectedCategory = new int[]{1,2,3,4,5}[position]; + } + @Override public void onNothingSelected(AdapterView parent) {} + }); + + mediaTypeRG.setOnCheckedChangeListener((g, id) -> mediaType = (id == R.id.photoRB) ? "image" : "video"); + + selectMediaBtn.setOnClickListener(v -> { + Intent i = new Intent(Intent.ACTION_PICK); + i.setType(mediaType.equals("image") ? "image/*" : "video/*"); + picker.launch(i); + }); + + submitBtn.setOnClickListener(v -> uploadPost()); + cancelBtn.setOnClickListener(v -> confirmCancel()); + } + + @Override + public void onBackPressed() { confirmCancel(); } + + private void confirmCancel() { + new AlertDialog.Builder(this) + .setTitle("Cancel post") + .setMessage("Are you sure?") + .setPositiveButton("Yes", (d, w) -> super.onBackPressed()) + .setNegativeButton("No", null) + .show(); + } + + private void uploadPost() { + if (selectedFileUri == null || descriptionET.getText().toString().trim().isEmpty()) { + Toast.makeText(this, "Select file and enter description", Toast.LENGTH_SHORT).show(); + return; + } + + String rawToken = getSharedPreferences("MyAppPrefs", MODE_PRIVATE) + .getString("authToken", null); + + if (rawToken == null) { + Toast.makeText(this, "Login required", Toast.LENGTH_SHORT).show(); + return; + } + + String authHeader = "Token " + rawToken; + + try { + File file = FileUtils.getFileFromUri(this, selectedFileUri); + MediaType mediaTypeFile = MediaType.parse(getContentResolver().getType(selectedFileUri)); + RequestBody fileBody = RequestBody.create(mediaTypeFile, file); + + MultipartBody.Part filePart = MultipartBody.Part.createFormData( + mediaType.equals("image") ? "image" : "video", + file.getName(), + fileBody + ); + + RequestBody desc = RequestBody.create(MediaType.parse("text/plain"), + descriptionET.getText().toString().trim()); + + RequestBody ct = RequestBody.create(MediaType.parse("text/plain"), mediaType); + RequestBody status = RequestBody.create(MediaType.parse("text/plain"), "public"); + RequestBody category = RequestBody.create(MediaType.parse("text/plain"), String.valueOf(selectedCategory)); + + ApiService apiService = ApiClient.getClient().create(ApiService.class); + + Call call = apiService.createPublication( + authHeader, + desc, + ct, + status, + category, + filePart + ); + + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful() && response.body() != null) { + Toast.makeText(NewPostActivity.this, "Post created 🎉", Toast.LENGTH_SHORT).show(); + setResult(RESULT_OK); // signal MainActivity to refresh + finish(); + } else { + Toast.makeText(NewPostActivity.this, + "Error " + response.code() + ": check fields", Toast.LENGTH_LONG).show(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + Toast.makeText(NewPostActivity.this, t.getMessage(), Toast.LENGTH_LONG).show(); + } + }); + + } catch (Exception e) { + Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); + } + } } 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 7662b4d..a3a72ac 100644 --- a/app/src/main/java/com/example/gallery/adapters/PostsAdapter.java +++ b/app/src/main/java/com/example/gallery/adapters/PostsAdapter.java @@ -1,4 +1,104 @@ package com.example.gallery.adapters; -public class PostsAdapter { +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.example.gallery.R; +import com.example.gallery.api.ApiClient; +import com.example.gallery.models.Publication; + +import java.util.List; + +public class PostsAdapter extends RecyclerView.Adapter { + + private final List publications; + + public PostsAdapter(List publications) { + this.publications = publications; + } + + public void updateData(List newData) { + publications.clear(); + publications.addAll(newData); + notifyDataSetChanged(); + } + + @NonNull + @Override + public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .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 : "" + ); + + holder.mediaTypeBadge.setText( + pub.content_type != null ? pub.content_type.toUpperCase() : "" + ); + + String mediaPath = null; + + 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); + + } else { + holder.mediaIV.setImageResource(R.drawable.image_placeholder_background); + } + } + + @Override + public int getItemCount() { + return publications.size(); + } + + static class PostViewHolder extends RecyclerView.ViewHolder { + TextView descriptionTV; + TextView mediaTypeBadge; + ImageView mediaIV; + + public PostViewHolder(@NonNull View itemView) { + super(itemView); + descriptionTV = itemView.findViewById(R.id.postDescription); + mediaIV = itemView.findViewById(R.id.postImage); + mediaTypeBadge = itemView.findViewById(R.id.mediaTypeBadge); + } + } } diff --git a/app/src/main/java/com/example/gallery/api/ApiClient.java b/app/src/main/java/com/example/gallery/api/ApiClient.java index a66e98f..772ea2f 100644 --- a/app/src/main/java/com/example/gallery/api/ApiClient.java +++ b/app/src/main/java/com/example/gallery/api/ApiClient.java @@ -5,10 +5,12 @@ import retrofit2.converter.gson.GsonConverterFactory; public class ApiClient { - private static final String BASE_URL = "https://gallery.steve-dekart.xyz/"; + // Base URL of your backend + public static final String BASE_URL = "https://gallery.steve-dekart.xyz/"; private static Retrofit retrofit; + // Returns singleton Retrofit client public static Retrofit getClient() { if (retrofit == null) { retrofit = new Retrofit.Builder() @@ -18,4 +20,4 @@ public class ApiClient { } return retrofit; } -} +} \ No newline at end of file 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 64ef21b..e63aaca 100644 --- a/app/src/main/java/com/example/gallery/api/ApiService.java +++ b/app/src/main/java/com/example/gallery/api/ApiService.java @@ -3,17 +3,25 @@ package com.example.gallery.api; import com.example.gallery.UserResponse; 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.RegisterRequest; import com.example.gallery.models.RegisterResponse; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Multipart; import retrofit2.http.POST; +import retrofit2.http.Part; public interface ApiService { + /* ===================== AUTH ===================== */ + @POST("api/auth/register/") Call register(@Body RegisterRequest request); @@ -22,4 +30,22 @@ public interface ApiService { @GET("api/auth/me/") Call getMe(@Header("Authorization") String token); -} \ No newline at end of file + + /* ================== PUBLICATIONS ================= */ + + @GET("api/publications/") + Call getPublications( + @Header("Authorization") String token + ); + + @Multipart + @POST("api/publications/") + Call createPublication( + @Header("Authorization") String authHeader, + @Part("description") RequestBody description, + @Part("content_type") RequestBody contentType, + @Part("status") RequestBody status, + @Part("category") RequestBody category, + @Part MultipartBody.Part file + ); +} diff --git a/app/src/main/java/com/example/gallery/models/FileUtils.java b/app/src/main/java/com/example/gallery/models/FileUtils.java index 6b3b203..24c7fcd 100644 --- a/app/src/main/java/com/example/gallery/models/FileUtils.java +++ b/app/src/main/java/com/example/gallery/models/FileUtils.java @@ -1,4 +1,48 @@ package com.example.gallery.models; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.provider.OpenableColumns; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; + public class FileUtils { -} + + public static File getFileFromUri(Context context, Uri uri) throws Exception { + String fileName = getFileName(context, uri); + File tempFile = new File(context.getCacheDir(), fileName); + tempFile.createNewFile(); + + try (InputStream inputStream = context.getContentResolver().openInputStream(uri); + FileOutputStream outputStream = new FileOutputStream(tempFile)) { + + byte[] buf = new byte[1024]; + int len; + while ((len = inputStream.read(buf)) > 0) { + outputStream.write(buf, 0, len); + } + } + return tempFile; + } + + public static String getFileName(Context context, Uri uri) { + String result = null; + if ("content".equals(uri.getScheme())) { + try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) { + if (cursor != null && cursor.moveToFirst()) { + int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); + if (nameIndex >= 0) { + result = cursor.getString(nameIndex); + } + } + } + } + if (result == null) { + result = uri.getLastPathSegment(); + } + return result; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/gallery/models/Post.java b/app/src/main/java/com/example/gallery/models/Post.java index 2b21c98..6789a65 100644 --- a/app/src/main/java/com/example/gallery/models/Post.java +++ b/app/src/main/java/com/example/gallery/models/Post.java @@ -1,4 +1,16 @@ package com.example.gallery.models; public class Post { + private int id; + private String description; + private String media_type; + private String file_url; + private String username; + + // getters + public int getId() { return id; } + public String getDescription() { return description; } + public String getMedia_type() { return media_type; } + public String getFile_url() { return file_url; } + public String getUsername() { return username; } } diff --git a/app/src/main/java/com/example/gallery/models/PostResponse.java b/app/src/main/java/com/example/gallery/models/PostResponse.java index bb06647..c1e0654 100644 --- a/app/src/main/java/com/example/gallery/models/PostResponse.java +++ b/app/src/main/java/com/example/gallery/models/PostResponse.java @@ -1,4 +1,11 @@ package com.example.gallery.models; public class PostResponse { -} + private boolean success; + private String message; + private Post post; + + public boolean isSuccess() { return success; } + public String getMessage() { return message; } + public Post getPost() { return post; } +} \ No newline at end of file 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 7d851c8..c21537e 100644 --- a/app/src/main/java/com/example/gallery/models/Publication.java +++ b/app/src/main/java/com/example/gallery/models/Publication.java @@ -1,4 +1,11 @@ package com.example.gallery.models; public class Publication { + public int pk; + public String image; + public String video; + public String content_type; + public String description; + public String time_created; } + diff --git a/app/src/main/java/com/example/gallery/models/PublicationListResponse.java b/app/src/main/java/com/example/gallery/models/PublicationListResponse.java index 984b9ed..ce8b512 100644 --- a/app/src/main/java/com/example/gallery/models/PublicationListResponse.java +++ b/app/src/main/java/com/example/gallery/models/PublicationListResponse.java @@ -1,4 +1,11 @@ package com.example.gallery.models; +import java.util.List; + public class PublicationListResponse { + public int count; + public int page; + public int page_size; + public int total_pages; + public List results; } diff --git a/app/src/main/java/com/example/gallery/models/PublicationRequest.java b/app/src/main/java/com/example/gallery/models/PublicationRequest.java index 96d7e83..868c740 100644 --- a/app/src/main/java/com/example/gallery/models/PublicationRequest.java +++ b/app/src/main/java/com/example/gallery/models/PublicationRequest.java @@ -1,4 +1,9 @@ package com.example.gallery.models; public class PublicationRequest { + public String image; + public String video; + public String content_type; + public String description; + public int category; } diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 5f796f2..ff46383 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -97,14 +97,14 @@ + android:focusable="true" + android:gravity="center" + android:text="Don't have an account? Register" + android:textColor="#03396c" + android:textSize="14sp" /> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 2ba8472..aeb59f2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,6 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +