Post editing functionality

Post editing is now functional! You can now edit the post you've made.

Closes #30
This commit is contained in:
Balazs Toldi 2023-08-01 09:32:34 +02:00
parent 907f6e92c3
commit 3a66a79f49
No known key found for this signature in database
GPG Key ID: 6C7D440036F99D58
4 changed files with 179 additions and 35 deletions

View File

@ -3,16 +3,20 @@ package eu.toldi.infinityforlemmy.activities;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -22,18 +26,22 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.FileProvider; import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.concurrent.ExecutionException;
import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import javax.inject.Inject; import javax.inject.Inject;
@ -47,14 +55,16 @@ import eu.toldi.infinityforlemmy.RetrofitHolder;
import eu.toldi.infinityforlemmy.UploadImageEnabledActivity; import eu.toldi.infinityforlemmy.UploadImageEnabledActivity;
import eu.toldi.infinityforlemmy.UploadedImage; import eu.toldi.infinityforlemmy.UploadedImage;
import eu.toldi.infinityforlemmy.adapters.MarkdownBottomBarRecyclerViewAdapter; import eu.toldi.infinityforlemmy.adapters.MarkdownBottomBarRecyclerViewAdapter;
import eu.toldi.infinityforlemmy.apis.RedditAPI; import eu.toldi.infinityforlemmy.apis.LemmyAPI;
import eu.toldi.infinityforlemmy.bottomsheetfragments.UploadedImagesBottomSheetFragment; import eu.toldi.infinityforlemmy.bottomsheetfragments.UploadedImagesBottomSheetFragment;
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper; import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
import eu.toldi.infinityforlemmy.customviews.LinearLayoutManagerBugFixed; import eu.toldi.infinityforlemmy.customviews.LinearLayoutManagerBugFixed;
import eu.toldi.infinityforlemmy.customviews.slidr.Slidr; import eu.toldi.infinityforlemmy.customviews.slidr.Slidr;
import eu.toldi.infinityforlemmy.dto.EditPostDTO;
import eu.toldi.infinityforlemmy.events.SwitchAccountEvent; import eu.toldi.infinityforlemmy.events.SwitchAccountEvent;
import eu.toldi.infinityforlemmy.utils.APIUtils; import eu.toldi.infinityforlemmy.post.Post;
import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils; import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils;
import eu.toldi.infinityforlemmy.utils.UploadImageUtils;
import eu.toldi.infinityforlemmy.utils.Utils; import eu.toldi.infinityforlemmy.utils.Utils;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -63,16 +73,19 @@ import retrofit2.Retrofit;
public class EditPostActivity extends BaseActivity implements UploadImageEnabledActivity { public class EditPostActivity extends BaseActivity implements UploadImageEnabledActivity {
public static final String EXTRA_TITLE = "ET"; public static final String EXTRA_DATA = "ED";
public static final String EXTRA_CONTENT = "EC";
public static final String EXTRA_FULLNAME = "EF";
private static final int UPLOAD_IMAGE_REQUEST_CODE = 1;
private static final int PICK_IMAGE_REQUEST_CODE = 100; private static final int PICK_IMAGE_REQUEST_CODE = 100;
private static final int CAPTURE_IMAGE_REQUEST_CODE = 200; private static final int CAPTURE_IMAGE_REQUEST_CODE = 200;
private static final int MARKDOWN_PREVIEW_REQUEST_CODE = 300; private static final int MARKDOWN_PREVIEW_REQUEST_CODE = 300;
private static final String UPLOADED_IMAGES_STATE = "UIS"; private static final String UPLOADED_IMAGES_STATE = "UIS";
private static final String picturePattern = "https:\\/\\/[^\\/]+\\/pictrs\\/image\\/([a-f\\d-]+\\.jpeg)";
@BindView(R.id.coordinator_layout_edit_post_activity) @BindView(R.id.coordinator_layout_edit_post_activity)
CoordinatorLayout coordinatorLayout; CoordinatorLayout coordinatorLayout;
@BindView(R.id.appbar_layout_edit_post_activity) @BindView(R.id.appbar_layout_edit_post_activity)
@ -87,6 +100,15 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
EditText contentEditText; EditText contentEditText;
@BindView(R.id.markdown_bottom_bar_recycler_view_edit_post_activity) @BindView(R.id.markdown_bottom_bar_recycler_view_edit_post_activity)
RecyclerView markdownBottomBarRecyclerView; RecyclerView markdownBottomBarRecyclerView;
@BindView(R.id.post_link_edit_text_post_edit_activity)
EditText linkEditText;
@BindView(R.id.upload_image_button_post_edit_activity)
MaterialButton uploadImageButton;
@BindView(R.id.image_view_post_edit_activity)
ImageView imageView;
@Inject @Inject
@Named("no_oauth") @Named("no_oauth")
RetrofitHolder mRetrofit; RetrofitHolder mRetrofit;
@ -103,13 +125,16 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
CustomThemeWrapper mCustomThemeWrapper; CustomThemeWrapper mCustomThemeWrapper;
@Inject @Inject
Executor mExecutor; Executor mExecutor;
private String mFullName; private Post mPost;
private String mAccessToken; private String mAccessToken;
private String mPostContent;
private boolean isSubmitting = false; private boolean isSubmitting = false;
private Uri capturedImageUri; private Uri capturedImageUri;
private ArrayList<UploadedImage> uploadedImages = new ArrayList<>(); private ArrayList<UploadedImage> uploadedImages = new ArrayList<>();
private RequestManager mGlide;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
((Infinity) getApplication()).getAppComponent().inject(this); ((Infinity) getApplication()).getAppComponent().inject(this);
@ -137,11 +162,49 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mFullName = getIntent().getStringExtra(EXTRA_FULLNAME); mPost = getIntent().getParcelableExtra(EXTRA_DATA);
if (mPost == null) {
finish();
}
mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null); mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null);
titleEditText.setText(getIntent().getStringExtra(EXTRA_TITLE)); titleEditText.setText(mPost.getTitle());
mPostContent = getIntent().getStringExtra(EXTRA_CONTENT); contentEditText.setText(mPost.getSelfText());
contentEditText.setText(mPostContent); linkEditText.setText(mPost.getUrl());
mGlide = Glide.with(this);
if (mPost.getUrl().matches(picturePattern)) {
loadImage();
}
linkEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (charSequence.toString().matches(picturePattern)) {
loadImage();
} else {
uploadImageButton.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
uploadImageButton.setOnClickListener(view -> {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, getString(R.string.select_from_gallery)), UPLOAD_IMAGE_REQUEST_CODE);
});
if (savedInstanceState != null) { if (savedInstanceState != null) {
uploadedImages = savedInstanceState.getParcelableArrayList(UPLOADED_IMAGES_STATE); uploadedImages = savedInstanceState.getParcelableArrayList(UPLOADED_IMAGES_STATE);
@ -192,7 +255,10 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
titleEditText.setTextColor(mCustomThemeWrapper.getPostTitleColor()); titleEditText.setTextColor(mCustomThemeWrapper.getPostTitleColor());
divider.setBackgroundColor(mCustomThemeWrapper.getPostTitleColor()); divider.setBackgroundColor(mCustomThemeWrapper.getPostTitleColor());
contentEditText.setTextColor(mCustomThemeWrapper.getPostContentColor()); contentEditText.setTextColor(mCustomThemeWrapper.getPostContentColor());
linkEditText.setTextColor(mCustomThemeWrapper.getPostContentColor());
uploadImageButton.setTextColor(mCustomThemeWrapper.getButtonTextColor());
uploadImageButton.setBackgroundColor(mCustomThemeWrapper.getColorPrimaryLightTheme());
if (titleTypeface != null) { if (titleTypeface != null) {
titleEditText.setTypeface(titleTypeface); titleEditText.setTypeface(titleTypeface);
} }
@ -201,6 +267,12 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
} }
} }
private void loadImage() {
uploadImageButton.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
mGlide.load(mPost.getUrl()).into(imageView);
}
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
@ -236,21 +308,19 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
isSubmitting = true; isSubmitting = true;
Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_SHORT).show(); Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_SHORT).show();
mRetrofit.getRetrofit().create(LemmyAPI.class).postUpdate(new EditPostDTO(mPost.getId(), titleEditText.getText().toString(), linkEditText.getText().toString(), contentEditText.getText().toString(), mPost.isNSFW(), null, mAccessToken))
Map<String, String> params = new HashMap<>();
params.put(APIUtils.THING_ID_KEY, mFullName);
params.put(APIUtils.TEXT_KEY, contentEditText.getText().toString());
mRetrofit.getRetrofit().create(RedditAPI.class)
.editPostOrComment(APIUtils.getOAuthHeader(mAccessToken), params)
.enqueue(new Callback<String>() { .enqueue(new Callback<String>() {
@Override @Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
isSubmitting = false; isSubmitting = false;
if (response.isSuccessful()) {
Toast.makeText(EditPostActivity.this, R.string.edit_success, Toast.LENGTH_SHORT).show(); Toast.makeText(EditPostActivity.this, R.string.edit_success, Toast.LENGTH_SHORT).show();
Intent returnIntent = new Intent(); Intent returnIntent = new Intent();
setResult(RESULT_OK, returnIntent); setResult(RESULT_OK, returnIntent);
finish(); finish();
} else {
Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show();
}
} }
@Override @Override
@ -274,6 +344,39 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
} }
Utils.uploadImageToReddit(this, mExecutor, mRetrofit, Utils.uploadImageToReddit(this, mExecutor, mRetrofit,
mAccessToken, contentEditText, coordinatorLayout, data.getData(), uploadedImages); mAccessToken, contentEditText, coordinatorLayout, data.getData(), uploadedImages);
} else if (requestCode == UPLOAD_IMAGE_REQUEST_CODE) {
if (data == null) {
Snackbar.make(coordinatorLayout, R.string.error_getting_image, Snackbar.LENGTH_SHORT).show();
return;
}
Toast.makeText(this, R.string.uploading_image, Toast.LENGTH_SHORT).show();
Handler handler = new Handler();
Uri imageUri = data.getData();
mExecutor.execute(() -> {
try {
Bitmap bitmap = Glide.with(this).asBitmap().load(imageUri).submit().get();
String imageUrlOrError = UploadImageUtils.uploadImage(mRetrofit, mAccessToken, bitmap);
handler.post(() -> {
if (imageUrlOrError != null && !imageUrlOrError.startsWith("Error: ")) {
String fileName = Utils.getFileName(this, imageUri);
if (fileName == null) {
fileName = imageUrlOrError;
}
mPost.setUrl(imageUrlOrError);
linkEditText.setText(imageUrlOrError);
Snackbar.make(coordinatorLayout, R.string.upload_image_success, Snackbar.LENGTH_LONG).show();
} else {
Toast.makeText(this, R.string.upload_image_failed, Toast.LENGTH_LONG).show();
}
});
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
handler.post(() -> Toast.makeText(this, R.string.get_image_bitmap_failed, Toast.LENGTH_LONG).show());
} catch (XmlPullParserException | JSONException | IOException e) {
e.printStackTrace();
handler.post(() -> Toast.makeText(this, R.string.error_processing_image, Toast.LENGTH_LONG).show());
}
});
} else if (requestCode == CAPTURE_IMAGE_REQUEST_CODE) { } else if (requestCode == CAPTURE_IMAGE_REQUEST_CODE) {
Utils.uploadImageToReddit(this, mExecutor, mRetrofit, Utils.uploadImageToReddit(this, mExecutor, mRetrofit,
mAccessToken, contentEditText, coordinatorLayout, capturedImageUri, uploadedImages); mAccessToken, contentEditText, coordinatorLayout, capturedImageUri, uploadedImages);
@ -281,6 +384,7 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
editPost(); editPost();
} }
} }
} }
@Override @Override
@ -304,7 +408,7 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled
if (isSubmitting) { if (isSubmitting) {
promptAlertDialog(R.string.exit_when_submit, R.string.exit_when_edit_post_detail); promptAlertDialog(R.string.exit_when_submit, R.string.exit_when_edit_post_detail);
} else { } else {
if (contentEditText.getText().toString().equals(mPostContent)) { if (contentEditText.getText().toString().equals(mPost.getSelfText())) {
finish(); finish();
} else { } else {
promptAlertDialog(R.string.discard, R.string.discard_detail); promptAlertDialog(R.string.discard, R.string.discard_detail);

View File

@ -691,10 +691,8 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
hideItem.setVisible(false); hideItem.setVisible(false);
} }
if (mPost.getAuthor().equals(mAccountName)) { if (mPost.getAuthorNamePrefixed().equals(mAccountQualifiedName)) {
if (mPost.getPostType() == Post.TEXT_TYPE) {
mMenu.findItem(R.id.action_edit_view_post_detail_fragment).setVisible(true); mMenu.findItem(R.id.action_edit_view_post_detail_fragment).setVisible(true);
}
mMenu.findItem(R.id.action_delete_view_post_detail_fragment).setVisible(true); mMenu.findItem(R.id.action_delete_view_post_detail_fragment).setVisible(true);
MenuItem nsfwItem = mMenu.findItem(R.id.action_nsfw_view_post_detail_fragment); MenuItem nsfwItem = mMenu.findItem(R.id.action_nsfw_view_post_detail_fragment);
@ -1061,9 +1059,7 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
return true; return true;
} else if (itemId == R.id.action_edit_view_post_detail_fragment) { } else if (itemId == R.id.action_edit_view_post_detail_fragment) {
Intent editPostIntent = new Intent(activity, EditPostActivity.class); Intent editPostIntent = new Intent(activity, EditPostActivity.class);
editPostIntent.putExtra(EditPostActivity.EXTRA_FULLNAME, mPost.getFullName()); editPostIntent.putExtra(EditPostActivity.EXTRA_DATA, mPost);
editPostIntent.putExtra(EditPostActivity.EXTRA_TITLE, mPost.getTitle());
editPostIntent.putExtra(EditPostActivity.EXTRA_CONTENT, mPost.getSelfText());
startActivityForResult(editPostIntent, EDIT_POST_REQUEST_CODE); startActivityForResult(editPostIntent, EDIT_POST_REQUEST_CODE);
return true; return true;
} else if (itemId == R.id.action_delete_view_post_detail_fragment) { } else if (itemId == R.id.action_delete_view_post_detail_fragment) {

View File

@ -49,11 +49,54 @@
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:fontFamily="?attr/title_font_family" /> android:fontFamily="?attr/title_font_family" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<View <View
android:id="@+id/divider_edit_post_activity" android:id="@+id/divider_edit_post_activity"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" /> android:layout_height="1dp" />
<EditText
android:id="@+id/post_link_edit_text_post_edit_activity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
android:fontFamily="?attr/content_font_family"
android:gravity="top"
android:hint="@string/post_link_hint"
android:inputType="textMultiLine"
android:padding="16dp"
android:textColor="?attr/primaryTextColor"
android:textSize="?attr/content_font_18" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/upload_image_button_post_edit_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:fontFamily="?attr/font_family"
android:text="@string/upload_image"
android:textSize="?attr/font_default" />
<ImageView
android:id="@+id/image_view_post_edit_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitStart"
android:visibility="gone" />
<View
android:id="@+id/divider2_edit_post_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText <EditText
android:id="@+id/post_text_content_edit_text_edit_post_activity" android:id="@+id/post_text_content_edit_text_edit_post_activity"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -1343,4 +1343,5 @@
<string name="url_cannot_be_null_or_empty">URL cannot be null or empty</string> <string name="url_cannot_be_null_or_empty">URL cannot be null or empty</string>
<string name="could_not_resolve_link">Could not resolve URL :(</string> <string name="could_not_resolve_link">Could not resolve URL :(</string>
<string name="mark_post_as_read_failed">Failed to mark post as read</string> <string name="mark_post_as_read_failed">Failed to mark post as read</string>
<string name="upload_image">Upload an image</string>
</resources> </resources>