Save and restore comment draft in CommentActivity.

This commit is contained in:
Docile-Alligator
2025-06-12 21:55:52 -04:00
parent 38ed861c0d
commit 2ad647da60
7 changed files with 124 additions and 5 deletions

View File

@ -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'

View File

@ -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) {

View File

@ -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<UploadedImage> 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<CommentDraft>() {
@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);
}
}
}

View File

@ -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<CommentDraft>
}

View File

@ -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<CommentDraft> {
return commentDraftDao.getCommentDraftLiveData(parentFullname)
}
public suspend fun saveCommentDraft(parentFullname: String, content: String) {
commentDraftDao.insert(CommentDraft(parentFullname, content, System.currentTimeMillis()))
}
}

View File

@ -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<CommentDraft> {
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 <T : ViewModel> create(
modelClass: Class<T>,
extras: CreationExtras
): T {
return CommentActivityViewModel(
commentActivityRepository,
) as T
}
}
}
}
}

View File

@ -672,6 +672,8 @@
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="discard_dialog_button">Discard</string>
<string name="save_comment_draft">Save comment draft?</string>
<string name="save_comment_draft_detail">Your draft will be saved.</string>
<string name="no_data_received">No data received</string>
<string name="no_image_path_received">No image path received</string>