Skip to content

Commit

Permalink
v1.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
debojit16mitra committed Dec 14, 2024
1 parent 0d66cb0 commit 2912ebe
Show file tree
Hide file tree
Showing 14 changed files with 490 additions and 86 deletions.
4 changes: 2 additions & 2 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ android {
minSdk = 30
targetSdk = 35
versionCode = 1
versionName = "1.0.1"
versionName = "1.0.2"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
106 changes: 59 additions & 47 deletions app/src/main/java/com/bunny/ml/smartchef/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import static com.bunny.ml.smartchef.activities.SettingsActivity.UPDATE_CHECK_INTERVAL;

import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
Expand All @@ -21,6 +21,7 @@
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.work.ExistingPeriodicWorkPolicy;

import com.airbnb.lottie.LottieAnimationView;
import com.bunny.ml.smartchef.activities.AIChatActivity;
Expand All @@ -33,12 +34,12 @@
import com.bunny.ml.smartchef.firebase.ProfileManager;
import com.bunny.ml.smartchef.models.Chat;
import com.bunny.ml.smartchef.utils.AppUpdater;
import com.bunny.ml.smartchef.utils.CookingMotivationManager;
import com.bunny.ml.smartchef.utils.CustomAlertDialog;
import com.bunny.ml.smartchef.utils.PermissionManager;
import com.bunny.ml.smartchef.utils.SwipeCallback;
import com.bunny.ml.smartchef.utils.UpdateWorker;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.FirebaseFirestoreException;

import java.util.Objects;
Expand All @@ -47,12 +48,10 @@

public class MainActivity extends AppCompatActivity implements ProfileActivity.MainActivityCallback {

private static final String TAG = "MainActivity";
private static final int NOTIFICATION_PERMISSION_CODE = 100;
private FirebaseAuth auth;
private ProfileManager profileManager;
private CircleImageView profile_image;
private TextView hello_user_textview;
private LinearLayout layout_try_model_btn, layout_chat_btn;
private LottieAnimationView animationView;
private TextView history_textview;
private RecyclerView chatHistoryRecyclerView;
Expand All @@ -67,8 +66,6 @@ protected void onCreate(Bundle savedInstanceState) {
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);

auth = FirebaseAuth.getInstance();

// Initialize views and base functionality
initializeViews();
setProfileImage();
Expand All @@ -83,7 +80,7 @@ protected void onCreate(Bundle savedInstanceState) {
// Check if opened from notification
if (getIntent().getBooleanExtra("show_update", false)) {
appUpdater.checkForUpdatesFromNotification();
} else {
} else {
// Always check for updates when app opens
appUpdater.checkForUpdates(false);
}
Expand All @@ -100,10 +97,10 @@ protected void onCreate(Bundle savedInstanceState) {
private void initializeViews() {
profile_image = findViewById(R.id.profile_image);
profileManager = ProfileManager.getInstance(MainActivity.this);
hello_user_textview = findViewById(R.id.hello_user_textview);
TextView hello_user_textview = findViewById(R.id.hello_user_textview);
history_textview = findViewById(R.id.history_textview);
layout_try_model_btn = findViewById(R.id.layout_try_model_btn);
layout_chat_btn = findViewById(R.id.layout_chat_btn);
LinearLayout layout_try_model_btn = findViewById(R.id.layout_try_model_btn);
LinearLayout layout_chat_btn = findViewById(R.id.layout_chat_btn);
animationView = findViewById(R.id.animationView);

profile_image.setOnClickListener(view12 -> setUpBottomSheet());
Expand All @@ -120,22 +117,16 @@ private void initializeViews() {

setupSwipeDelete();

layout_try_model_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, TryModelActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
}
layout_try_model_btn.setOnClickListener(view -> {
Intent intent = new Intent(MainActivity.this, TryModelActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
});

layout_chat_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AIChatActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
}
layout_chat_btn.setOnClickListener(view -> {
Intent intent = new Intent(MainActivity.this, AIChatActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
});

new Handler(Looper.getMainLooper()).postDelayed(() -> animationView.playAnimation(), 500);
Expand All @@ -151,24 +142,23 @@ private void checkNotificationPermission() {
}

private void showNotificationPermissionDialog() {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
new CustomAlertDialog(MainActivity.this)
.setDialogTitle("Notification Permission")
.setMessage("SmartChef needs notification permission for two reasons:\n\n1. For sending cooking motivations.\n2. To keep you updated with the latest app versions.\n\nWould you like to enable notifications?")
.setPositiveButton("Enable", () -> {
PermissionManager.setNotificationPermissionAsked(this, true);
requestNotificationPermission();
})
.setNegativeButton("No Thanks", () -> {
PermissionManager.setNotificationPermissionAsked(this, true);
PermissionManager.setNotificationPermissionDenied(this, true);
PermissionManager.setAutoUpdateEnabled(MainActivity.this, false);
// Cancel any scheduled update checks
androidx.work.WorkManager.getInstance(MainActivity.this)
.cancelUniqueWork("update_check");
})
.show();
}, 500);
new Handler(Looper.getMainLooper()).postDelayed(() -> new CustomAlertDialog(MainActivity.this)
.setDialogTitle("Notification Permission")
.setMessage("SmartChef needs notification permission for two reasons:\n\n1. For sending cooking motivations.\n2. To keep you updated with the latest app versions.\n\nWould you like to enable notifications?")
.setPositiveButton("Enable", () -> {
PermissionManager.setNotificationPermissionAsked(this, true);
requestNotificationPermission();
})
.setNegativeButton("No Thanks", () -> {
turnOffMotivation();
PermissionManager.setNotificationPermissionAsked(this, true);
PermissionManager.setNotificationPermissionDenied(this, true);
PermissionManager.setAutoUpdateEnabled(MainActivity.this, false);
// Cancel any scheduled update checks
androidx.work.WorkManager.getInstance(MainActivity.this)
.cancelUniqueWork("update_check");
})
.show(), 500);
}

private void requestNotificationPermission() {
Expand All @@ -187,19 +177,35 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
if (requestCode == NOTIFICATION_PERMISSION_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
if (profileManager.getCookingMotivation()){
CookingMotivationManager cookingMotivationManager = new CookingMotivationManager(this);
cookingMotivationManager.scheduleDailyMotivation();
}
PermissionManager.setNotificationPermissionDenied(this, false);
PermissionManager.setAutoUpdateEnabled(this, true);
if (appUpdater != null) {
appUpdater.checkForUpdates(false);
}
} else {
// Permission denied
turnOffMotivation();
PermissionManager.setNotificationPermissionDenied(this, true);
PermissionManager.setAutoUpdateEnabled(this, false);
}
}
}

private void turnOffMotivation() {
if (profileManager.getCookingMotivation()){
profileManager.setCookingMotivation(false, new ProfileManager.BaseCallback() {
@Override
public void onFailure(String error) {
Log.e(TAG, error);
}
});
}
}

private void scheduleUpdateChecks() {
androidx.work.PeriodicWorkRequest updateWorkRequest =
new androidx.work.PeriodicWorkRequest.Builder(
Expand All @@ -212,7 +218,7 @@ private void scheduleUpdateChecks() {
androidx.work.WorkManager.getInstance(this)
.enqueueUniquePeriodicWork(
"update_check",
androidx.work.ExistingPeriodicWorkPolicy.REPLACE,
ExistingPeriodicWorkPolicy.REPLACE,
updateWorkRequest
);
}
Expand Down Expand Up @@ -325,7 +331,7 @@ public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction)
// Delete chat
CustomAlertDialog dialog = new CustomAlertDialog(MainActivity.this);
dialog.setIcon(Objects.requireNonNull(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_round_delete)))
.setIconTint(ContextCompat.getColor(MainActivity.this, R.color.delete))
.setIconTint(ContextCompat.getColor(MainActivity.this, R.color.mode_inverse))
.setMessage("Are you sure you want to delete this chat?")
.setPositiveButton("Yes", () -> {
chatRepository.deleteChat(currentChat.getDocumentId());
Expand All @@ -339,8 +345,6 @@ public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction)
.show();

} else if (direction == ItemTouchHelper.RIGHT) {
boolean newStarredState = !currentChat.isStarred();

if (currentChat.isStarred()) {
// Show confirmation dialog for unstarring
CustomAlertDialog dialog = new CustomAlertDialog(MainActivity.this);
Expand Down Expand Up @@ -400,6 +404,14 @@ protected boolean shouldUseAlternateIcon(RecyclerView.ViewHolder viewHolder) {
new ItemTouchHelper(swipeCallback).attachToRecyclerView(chatHistoryRecyclerView);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == AppUpdater.REQUEST_INSTALL_PACKAGES) {
appUpdater.onActivityResult(requestCode, resultCode);
}
}

@Override
protected void onDestroy() {
super.onDestroy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class AIChatActivity extends AppCompatActivity implements ChatWebSocket.C
private FirebaseAuth firebaseAuth;
private boolean hasOldMessages = false;
private boolean isServerConnected = false;
private boolean isMessagePending = false;

//pagination
private DocumentSnapshot lastVisibleMessage;
Expand Down Expand Up @@ -102,8 +103,6 @@ private void initializeViews() {

backBtn.setOnClickListener(v -> handleBack());

sendButton.setOnClickListener(v -> sendMessage());

setupSuggestionAdapter();

// Add keyboard visibility listener
Expand All @@ -122,14 +121,16 @@ private void initializeViews() {
});

sendButton.setOnClickListener(v -> {
String messageText = messageInput.getText().toString().trim();
if (TextUtils.isEmpty(messageText)) return;
if (isServerConnected) {
sendMessage();
sendMessage(messageText);
} else {
// Attempt to reconnect
if (chatWebSocket != null) {
chatWebSocket.connect();
}

isMessagePending = true;
// Show toast to inform user
Toast.makeText(this, "Connecting to server...", Toast.LENGTH_SHORT).show();
return;
Expand All @@ -148,10 +149,11 @@ private void setupSuggestionAdapter() {
messageInput.setText(suggestion);

if (isServerConnected) {
sendMessage();
sendMessage(suggestion);
layoutSuggestions.setVisibility(View.GONE);
} else {
// Show connection toast and attempt to reconnect
isMessagePending = true;
Toast.makeText(this, getString(R.string.connecting_to_server), Toast.LENGTH_SHORT).show();
if (chatWebSocket != null) {
chatWebSocket.connect();
Expand Down Expand Up @@ -315,9 +317,7 @@ private void loadMessages() {
}
}

private void sendMessage() {
String messageText = messageInput.getText().toString().trim();
if (TextUtils.isEmpty(messageText)) return;
private void sendMessage(String messageText) {

if (layout_greet_user.getVisibility() == View.VISIBLE) {
layout_greet_user.setVisibility(View.GONE);
Expand All @@ -337,7 +337,14 @@ private void sendMessage() {
);

chatAdapter.addMessage(userMessage);
scrollToBottom();
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
chatAdapter.showTyping(true);
scrollToBottom();
}
}, 400);


// Save message to Firebase
chatRepository.saveMessage(userMessage);
Expand All @@ -351,12 +358,20 @@ private void sendMessage() {
// WebSocket callback implementations
@Override
public void onConnected() {
if (isMessagePending){
String messageText = messageInput.getText().toString().trim();
if (!TextUtils.isEmpty(messageText)){
sendMessage(messageText);
}
isMessagePending = false;
}
isServerConnected = true;
}

@Override
public void onMessageReceived(String content) {
runOnUiThread(() -> {
chatAdapter.showTyping(false);
if (currentAiMessage == null) {
currentAiMessage = new ChatMessage(
content,
Expand Down Expand Up @@ -401,6 +416,7 @@ public void onError(String error) {
Log.e(TAG, error);

runOnUiThread(() -> {
chatAdapter.showTyping(false);
// Only show error if user was actively trying to send a message
if (!messageInput.isEnabled()) {
messageInput.setEnabled(true);
Expand Down
Loading

0 comments on commit 2912ebe

Please sign in to comment.