From 2ad647da608918ccae2a8def9f36e14353fab4d8 Mon Sep 17 00:00:00 2001 From: Docile-Alligator <25734209+Docile-Alligator@users.noreply.github.com> Date: Thu, 12 Jun 2025 21:55:52 -0400 Subject: [PATCH] Save and restore comment draft in CommentActivity. --- app/build.gradle | 1 + .../RedditDataRoomDatabase.java | 3 ++ .../activities/CommentActivity.java | 45 ++++++++++++++++--- .../comment/CommentDraftDao.kt | 20 +++++++++ .../repositories/CommentActivityRepository.kt | 17 +++++++ .../viewmodels/CommentActivityViewModel.kt | 41 +++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 7 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/comment/CommentDraftDao.kt create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/repositories/CommentActivityRepository.kt create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/viewmodels/CommentActivityViewModel.kt diff --git a/app/build.gradle b/app/build.gradle index b9d8e041..63b592db 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,6 +86,7 @@ dependencies { implementation "androidx.room:room-runtime:$roomVersion" annotationProcessor "androidx.room:room-compiler:$roomVersion" implementation "androidx.room:room-guava:$roomVersion" + implementation "androidx.room:room-ktx:$roomVersion" implementation 'androidx.viewpager2:viewpager2:1.1.0' implementation 'androidx.work:work-runtime:2.9.0' implementation 'com.google.android.material:material:1.12.0' diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java index 69a752a1..ac5f22ec 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java @@ -14,6 +14,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase; import ml.docilealligator.infinityforreddit.account.Account; import ml.docilealligator.infinityforreddit.account.AccountDao; import ml.docilealligator.infinityforreddit.comment.CommentDraft; +import ml.docilealligator.infinityforreddit.comment.CommentDraftDao; import ml.docilealligator.infinityforreddit.commentfilter.CommentFilter; import ml.docilealligator.infinityforreddit.commentfilter.CommentFilterDao; import ml.docilealligator.infinityforreddit.commentfilter.CommentFilterUsage; @@ -88,6 +89,8 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { public abstract CommentFilterUsageDao commentFilterUsageDao(); + public abstract CommentDraftDao commentDraftDao(); + private static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLiteDatabase database) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java index 260ff43c..5bdb2798 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java @@ -1,6 +1,7 @@ package ml.docilealligator.infinityforreddit.activities; import android.content.ActivityNotFoundException; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -11,6 +12,7 @@ import android.os.Handler; import android.provider.MediaStore; import android.text.Spanned; import android.text.TextUtils; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -21,6 +23,8 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.FileProvider; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestManager; @@ -50,6 +54,7 @@ import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import kotlin.Unit; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; @@ -60,6 +65,7 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.CopyTextBottomS import ml.docilealligator.infinityforreddit.bottomsheetfragments.GiphyGifInfoBottomSheetFragment; import ml.docilealligator.infinityforreddit.bottomsheetfragments.UploadedImagesBottomSheetFragment; import ml.docilealligator.infinityforreddit.comment.Comment; +import ml.docilealligator.infinityforreddit.comment.CommentDraft; import ml.docilealligator.infinityforreddit.comment.SendComment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; @@ -73,11 +79,13 @@ import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry; import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin; import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils; import ml.docilealligator.infinityforreddit.network.AnyAccountAccessTokenAuthenticator; +import ml.docilealligator.infinityforreddit.repositories.CommentActivityRepository; import ml.docilealligator.infinityforreddit.thing.GiphyGif; import ml.docilealligator.infinityforreddit.thing.UploadedImage; import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.utils.Utils; +import ml.docilealligator.infinityforreddit.viewmodels.CommentActivityViewModel; import okhttp3.ConnectionPool; import okhttp3.OkHttpClient; import retrofit2.Retrofit; @@ -135,6 +143,7 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA private ArrayList uploadedImages = new ArrayList<>(); private GiphyGif giphyGif; private Menu mMenu; + public CommentActivityViewModel commentActivityViewModel; /** * Post or comment body text color @@ -332,6 +341,22 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA Utils.showKeyboard(this, new Handler(), binding.commentCommentEditText); Giphy.INSTANCE.configure(this, APIUtils.GIPHY_GIF_API_KEY); + + commentActivityViewModel = new ViewModelProvider( + this, + CommentActivityViewModel.Companion.provideFactory(new CommentActivityRepository(mRedditDataRoomDatabase.commentDraftDao())) + ).get(CommentActivityViewModel.class); + + if (savedInstanceState == null) { + commentActivityViewModel.getCommentDraft(parentFullname).observe(this, new Observer() { + @Override + public void onChanged(CommentDraft commentDraft) { + if (commentDraft != null) { + binding.commentCommentEditText.setText(commentDraft.getContent()); + } + } + }); + } } private void loadCurrentAccount() { @@ -497,13 +522,23 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA } } - private void promptAlertDialog(int titleResId, int messageResId) { + private void promptAlertDialog(int titleResId, int messageResId, boolean canSaveDraft) { new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) .setTitle(titleResId) .setMessage(messageResId) .setPositiveButton(R.string.yes, (dialogInterface, i) - -> finish()) - .setNegativeButton(R.string.no, null) + -> { + if (canSaveDraft) { + commentActivityViewModel.saveCommentDraft(parentFullname, binding.commentCommentEditText.getText().toString(), () -> { + finish(); + return Unit.INSTANCE; + }); + } else { + finish(); + } + }) + .setNegativeButton(R.string.no, (dialog, which) -> finish()) + .setNeutralButton(R.string.cancel, null) .show(); } @@ -530,12 +565,12 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA @Override public void onBackPressed() { if (isSubmitting) { - promptAlertDialog(R.string.exit_when_submit, R.string.exit_when_edit_comment_detail); + promptAlertDialog(R.string.exit_when_submit, R.string.exit_when_edit_comment_detail, false); } else { if (binding.commentCommentEditText.getText().toString().equals("")) { finish(); } else { - promptAlertDialog(R.string.discard, R.string.discard_detail); + promptAlertDialog(R.string.save_comment_draft, R.string.save_comment_draft_detail, true); } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/comment/CommentDraftDao.kt b/app/src/main/java/ml/docilealligator/infinityforreddit/comment/CommentDraftDao.kt new file mode 100644 index 00000000..5ec2154f --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/comment/CommentDraftDao.kt @@ -0,0 +1,20 @@ +package ml.docilealligator.infinityforreddit.comment + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query + +@Dao +interface CommentDraftDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(commentDraft: CommentDraft) + + @Delete + fun delete(commentDraft: CommentDraft) + + @Query("SELECT * FROM comment_draft WHERE parent_full_name = :parentFullName") + fun getCommentDraftLiveData(parentFullName: String): LiveData +} \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/repositories/CommentActivityRepository.kt b/app/src/main/java/ml/docilealligator/infinityforreddit/repositories/CommentActivityRepository.kt new file mode 100644 index 00000000..515e85ea --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/repositories/CommentActivityRepository.kt @@ -0,0 +1,17 @@ +package ml.docilealligator.infinityforreddit.repositories + +import androidx.lifecycle.LiveData +import ml.docilealligator.infinityforreddit.comment.CommentDraft +import ml.docilealligator.infinityforreddit.comment.CommentDraftDao + +class CommentActivityRepository( + private val commentDraftDao: CommentDraftDao +) { + public fun getCommentDraft(parentFullname: String): LiveData { + return commentDraftDao.getCommentDraftLiveData(parentFullname) + } + + public suspend fun saveCommentDraft(parentFullname: String, content: String) { + commentDraftDao.insert(CommentDraft(parentFullname, content, System.currentTimeMillis())) + } +} \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/viewmodels/CommentActivityViewModel.kt b/app/src/main/java/ml/docilealligator/infinityforreddit/viewmodels/CommentActivityViewModel.kt new file mode 100644 index 00000000..a5a57245 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/viewmodels/CommentActivityViewModel.kt @@ -0,0 +1,41 @@ +package ml.docilealligator.infinityforreddit.viewmodels + +import androidx.lifecycle.LiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.CreationExtras +import kotlinx.coroutines.launch +import ml.docilealligator.infinityforreddit.comment.CommentDraft +import ml.docilealligator.infinityforreddit.repositories.CommentActivityRepository + +class CommentActivityViewModel( + private val commentActivityRepository: CommentActivityRepository +): ViewModel() { + fun getCommentDraft(parentFullname: String): LiveData { + return commentActivityRepository.getCommentDraft(parentFullname) + } + + fun saveCommentDraft(parentFullname: String, content: String, onSaved: () -> Unit) { + viewModelScope.launch { + commentActivityRepository.saveCommentDraft(parentFullname, content) + onSaved() + } + } + + companion object { + fun provideFactory(commentActivityRepository: CommentActivityRepository) : ViewModelProvider.Factory { + return object: ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun create( + modelClass: Class, + extras: CreationExtras + ): T { + return CommentActivityViewModel( + commentActivityRepository, + ) as T + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 78861d61..9948d7c7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -672,6 +672,8 @@ Yes No Discard + Save comment draft? + Your draft will be saved. No data received No image path received