mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2024-11-06 18:57:26 +01:00
Merge remote-tracking branch 'codeberg/master'
This commit is contained in:
commit
2392d9fa29
@ -77,6 +77,7 @@ import eu.toldi.infinityforlemmy.fragments.InboxFragment;
|
|||||||
import eu.toldi.infinityforlemmy.fragments.MorePostsInfoFragment;
|
import eu.toldi.infinityforlemmy.fragments.MorePostsInfoFragment;
|
||||||
import eu.toldi.infinityforlemmy.fragments.MultiRedditListingFragment;
|
import eu.toldi.infinityforlemmy.fragments.MultiRedditListingFragment;
|
||||||
import eu.toldi.infinityforlemmy.fragments.PostFragment;
|
import eu.toldi.infinityforlemmy.fragments.PostFragment;
|
||||||
|
import eu.toldi.infinityforlemmy.fragments.PrivateMessageFragment;
|
||||||
import eu.toldi.infinityforlemmy.fragments.SidebarFragment;
|
import eu.toldi.infinityforlemmy.fragments.SidebarFragment;
|
||||||
import eu.toldi.infinityforlemmy.fragments.SubredditListingFragment;
|
import eu.toldi.infinityforlemmy.fragments.SubredditListingFragment;
|
||||||
import eu.toldi.infinityforlemmy.fragments.SubscribedSubredditsListingFragment;
|
import eu.toldi.infinityforlemmy.fragments.SubscribedSubredditsListingFragment;
|
||||||
@ -319,6 +320,7 @@ public interface AppComponent {
|
|||||||
|
|
||||||
void inject(CommentMoreBottomSheetFragment commentMoreBottomSheetFragment);
|
void inject(CommentMoreBottomSheetFragment commentMoreBottomSheetFragment);
|
||||||
|
|
||||||
|
void inject(PrivateMessageFragment privateMessageFragment);
|
||||||
|
|
||||||
@Component.Factory
|
@Component.Factory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
|
@ -10,6 +10,7 @@ import javax.inject.Singleton;
|
|||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import eu.toldi.infinityforlemmy.apis.StreamableAPI;
|
import eu.toldi.infinityforlemmy.apis.StreamableAPI;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||||
import eu.toldi.infinityforlemmy.comment.LemmyCommentAPI;
|
import eu.toldi.infinityforlemmy.comment.LemmyCommentAPI;
|
||||||
import eu.toldi.infinityforlemmy.post.LemmyPostAPI;
|
import eu.toldi.infinityforlemmy.post.LemmyPostAPI;
|
||||||
import eu.toldi.infinityforlemmy.utils.APIUtils;
|
import eu.toldi.infinityforlemmy.utils.APIUtils;
|
||||||
@ -226,4 +227,10 @@ abstract class NetworkModule {
|
|||||||
static LemmyCommentAPI provideCommentAPI(@Named("no_oauth") RetrofitHolder retrofitHolder) {
|
static LemmyCommentAPI provideCommentAPI(@Named("no_oauth") RetrofitHolder retrofitHolder) {
|
||||||
return new LemmyCommentAPI(retrofitHolder);
|
return new LemmyCommentAPI(retrofitHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static LemmyPrivateMessageAPI provideLemmyPrivateMessageAPI(@Named("base") RetrofitHolder retrofit) {
|
||||||
|
return new LemmyPrivateMessageAPI(retrofit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ import eu.toldi.infinityforlemmy.events.PassPrivateMessageEvent;
|
|||||||
import eu.toldi.infinityforlemmy.events.PassPrivateMessageIndexEvent;
|
import eu.toldi.infinityforlemmy.events.PassPrivateMessageIndexEvent;
|
||||||
import eu.toldi.infinityforlemmy.events.SwitchAccountEvent;
|
import eu.toldi.infinityforlemmy.events.SwitchAccountEvent;
|
||||||
import eu.toldi.infinityforlemmy.fragments.InboxFragment;
|
import eu.toldi.infinityforlemmy.fragments.InboxFragment;
|
||||||
|
import eu.toldi.infinityforlemmy.fragments.PrivateMessageFragment;
|
||||||
import eu.toldi.infinityforlemmy.message.CommentInteraction;
|
import eu.toldi.infinityforlemmy.message.CommentInteraction;
|
||||||
import eu.toldi.infinityforlemmy.message.FetchMessage;
|
import eu.toldi.infinityforlemmy.message.FetchMessage;
|
||||||
import eu.toldi.infinityforlemmy.message.ReadMessage;
|
import eu.toldi.infinityforlemmy.message.ReadMessage;
|
||||||
@ -180,7 +181,7 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
|
|||||||
if (i == EditorInfo.IME_ACTION_DONE) {
|
if (i == EditorInfo.IME_ACTION_DONE) {
|
||||||
Utils.hideKeyboard(this);
|
Utils.hideKeyboard(this);
|
||||||
Intent pmIntent = new Intent(this, SendPrivateMessageActivity.class);
|
Intent pmIntent = new Intent(this, SendPrivateMessageActivity.class);
|
||||||
pmIntent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, thingEditText.getText().toString());
|
//pmIntent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, thingEditText.getText().toString());
|
||||||
startActivity(pmIntent);
|
startActivity(pmIntent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -193,7 +194,7 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
|
|||||||
-> {
|
-> {
|
||||||
Utils.hideKeyboard(this);
|
Utils.hideKeyboard(this);
|
||||||
Intent pmIntent = new Intent(this, SendPrivateMessageActivity.class);
|
Intent pmIntent = new Intent(this, SendPrivateMessageActivity.class);
|
||||||
pmIntent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, thingEditText.getText().toString());
|
//pmIntent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, thingEditText.getText().toString());
|
||||||
startActivity(pmIntent);
|
startActivity(pmIntent);
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
@ -330,7 +331,7 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
|
|||||||
if (resultCode == RESULT_OK && requestCode == SEARCH_USER_REQUEST_CODE && data != null) {
|
if (resultCode == RESULT_OK && requestCode == SEARCH_USER_REQUEST_CODE && data != null) {
|
||||||
String username = data.getStringExtra(SearchActivity.EXTRA_RETURN_USER_NAME);
|
String username = data.getStringExtra(SearchActivity.EXTRA_RETURN_USER_NAME);
|
||||||
Intent intent = new Intent(this, SendPrivateMessageActivity.class);
|
Intent intent = new Intent(this, SendPrivateMessageActivity.class);
|
||||||
intent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, username);
|
//intent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, username);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,7 +442,7 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Fragment createFragment(int position) {
|
public Fragment createFragment(int position) {
|
||||||
InboxFragment fragment = new InboxFragment();
|
Fragment fragment = new InboxFragment();
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(InboxFragment.EXTRA_ACCESS_TOKEN, mAccessToken);
|
bundle.putString(InboxFragment.EXTRA_ACCESS_TOKEN, mAccessToken);
|
||||||
switch (position) {
|
switch (position) {
|
||||||
@ -450,11 +451,9 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_MENTIONS);
|
bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_MENTIONS);
|
||||||
fragment.setArguments(bundle);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_MESSAGES);
|
fragment = new PrivateMessageFragment();
|
||||||
fragment.setArguments(bundle);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fragment.setArguments(bundle);
|
fragment.setArguments(bundle);
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
package eu.toldi.infinityforlemmy.activities;
|
package eu.toldi.infinityforlemmy.activities;
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
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.provider.MediaStore;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -10,12 +15,20 @@ import android.widget.EditText;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
import androidx.core.content.FileProvider;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.google.android.material.appbar.AppBarLayout;
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
@ -23,13 +36,24 @@ import butterknife.BindView;
|
|||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.toldi.infinityforlemmy.Infinity;
|
import eu.toldi.infinityforlemmy.Infinity;
|
||||||
import eu.toldi.infinityforlemmy.R;
|
import eu.toldi.infinityforlemmy.R;
|
||||||
|
import eu.toldi.infinityforlemmy.RetrofitHolder;
|
||||||
|
import eu.toldi.infinityforlemmy.UploadImageEnabledActivity;
|
||||||
|
import eu.toldi.infinityforlemmy.UploadedImage;
|
||||||
|
import eu.toldi.infinityforlemmy.adapters.MarkdownBottomBarRecyclerViewAdapter;
|
||||||
|
import eu.toldi.infinityforlemmy.bottomsheetfragments.UploadedImagesBottomSheetFragment;
|
||||||
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
||||||
import eu.toldi.infinityforlemmy.message.ComposeMessage;
|
import eu.toldi.infinityforlemmy.customviews.LinearLayoutManagerBugFixed;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||||
|
import eu.toldi.infinityforlemmy.user.BasicUserInfo;
|
||||||
import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils;
|
import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils;
|
||||||
import retrofit2.Retrofit;
|
import eu.toldi.infinityforlemmy.utils.Utils;
|
||||||
|
|
||||||
public class SendPrivateMessageActivity extends BaseActivity {
|
public class SendPrivateMessageActivity extends BaseActivity implements UploadImageEnabledActivity {
|
||||||
public static final String EXTRA_RECIPIENT_USERNAME = "ERU";
|
public static final String EXTRA_RECIPIENT_USER_INFO = "ERUI";
|
||||||
|
|
||||||
|
private static final int PICK_IMAGE_REQUEST_CODE = 100;
|
||||||
|
private static final int CAPTURE_IMAGE_REQUEST_CODE = 200;
|
||||||
@BindView(R.id.coordinator_layout_send_private_message_activity)
|
@BindView(R.id.coordinator_layout_send_private_message_activity)
|
||||||
CoordinatorLayout coordinatorLayout;
|
CoordinatorLayout coordinatorLayout;
|
||||||
@BindView(R.id.appbar_layout_send_private_message_activity)
|
@BindView(R.id.appbar_layout_send_private_message_activity)
|
||||||
@ -40,15 +64,20 @@ public class SendPrivateMessageActivity extends BaseActivity {
|
|||||||
EditText usernameEditText;
|
EditText usernameEditText;
|
||||||
@BindView(R.id.divider_1_send_private_message_activity)
|
@BindView(R.id.divider_1_send_private_message_activity)
|
||||||
View divider1;
|
View divider1;
|
||||||
@BindView(R.id.subjet_edit_text_send_private_message_activity)
|
|
||||||
EditText subjectEditText;
|
|
||||||
@BindView(R.id.divider_2_send_private_message_activity)
|
@BindView(R.id.divider_2_send_private_message_activity)
|
||||||
View divider2;
|
View divider2;
|
||||||
@BindView(R.id.content_edit_text_send_private_message_activity)
|
@BindView(R.id.content_edit_text_send_private_message_activity)
|
||||||
EditText messageEditText;
|
EditText messageEditText;
|
||||||
|
|
||||||
|
@BindView(R.id.markdown_bottom_bar_recycler_view_send_private_message_activity)
|
||||||
|
RecyclerView markdownBottomBarRecyclerView;
|
||||||
@Inject
|
@Inject
|
||||||
@Named("oauth")
|
@Named("no_oauth")
|
||||||
Retrofit mOauthRetrofit;
|
RetrofitHolder mRetrofit;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Executor mExecutor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Named("default")
|
@Named("default")
|
||||||
SharedPreferences mSharedPreferences;
|
SharedPreferences mSharedPreferences;
|
||||||
@ -57,15 +86,24 @@ public class SendPrivateMessageActivity extends BaseActivity {
|
|||||||
SharedPreferences mCurrentAccountSharedPreferences;
|
SharedPreferences mCurrentAccountSharedPreferences;
|
||||||
@Inject
|
@Inject
|
||||||
CustomThemeWrapper mCustomThemeWrapper;
|
CustomThemeWrapper mCustomThemeWrapper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LemmyPrivateMessageAPI mLemmyPrivateMessageAPI;
|
||||||
private String mAccessToken;
|
private String mAccessToken;
|
||||||
|
|
||||||
|
private BasicUserInfo mRecipientBasicUserInfo;
|
||||||
private boolean isSubmitting = false;
|
private boolean isSubmitting = false;
|
||||||
|
|
||||||
|
private ArrayList<UploadedImage> uploadedImages = new ArrayList<>();
|
||||||
|
|
||||||
|
private Uri capturedImageUri;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
((Infinity) getApplication()).getAppComponent().inject(this);
|
((Infinity) getApplication()).getAppComponent().inject(this);
|
||||||
|
|
||||||
setImmersiveModeNotApplicable();
|
setImmersiveModeNotApplicable();
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_send_private_message);
|
setContentView(R.layout.activity_send_private_message);
|
||||||
|
|
||||||
@ -77,14 +115,66 @@ public class SendPrivateMessageActivity extends BaseActivity {
|
|||||||
addOnOffsetChangedListener(appBarLayout);
|
addOnOffsetChangedListener(appBarLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkdownBottomBarRecyclerViewAdapter adapter = new MarkdownBottomBarRecyclerViewAdapter(
|
||||||
|
mCustomThemeWrapper, new MarkdownBottomBarRecyclerViewAdapter.ItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(int item) {
|
||||||
|
MarkdownBottomBarRecyclerViewAdapter.bindEditTextWithItemClickListener(
|
||||||
|
SendPrivateMessageActivity.this, messageEditText, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUploadImage() {
|
||||||
|
Utils.hideKeyboard(SendPrivateMessageActivity.this);
|
||||||
|
UploadedImagesBottomSheetFragment fragment = new UploadedImagesBottomSheetFragment();
|
||||||
|
Bundle arguments = new Bundle();
|
||||||
|
arguments.putParcelableArrayList(UploadedImagesBottomSheetFragment.EXTRA_UPLOADED_IMAGES,
|
||||||
|
uploadedImages);
|
||||||
|
fragment.setArguments(arguments);
|
||||||
|
fragment.show(getSupportFragmentManager(), fragment.getTag());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
markdownBottomBarRecyclerView.setLayoutManager(new LinearLayoutManagerBugFixed(this,
|
||||||
|
LinearLayoutManagerBugFixed.HORIZONTAL, false));
|
||||||
|
markdownBottomBarRecyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null);
|
mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null);
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
if (savedInstanceState != null) {
|
||||||
String username = getIntent().getStringExtra(EXTRA_RECIPIENT_USERNAME);
|
mRecipientBasicUserInfo = savedInstanceState.getParcelable(EXTRA_RECIPIENT_USER_INFO);
|
||||||
if (username != null) {
|
} else {
|
||||||
usernameEditText.setText(username);
|
mRecipientBasicUserInfo = getIntent().getParcelableExtra(EXTRA_RECIPIENT_USER_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mRecipientBasicUserInfo != null) {
|
||||||
|
usernameEditText.setText(mRecipientBasicUserInfo.getQualifiedName());
|
||||||
|
usernameEditText.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
if (requestCode == PICK_IMAGE_REQUEST_CODE) {
|
||||||
|
if (data == null) {
|
||||||
|
Toast.makeText(SendPrivateMessageActivity.this, R.string.error_getting_image, Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Utils.uploadImageToReddit(this, mExecutor, mRetrofit,
|
||||||
|
mAccessToken, messageEditText, coordinatorLayout, data.getData(), uploadedImages);
|
||||||
|
} else if (requestCode == CAPTURE_IMAGE_REQUEST_CODE) {
|
||||||
|
Utils.uploadImageToReddit(this, mExecutor, mRetrofit,
|
||||||
|
mAccessToken, messageEditText, coordinatorLayout, capturedImageUri, uploadedImages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -108,12 +198,6 @@ public class SendPrivateMessageActivity extends BaseActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subjectEditText.getText() == null || subjectEditText.getText().toString().equals("")) {
|
|
||||||
isSubmitting = false;
|
|
||||||
Snackbar.make(coordinatorLayout, R.string.message_subject_required, Snackbar.LENGTH_LONG).show();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messageEditText.getText() == null || messageEditText.getText().toString().equals("")) {
|
if (messageEditText.getText() == null || messageEditText.getText().toString().equals("")) {
|
||||||
isSubmitting = false;
|
isSubmitting = false;
|
||||||
Snackbar.make(coordinatorLayout, R.string.message_content_required, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(coordinatorLayout, R.string.message_content_required, Snackbar.LENGTH_LONG).show();
|
||||||
@ -125,32 +209,26 @@ public class SendPrivateMessageActivity extends BaseActivity {
|
|||||||
Snackbar sendingSnackbar = Snackbar.make(coordinatorLayout, R.string.sending_message, Snackbar.LENGTH_INDEFINITE);
|
Snackbar sendingSnackbar = Snackbar.make(coordinatorLayout, R.string.sending_message, Snackbar.LENGTH_INDEFINITE);
|
||||||
sendingSnackbar.show();
|
sendingSnackbar.show();
|
||||||
|
|
||||||
ComposeMessage.composeMessage(mOauthRetrofit, mAccessToken, getResources().getConfiguration().locale,
|
mLemmyPrivateMessageAPI.sendPrivateMessage(mAccessToken, mRecipientBasicUserInfo.getId(), messageEditText.getText().toString(), new LemmyPrivateMessageAPI.PrivateMessageSentListener() {
|
||||||
usernameEditText.getText().toString(), subjectEditText.getText().toString(),
|
@Override
|
||||||
messageEditText.getText().toString(), new ComposeMessage.ComposeMessageListener() {
|
public void onPrivateMessageSentSuccess(@NonNull PrivateMessage privateMessage) {
|
||||||
@Override
|
isSubmitting = false;
|
||||||
public void composeMessageSuccess() {
|
item.setEnabled(true);
|
||||||
isSubmitting = false;
|
item.getIcon().setAlpha(255);
|
||||||
item.setEnabled(true);
|
Toast.makeText(SendPrivateMessageActivity.this, R.string.send_message_success, Toast.LENGTH_SHORT).show();
|
||||||
item.getIcon().setAlpha(255);
|
finish();
|
||||||
Toast.makeText(SendPrivateMessageActivity.this, R.string.send_message_success, Toast.LENGTH_SHORT).show();
|
}
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void composeMessageFailed(String errorMessage) {
|
public void onPrivateMessageSentError() {
|
||||||
isSubmitting = false;
|
isSubmitting = false;
|
||||||
sendingSnackbar.dismiss();
|
sendingSnackbar.dismiss();
|
||||||
item.setEnabled(true);
|
item.setEnabled(true);
|
||||||
item.getIcon().setAlpha(255);
|
item.getIcon().setAlpha(255);
|
||||||
|
|
||||||
if (errorMessage == null || errorMessage.equals("")) {
|
Snackbar.make(coordinatorLayout, R.string.send_message_failed, Snackbar.LENGTH_LONG).show();
|
||||||
Snackbar.make(coordinatorLayout, R.string.send_message_failed, Snackbar.LENGTH_LONG).show();
|
}
|
||||||
} else {
|
});
|
||||||
Snackbar.make(coordinatorLayout, errorMessage, Snackbar.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -159,6 +237,7 @@ public class SendPrivateMessageActivity extends BaseActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
outState.putParcelable(EXTRA_RECIPIENT_USER_INFO, mRecipientBasicUserInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -177,19 +256,49 @@ public class SendPrivateMessageActivity extends BaseActivity {
|
|||||||
applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, null, toolbar);
|
applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, null, toolbar);
|
||||||
int primaryTextColor = mCustomThemeWrapper.getPrimaryTextColor();
|
int primaryTextColor = mCustomThemeWrapper.getPrimaryTextColor();
|
||||||
usernameEditText.setTextColor(primaryTextColor);
|
usernameEditText.setTextColor(primaryTextColor);
|
||||||
subjectEditText.setTextColor(primaryTextColor);
|
|
||||||
messageEditText.setTextColor(primaryTextColor);
|
messageEditText.setTextColor(primaryTextColor);
|
||||||
int secondaryTextColor = mCustomThemeWrapper.getSecondaryTextColor();
|
int secondaryTextColor = mCustomThemeWrapper.getSecondaryTextColor();
|
||||||
usernameEditText.setHintTextColor(secondaryTextColor);
|
usernameEditText.setHintTextColor(secondaryTextColor);
|
||||||
subjectEditText.setHintTextColor(secondaryTextColor);
|
|
||||||
messageEditText.setHintTextColor(secondaryTextColor);
|
messageEditText.setHintTextColor(secondaryTextColor);
|
||||||
int dividerColor = mCustomThemeWrapper.getDividerColor();
|
int dividerColor = mCustomThemeWrapper.getDividerColor();
|
||||||
divider1.setBackgroundColor(dividerColor);
|
divider1.setBackgroundColor(dividerColor);
|
||||||
divider2.setBackgroundColor(dividerColor);
|
divider2.setBackgroundColor(dividerColor);
|
||||||
if (typeface != null) {
|
if (typeface != null) {
|
||||||
usernameEditText.setTypeface(typeface);
|
usernameEditText.setTypeface(typeface);
|
||||||
subjectEditText.setTypeface(typeface);
|
|
||||||
messageEditText.setTypeface(typeface);
|
messageEditText.setTypeface(typeface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadImage() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setType("image/*");
|
||||||
|
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||||
|
startActivityForResult(Intent.createChooser(intent,
|
||||||
|
getResources().getString(R.string.select_from_gallery)), PICK_IMAGE_REQUEST_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void captureImage() {
|
||||||
|
Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||||
|
try {
|
||||||
|
capturedImageUri = FileProvider.getUriForFile(this, "eu.toldi.infinityforlemmy.provider",
|
||||||
|
File.createTempFile("captured_image", ".jpg", getExternalFilesDir(Environment.DIRECTORY_PICTURES)));
|
||||||
|
pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageUri);
|
||||||
|
startActivityForResult(pictureIntent, CAPTURE_IMAGE_REQUEST_CODE);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Toast.makeText(this, R.string.error_creating_temp_file, Toast.LENGTH_SHORT).show();
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Toast.makeText(this, R.string.no_camera_available, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertImageUrl(UploadedImage uploadedImage) {
|
||||||
|
int start = Math.max(messageEditText.getSelectionStart(), 0);
|
||||||
|
int end = Math.max(messageEditText.getSelectionEnd(), 0);
|
||||||
|
messageEditText.getText().replace(Math.min(start, end), Math.max(start, end),
|
||||||
|
"![" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")",
|
||||||
|
0, "![]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length());
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ import android.content.SharedPreferences;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
@ -27,6 +28,7 @@ import org.greenrobot.eventbus.EventBus;
|
|||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -46,14 +48,15 @@ import eu.toldi.infinityforlemmy.customviews.LinearLayoutManagerBugFixed;
|
|||||||
import eu.toldi.infinityforlemmy.events.PassPrivateMessageEvent;
|
import eu.toldi.infinityforlemmy.events.PassPrivateMessageEvent;
|
||||||
import eu.toldi.infinityforlemmy.events.PassPrivateMessageIndexEvent;
|
import eu.toldi.infinityforlemmy.events.PassPrivateMessageIndexEvent;
|
||||||
import eu.toldi.infinityforlemmy.events.RepliedToPrivateMessageEvent;
|
import eu.toldi.infinityforlemmy.events.RepliedToPrivateMessageEvent;
|
||||||
import eu.toldi.infinityforlemmy.message.Message;
|
|
||||||
import eu.toldi.infinityforlemmy.message.ReadMessage;
|
import eu.toldi.infinityforlemmy.message.ReadMessage;
|
||||||
import eu.toldi.infinityforlemmy.message.ReplyMessage;
|
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||||
import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils;
|
import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils;
|
||||||
import retrofit2.Retrofit;
|
import retrofit2.Retrofit;
|
||||||
|
|
||||||
public class ViewPrivateMessagesActivity extends BaseActivity implements ActivityToolbarInterface {
|
public class ViewPrivateMessagesActivity extends BaseActivity implements ActivityToolbarInterface {
|
||||||
|
|
||||||
|
public static final String EXTRA_PRIVATE_MESSAGE = "EPM";
|
||||||
public static final String EXTRA_PRIVATE_MESSAGE_INDEX = "EPM";
|
public static final String EXTRA_PRIVATE_MESSAGE_INDEX = "EPM";
|
||||||
public static final String EXTRA_MESSAGE_POSITION = "EMP";
|
public static final String EXTRA_MESSAGE_POSITION = "EMP";
|
||||||
private static final String USER_AVATAR_STATE = "UAS";
|
private static final String USER_AVATAR_STATE = "UAS";
|
||||||
@ -91,14 +94,19 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit
|
|||||||
CustomThemeWrapper mCustomThemeWrapper;
|
CustomThemeWrapper mCustomThemeWrapper;
|
||||||
@Inject
|
@Inject
|
||||||
Executor mExecutor;
|
Executor mExecutor;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LemmyPrivateMessageAPI mLemmyPrivateMessageAPI;
|
||||||
private LinearLayoutManagerBugFixed mLinearLayoutManager;
|
private LinearLayoutManagerBugFixed mLinearLayoutManager;
|
||||||
private PrivateMessagesDetailRecyclerViewAdapter mAdapter;
|
private PrivateMessagesDetailRecyclerViewAdapter mAdapter;
|
||||||
@State
|
@State
|
||||||
Message privateMessage;
|
PrivateMessage privateMessage;
|
||||||
@State
|
@State
|
||||||
Message replyTo;
|
PrivateMessage replyTo;
|
||||||
private String mAccessToken;
|
private String mAccessToken;
|
||||||
private String mAccountName;
|
private String mAccountName;
|
||||||
|
|
||||||
|
private String mAccountQualifiedName;
|
||||||
private String mUserAvatar;
|
private String mUserAvatar;
|
||||||
private ArrayList<ProvideUserAvatarCallback> mProvideUserAvatarCallbacks;
|
private ArrayList<ProvideUserAvatarCallback> mProvideUserAvatarCallbacks;
|
||||||
private boolean isLoadingUserAvatar = false;
|
private boolean isLoadingUserAvatar = false;
|
||||||
@ -128,6 +136,11 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit
|
|||||||
addOnOffsetChangedListener(mAppBarLayout);
|
addOnOffsetChangedListener(mAppBarLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Intent intent = getIntent();
|
||||||
|
privateMessage = intent.getParcelableExtra(EXTRA_PRIVATE_MESSAGE);
|
||||||
|
|
||||||
|
Log.i("ViewPrivate", "privateMessage: " + privateMessage);
|
||||||
|
|
||||||
setSupportActionBar(mToolbar);
|
setSupportActionBar(mToolbar);
|
||||||
setToolbarGoToTop(mToolbar);
|
setToolbarGoToTop(mToolbar);
|
||||||
|
|
||||||
@ -135,6 +148,7 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit
|
|||||||
|
|
||||||
mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null);
|
mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null);
|
||||||
mAccountName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_NAME, null);
|
mAccountName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_NAME, null);
|
||||||
|
mAccountQualifiedName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_QUALIFIED_NAME, null);
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mUserAvatar = savedInstanceState.getString(USER_AVATAR_STATE);
|
mUserAvatar = savedInstanceState.getString(USER_AVATAR_STATE);
|
||||||
@ -144,36 +158,37 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit
|
|||||||
bindView();
|
bindView();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (privateMessage != null) {
|
||||||
|
bindView();
|
||||||
|
}
|
||||||
EventBus.getDefault().post(new PassPrivateMessageIndexEvent(getIntent().getIntExtra(EXTRA_PRIVATE_MESSAGE_INDEX, -1)));
|
EventBus.getDefault().post(new PassPrivateMessageIndexEvent(getIntent().getIntExtra(EXTRA_PRIVATE_MESSAGE_INDEX, -1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindView() {
|
private void bindView() {
|
||||||
if (privateMessage != null) {
|
if (privateMessage != null) {
|
||||||
if (privateMessage.getAuthor().equals(mAccountName)) {
|
if (privateMessage.getCreatorQualifiedName().equals(mAccountQualifiedName)) {
|
||||||
setTitle(privateMessage.getDestination());
|
setTitle(privateMessage.getRecipientName());
|
||||||
mToolbar.setOnClickListener(view -> {
|
mToolbar.setOnClickListener(view -> {
|
||||||
if (privateMessage.isDestinationDeleted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Intent intent = new Intent(this, ViewUserDetailActivity.class);
|
Intent intent = new Intent(this, ViewUserDetailActivity.class);
|
||||||
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getDestination());
|
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getRecipientName());
|
||||||
|
intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, privateMessage.getRecipientQualifiedName());
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setTitle(privateMessage.getAuthor());
|
setTitle(privateMessage.getCreatorName());
|
||||||
mToolbar.setOnClickListener(view -> {
|
mToolbar.setOnClickListener(view -> {
|
||||||
if (privateMessage.isAuthorDeleted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Intent intent = new Intent(this, ViewUserDetailActivity.class);
|
Intent intent = new Intent(this, ViewUserDetailActivity.class);
|
||||||
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getAuthor());
|
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getCreatorName());
|
||||||
|
intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, privateMessage.getCreatorQualifiedName());
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mAdapter = new PrivateMessagesDetailRecyclerViewAdapter(this, mSharedPreferences,
|
mAdapter = new PrivateMessagesDetailRecyclerViewAdapter(this, mSharedPreferences,
|
||||||
getResources().getConfiguration().locale, privateMessage, mAccountName, mCustomThemeWrapper);
|
getResources().getConfiguration().locale, privateMessage, mAccountQualifiedName, mCustomThemeWrapper);
|
||||||
mLinearLayoutManager = new LinearLayoutManagerBugFixed(this);
|
mLinearLayoutManager = new LinearLayoutManagerBugFixed(this);
|
||||||
mLinearLayoutManager.setStackFromEnd(true);
|
mLinearLayoutManager.setStackFromEnd(true);
|
||||||
mRecyclerView.setLayoutManager(mLinearLayoutManager);
|
mRecyclerView.setLayoutManager(mLinearLayoutManager);
|
||||||
@ -184,45 +199,40 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit
|
|||||||
if (!mEditText.getText().toString().equals("")) {
|
if (!mEditText.getText().toString().equals("")) {
|
||||||
//Send Message
|
//Send Message
|
||||||
if (privateMessage != null) {
|
if (privateMessage != null) {
|
||||||
ArrayList<Message> replies = privateMessage.getReplies();
|
List<PrivateMessage> replies = privateMessage.getReplies();
|
||||||
if (replyTo == null) {
|
if (replyTo == null) {
|
||||||
replyTo = privateMessage;
|
replyTo = privateMessage;
|
||||||
}
|
}
|
||||||
isSendingMessage = true;
|
isSendingMessage = true;
|
||||||
mSendImageView.setColorFilter(mSecondaryTextColor, android.graphics.PorterDuff.Mode.SRC_IN);
|
mSendImageView.setColorFilter(mSecondaryTextColor, android.graphics.PorterDuff.Mode.SRC_IN);
|
||||||
ReplyMessage.replyMessage(mEditText.getText().toString(), replyTo.getFullname(),
|
|
||||||
getResources().getConfiguration().locale, mOauthRetrofit, mAccessToken,
|
|
||||||
new ReplyMessage.ReplyMessageListener() {
|
|
||||||
@Override
|
|
||||||
public void replyMessageSuccess(Message message) {
|
|
||||||
if (mAdapter != null) {
|
|
||||||
mAdapter.addReply(message);
|
|
||||||
}
|
|
||||||
goToBottom();
|
|
||||||
mEditText.setText("");
|
|
||||||
mSendImageView.setColorFilter(mSendMessageIconColor, android.graphics.PorterDuff.Mode.SRC_IN);
|
|
||||||
isSendingMessage = false;
|
|
||||||
EventBus.getDefault().post(new RepliedToPrivateMessageEvent(message, getIntent().getIntExtra(EXTRA_MESSAGE_POSITION, -1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
mLemmyPrivateMessageAPI.sendPrivateMessage(mAccessToken, replyTo.getCreatorId(), mEditText.getText().toString(), new LemmyPrivateMessageAPI.PrivateMessageSentListener() {
|
||||||
public void replyMessageFailed(String errorMessage) {
|
|
||||||
if (errorMessage != null && !errorMessage.equals("")) {
|
@Override
|
||||||
Snackbar.make(mCoordinatorLayout, errorMessage, Snackbar.LENGTH_LONG).show();
|
public void onPrivateMessageSentSuccess(@NonNull PrivateMessage privateMessage) {
|
||||||
} else {
|
if (mAdapter != null) {
|
||||||
Snackbar.make(mCoordinatorLayout, R.string.reply_message_failed, Snackbar.LENGTH_LONG).show();
|
mAdapter.addReply(privateMessage);
|
||||||
}
|
}
|
||||||
mSendImageView.setColorFilter(mSendMessageIconColor, android.graphics.PorterDuff.Mode.SRC_IN);
|
goToBottom();
|
||||||
isSendingMessage = false;
|
mEditText.setText("");
|
||||||
}
|
isSendingMessage = false;
|
||||||
});
|
EventBus.getDefault().post(new RepliedToPrivateMessageEvent(privateMessage, getIntent().getIntExtra(EXTRA_MESSAGE_POSITION, -1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrivateMessageSentError() {
|
||||||
|
Snackbar.make(mCoordinatorLayout, R.string.reply_message_failed, Snackbar.LENGTH_LONG).show();
|
||||||
|
mSendImageView.setColorFilter(mSendMessageIconColor, android.graphics.PorterDuff.Mode.SRC_IN);
|
||||||
|
isSendingMessage = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
StringBuilder fullnames = new StringBuilder();
|
StringBuilder fullnames = new StringBuilder();
|
||||||
if (privateMessage.isNew()) {
|
|
||||||
fullnames.append(privateMessage.getFullname()).append(",");
|
|
||||||
}
|
|
||||||
if (replies != null && !replies.isEmpty()) {
|
if (replies != null && !replies.isEmpty()) {
|
||||||
for (Message m : replies) {
|
for (PrivateMessage m : replies) {
|
||||||
if (m.isNew()) {
|
if (!m.getRead()) {
|
||||||
fullnames.append(m).append(",");
|
fullnames.append(m).append(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1227,8 +1227,8 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.action_contact_mods_view_subreddit_detail_activity) {
|
} else if (itemId == R.id.action_contact_mods_view_subreddit_detail_activity) {
|
||||||
Intent intent = new Intent(this, SendPrivateMessageActivity.class);
|
/* Intent intent = new Intent(this, SendPrivateMessageActivity.class);
|
||||||
intent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, "r/" + communityName);
|
intent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, "r/" + communityName);*/
|
||||||
//startActivity(intent);
|
//startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.block_community_view_subreddit_detail_activity) {
|
} else if (itemId == R.id.block_community_view_subreddit_detail_activity) {
|
||||||
|
@ -108,6 +108,7 @@ import eu.toldi.infinityforlemmy.post.PostPagingSource;
|
|||||||
import eu.toldi.infinityforlemmy.readpost.InsertReadPost;
|
import eu.toldi.infinityforlemmy.readpost.InsertReadPost;
|
||||||
import eu.toldi.infinityforlemmy.subreddit.ParseSubredditData;
|
import eu.toldi.infinityforlemmy.subreddit.ParseSubredditData;
|
||||||
import eu.toldi.infinityforlemmy.subreddit.SubredditData;
|
import eu.toldi.infinityforlemmy.subreddit.SubredditData;
|
||||||
|
import eu.toldi.infinityforlemmy.user.BasicUserInfo;
|
||||||
import eu.toldi.infinityforlemmy.user.BlockUser;
|
import eu.toldi.infinityforlemmy.user.BlockUser;
|
||||||
import eu.toldi.infinityforlemmy.user.FetchUserData;
|
import eu.toldi.infinityforlemmy.user.FetchUserData;
|
||||||
import eu.toldi.infinityforlemmy.user.UserDao;
|
import eu.toldi.infinityforlemmy.user.UserDao;
|
||||||
@ -1268,7 +1269,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele
|
|||||||
}
|
}
|
||||||
|
|
||||||
Intent pmIntent = new Intent(this, SendPrivateMessageActivity.class);
|
Intent pmIntent = new Intent(this, SendPrivateMessageActivity.class);
|
||||||
pmIntent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USERNAME, username);
|
pmIntent.putExtra(SendPrivateMessageActivity.EXTRA_RECIPIENT_USER_INFO, new BasicUserInfo(mUserData.getId(), username, qualifiedName, mUserData.getAvatar(), mUserData.getDisplayName()));
|
||||||
startActivity(pmIntent);
|
startActivity(pmIntent);
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.action_add_to_post_filter_view_user_detail_activity) {
|
} else if (itemId == R.id.action_add_to_post_filter_view_user_detail_activity) {
|
||||||
|
@ -0,0 +1,343 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.adapters;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
import android.text.util.Linkify;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.paging.PagedListAdapter;
|
||||||
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import eu.toldi.infinityforlemmy.NetworkState;
|
||||||
|
import eu.toldi.infinityforlemmy.R;
|
||||||
|
import eu.toldi.infinityforlemmy.activities.BaseActivity;
|
||||||
|
import eu.toldi.infinityforlemmy.activities.LinkResolverActivity;
|
||||||
|
import eu.toldi.infinityforlemmy.activities.ViewPrivateMessagesActivity;
|
||||||
|
import eu.toldi.infinityforlemmy.activities.ViewUserDetailActivity;
|
||||||
|
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
||||||
|
import eu.toldi.infinityforlemmy.markdown.RedditHeadingPlugin;
|
||||||
|
import eu.toldi.infinityforlemmy.markdown.SpoilerAwareMovementMethod;
|
||||||
|
import eu.toldi.infinityforlemmy.markdown.SpoilerParserPlugin;
|
||||||
|
import eu.toldi.infinityforlemmy.markdown.SuperscriptPlugin;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||||
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
|
import io.noties.markwon.Markwon;
|
||||||
|
import io.noties.markwon.MarkwonConfiguration;
|
||||||
|
import io.noties.markwon.core.MarkwonTheme;
|
||||||
|
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
|
||||||
|
import io.noties.markwon.image.glide.GlideImagesPlugin;
|
||||||
|
import io.noties.markwon.inlineparser.HtmlInlineProcessor;
|
||||||
|
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
|
||||||
|
import io.noties.markwon.linkify.LinkifyPlugin;
|
||||||
|
import io.noties.markwon.movement.MovementMethodPlugin;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
|
||||||
|
public class PrivateMessageRecycleViewAdapter extends PagedListAdapter<PrivateMessage, RecyclerView.ViewHolder> {
|
||||||
|
private static final int VIEW_TYPE_DATA = 0;
|
||||||
|
private static final int VIEW_TYPE_ERROR = 1;
|
||||||
|
private static final int VIEW_TYPE_LOADING = 2;
|
||||||
|
private static final DiffUtil.ItemCallback<PrivateMessage> DIFF_CALLBACK = new DiffUtil.ItemCallback<>() {
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(@NonNull PrivateMessage message, @NonNull PrivateMessage t1) {
|
||||||
|
return message.getId() == t1.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(@NonNull PrivateMessage message, @NonNull PrivateMessage t1) {
|
||||||
|
return message.getContent().equals(t1.getContent());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private BaseActivity mActivity;
|
||||||
|
private Retrofit retrofit;
|
||||||
|
private Markwon mMarkwon;
|
||||||
|
private String mAccessToken;
|
||||||
|
|
||||||
|
private final LemmyPrivateMessageAPI lemmyPrivateMessageAPI;
|
||||||
|
private int mMessageType;
|
||||||
|
private NetworkState networkState;
|
||||||
|
private RetryLoadingMoreCallback mRetryLoadingMoreCallback;
|
||||||
|
private int mColorAccent;
|
||||||
|
private int mMessageBackgroundColor;
|
||||||
|
private int mUsernameColor;
|
||||||
|
private int mPrimaryTextColor;
|
||||||
|
private int mSecondaryTextColor;
|
||||||
|
private int mUnreadMessageBackgroundColor;
|
||||||
|
private int mColorPrimaryLightTheme;
|
||||||
|
private int mButtonTextColor;
|
||||||
|
private boolean markAllMessagesAsRead = false;
|
||||||
|
|
||||||
|
public PrivateMessageRecycleViewAdapter(BaseActivity activity, Retrofit oauthRetrofit,
|
||||||
|
CustomThemeWrapper customThemeWrapper,
|
||||||
|
String accessToken,
|
||||||
|
LemmyPrivateMessageAPI lemmyPrivateMessageAPI, RetryLoadingMoreCallback retryLoadingMoreCallback) {
|
||||||
|
super(DIFF_CALLBACK);
|
||||||
|
mActivity = activity;
|
||||||
|
retrofit = oauthRetrofit;
|
||||||
|
this.lemmyPrivateMessageAPI = lemmyPrivateMessageAPI;
|
||||||
|
mRetryLoadingMoreCallback = retryLoadingMoreCallback;
|
||||||
|
|
||||||
|
mColorAccent = customThemeWrapper.getColorAccent();
|
||||||
|
mMessageBackgroundColor = customThemeWrapper.getCardViewBackgroundColor();
|
||||||
|
mUsernameColor = customThemeWrapper.getUsername();
|
||||||
|
mPrimaryTextColor = customThemeWrapper.getPrimaryTextColor();
|
||||||
|
mSecondaryTextColor = customThemeWrapper.getSecondaryTextColor();
|
||||||
|
int spoilerBackgroundColor = mSecondaryTextColor | 0xFF000000;
|
||||||
|
mUnreadMessageBackgroundColor = customThemeWrapper.getUnreadMessageBackgroundColor();
|
||||||
|
mColorPrimaryLightTheme = customThemeWrapper.getColorPrimaryLightTheme();
|
||||||
|
mButtonTextColor = customThemeWrapper.getButtonTextColor();
|
||||||
|
|
||||||
|
// todo:https://github.com/Docile-Alligator/Infinity-For-Reddit/issues/1027
|
||||||
|
// add tables support and replace with MarkdownUtils#commonPostMarkwonBuilder
|
||||||
|
mMarkwon = Markwon.builder(mActivity)
|
||||||
|
.usePlugin(MarkwonInlineParserPlugin.create(plugin -> {
|
||||||
|
plugin.excludeInlineProcessor(HtmlInlineProcessor.class);
|
||||||
|
}))
|
||||||
|
.usePlugin(new AbstractMarkwonPlugin() {
|
||||||
|
@Override
|
||||||
|
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
|
||||||
|
builder.linkResolver((view, link) -> {
|
||||||
|
Intent intent = new Intent(mActivity, LinkResolverActivity.class);
|
||||||
|
Uri uri = Uri.parse(link);
|
||||||
|
intent.setData(uri);
|
||||||
|
mActivity.startActivity(intent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
|
||||||
|
builder.linkColor(customThemeWrapper.getLinkColor());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.usePlugin(SuperscriptPlugin.create())
|
||||||
|
.usePlugin(SpoilerParserPlugin.create(mSecondaryTextColor, spoilerBackgroundColor))
|
||||||
|
.usePlugin(RedditHeadingPlugin.create())
|
||||||
|
.usePlugin(StrikethroughPlugin.create())
|
||||||
|
.usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod()))
|
||||||
|
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
|
||||||
|
.usePlugin(GlideImagesPlugin.create(mActivity))
|
||||||
|
.build();
|
||||||
|
mAccessToken = accessToken;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
if (viewType == VIEW_TYPE_DATA) {
|
||||||
|
return new DataViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, parent, false));
|
||||||
|
} else if (viewType == VIEW_TYPE_ERROR) {
|
||||||
|
return new ErrorViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false));
|
||||||
|
} else {
|
||||||
|
return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||||
|
if (holder instanceof DataViewHolder) {
|
||||||
|
PrivateMessage message = getItem(holder.getBindingAdapterPosition());
|
||||||
|
if (message != null) {
|
||||||
|
|
||||||
|
if (!message.getRead()) {
|
||||||
|
if (markAllMessagesAsRead) {
|
||||||
|
message.setRead(true);
|
||||||
|
} else {
|
||||||
|
holder.itemView.setBackgroundColor(
|
||||||
|
mUnreadMessageBackgroundColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
((DataViewHolder) holder).titleTextView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
|
||||||
|
((DataViewHolder) holder).authorTextView.setText(message.getCreatorQualifiedName());
|
||||||
|
String subject = message.getRecipientQualifiedName();
|
||||||
|
((DataViewHolder) holder).subjectTextView.setText(subject);
|
||||||
|
mMarkwon.setMarkdown(((DataViewHolder) holder).contentCustomMarkwonView, message.getContent());
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(view -> {
|
||||||
|
|
||||||
|
Intent intent = new Intent(mActivity, ViewPrivateMessagesActivity.class);
|
||||||
|
intent.putExtra(ViewPrivateMessagesActivity.EXTRA_PRIVATE_MESSAGE, message);
|
||||||
|
mActivity.startActivity(intent);
|
||||||
|
|
||||||
|
|
||||||
|
if (message.getRead()) {
|
||||||
|
holder.itemView.setBackgroundColor(mMessageBackgroundColor);
|
||||||
|
|
||||||
|
|
||||||
|
lemmyPrivateMessageAPI.markPrivateMessageAsRead(mAccessToken, message.getId(), new LemmyPrivateMessageAPI.PrivateMessageMarkedAsReadListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrivateMessageMarkedAsReadError() {
|
||||||
|
message.setRead(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrivateMessageMarkedAsReadSuccess() {
|
||||||
|
message.setRead(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
((DataViewHolder) holder).authorTextView.setOnClickListener(view -> {
|
||||||
|
|
||||||
|
Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
|
||||||
|
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getCreatorName());
|
||||||
|
intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, message.getCreatorQualifiedName());
|
||||||
|
mActivity.startActivity(intent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
// Reached at the end
|
||||||
|
if (hasExtraRow() && position == getItemCount() - 1) {
|
||||||
|
if (networkState.getStatus() == NetworkState.Status.LOADING) {
|
||||||
|
return VIEW_TYPE_LOADING;
|
||||||
|
} else {
|
||||||
|
return VIEW_TYPE_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return VIEW_TYPE_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
if (hasExtraRow()) {
|
||||||
|
return super.getItemCount() + 1;
|
||||||
|
}
|
||||||
|
return super.getItemCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
|
||||||
|
super.onViewRecycled(holder);
|
||||||
|
if (holder instanceof DataViewHolder) {
|
||||||
|
((DataViewHolder) holder).itemView.setBackgroundColor(mMessageBackgroundColor);
|
||||||
|
((DataViewHolder) holder).titleTextView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasExtraRow() {
|
||||||
|
return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNetworkState(NetworkState newNetworkState) {
|
||||||
|
NetworkState previousState = this.networkState;
|
||||||
|
boolean previousExtraRow = hasExtraRow();
|
||||||
|
this.networkState = newNetworkState;
|
||||||
|
boolean newExtraRow = hasExtraRow();
|
||||||
|
if (previousExtraRow != newExtraRow) {
|
||||||
|
if (previousExtraRow) {
|
||||||
|
notifyItemRemoved(super.getItemCount());
|
||||||
|
} else {
|
||||||
|
notifyItemInserted(super.getItemCount());
|
||||||
|
}
|
||||||
|
} else if (newExtraRow && !previousState.equals(newNetworkState)) {
|
||||||
|
notifyItemChanged(getItemCount() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMessageReply(PrivateMessage newReply, int position) {
|
||||||
|
if (position >= 0 && position < super.getItemCount()) {
|
||||||
|
PrivateMessage message = getItem(position);
|
||||||
|
if (message != null) {
|
||||||
|
notifyItemChanged(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMarkAllMessagesAsRead(boolean markAllMessagesAsRead) {
|
||||||
|
this.markAllMessagesAsRead = markAllMessagesAsRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface RetryLoadingMoreCallback {
|
||||||
|
void retryLoadingMore();
|
||||||
|
}
|
||||||
|
|
||||||
|
class DataViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@BindView(R.id.author_text_view_item_message)
|
||||||
|
TextView authorTextView;
|
||||||
|
@BindView(R.id.subject_text_view_item_message)
|
||||||
|
TextView subjectTextView;
|
||||||
|
@BindView(R.id.title_text_view_item_message)
|
||||||
|
TextView titleTextView;
|
||||||
|
@BindView(R.id.content_custom_markwon_view_item_message)
|
||||||
|
TextView contentCustomMarkwonView;
|
||||||
|
|
||||||
|
DataViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ButterKnife.bind(this, itemView);
|
||||||
|
if (mActivity.typeface != null) {
|
||||||
|
authorTextView.setTypeface(mActivity.typeface);
|
||||||
|
subjectTextView.setTypeface(mActivity.typeface);
|
||||||
|
titleTextView.setTypeface(mActivity.titleTypeface);
|
||||||
|
contentCustomMarkwonView.setTypeface(mActivity.contentTypeface);
|
||||||
|
}
|
||||||
|
itemView.setBackgroundColor(mMessageBackgroundColor);
|
||||||
|
authorTextView.setTextColor(mUsernameColor);
|
||||||
|
subjectTextView.setTextColor(mPrimaryTextColor);
|
||||||
|
titleTextView.setTextColor(mPrimaryTextColor);
|
||||||
|
contentCustomMarkwonView.setTextColor(mSecondaryTextColor);
|
||||||
|
|
||||||
|
contentCustomMarkwonView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
|
||||||
|
contentCustomMarkwonView.setOnClickListener(view -> {
|
||||||
|
if (contentCustomMarkwonView.getSelectionStart() == -1 && contentCustomMarkwonView.getSelectionEnd() == -1) {
|
||||||
|
itemView.performClick();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ErrorViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@BindView(R.id.error_text_view_item_footer_error)
|
||||||
|
TextView errorTextView;
|
||||||
|
@BindView(R.id.retry_button_item_footer_error)
|
||||||
|
Button retryButton;
|
||||||
|
|
||||||
|
ErrorViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ButterKnife.bind(this, itemView);
|
||||||
|
if (mActivity.typeface != null) {
|
||||||
|
errorTextView.setTypeface(mActivity.typeface);
|
||||||
|
retryButton.setTypeface(mActivity.typeface);
|
||||||
|
}
|
||||||
|
errorTextView.setText(R.string.load_comments_failed);
|
||||||
|
errorTextView.setTextColor(mSecondaryTextColor);
|
||||||
|
retryButton.setOnClickListener(view -> mRetryLoadingMoreCallback.retryLoadingMore());
|
||||||
|
retryButton.setBackgroundTintList(ColorStateList.valueOf(mColorPrimaryLightTheme));
|
||||||
|
retryButton.setTextColor(mButtonTextColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@BindView(R.id.progress_bar_item_footer_loading)
|
||||||
|
ProgressBar progressBar;
|
||||||
|
|
||||||
|
LoadingViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ButterKnife.bind(this, itemView);
|
||||||
|
progressBar.setIndeterminateTintList(ColorStateList.valueOf(mColorAccent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,34 +27,35 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
|
||||||
import io.noties.markwon.Markwon;
|
|
||||||
import io.noties.markwon.MarkwonConfiguration;
|
|
||||||
import io.noties.markwon.core.MarkwonTheme;
|
|
||||||
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
|
|
||||||
import io.noties.markwon.inlineparser.BangInlineProcessor;
|
|
||||||
import io.noties.markwon.inlineparser.HtmlInlineProcessor;
|
|
||||||
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
|
|
||||||
import io.noties.markwon.linkify.LinkifyPlugin;
|
|
||||||
import io.noties.markwon.movement.MovementMethodPlugin;
|
|
||||||
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
|
|
||||||
import eu.toldi.infinityforlemmy.R;
|
import eu.toldi.infinityforlemmy.R;
|
||||||
import eu.toldi.infinityforlemmy.activities.LinkResolverActivity;
|
import eu.toldi.infinityforlemmy.activities.LinkResolverActivity;
|
||||||
import eu.toldi.infinityforlemmy.activities.ViewPrivateMessagesActivity;
|
import eu.toldi.infinityforlemmy.activities.ViewPrivateMessagesActivity;
|
||||||
import eu.toldi.infinityforlemmy.activities.ViewUserDetailActivity;
|
import eu.toldi.infinityforlemmy.activities.ViewUserDetailActivity;
|
||||||
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
||||||
|
import eu.toldi.infinityforlemmy.markdown.ClickableGlideImagesPlugin;
|
||||||
import eu.toldi.infinityforlemmy.markdown.RedditHeadingPlugin;
|
import eu.toldi.infinityforlemmy.markdown.RedditHeadingPlugin;
|
||||||
import eu.toldi.infinityforlemmy.markdown.SpoilerAwareMovementMethod;
|
import eu.toldi.infinityforlemmy.markdown.SpoilerAwareMovementMethod;
|
||||||
import eu.toldi.infinityforlemmy.markdown.SpoilerParserPlugin;
|
import eu.toldi.infinityforlemmy.markdown.SpoilerParserPlugin;
|
||||||
import eu.toldi.infinityforlemmy.markdown.SuperscriptPlugin;
|
import eu.toldi.infinityforlemmy.markdown.SuperscriptPlugin;
|
||||||
import eu.toldi.infinityforlemmy.message.Message;
|
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||||
import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils;
|
import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils;
|
||||||
import eu.toldi.infinityforlemmy.utils.Utils;
|
import eu.toldi.infinityforlemmy.utils.Utils;
|
||||||
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
|
import io.noties.markwon.Markwon;
|
||||||
|
import io.noties.markwon.MarkwonConfiguration;
|
||||||
|
import io.noties.markwon.core.MarkwonTheme;
|
||||||
|
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
|
||||||
|
import io.noties.markwon.image.glide.GlideImagesPlugin;
|
||||||
|
import io.noties.markwon.inlineparser.HtmlInlineProcessor;
|
||||||
|
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
|
||||||
|
import io.noties.markwon.linkify.LinkifyPlugin;
|
||||||
|
import io.noties.markwon.movement.MovementMethodPlugin;
|
||||||
|
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
|
||||||
|
|
||||||
public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
private static final int VIEW_TYPE_MESSAGE_SENT = 0;
|
private static final int VIEW_TYPE_MESSAGE_SENT = 0;
|
||||||
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 1;
|
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 1;
|
||||||
private Message mMessage;
|
private PrivateMessage mMessage;
|
||||||
private ViewPrivateMessagesActivity mViewPrivateMessagesActivity;
|
private ViewPrivateMessagesActivity mViewPrivateMessagesActivity;
|
||||||
private RequestManager mGlide;
|
private RequestManager mGlide;
|
||||||
private Locale mLocale;
|
private Locale mLocale;
|
||||||
@ -70,7 +71,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
|
|
||||||
public PrivateMessagesDetailRecyclerViewAdapter(ViewPrivateMessagesActivity viewPrivateMessagesActivity,
|
public PrivateMessagesDetailRecyclerViewAdapter(ViewPrivateMessagesActivity viewPrivateMessagesActivity,
|
||||||
SharedPreferences sharedPreferences, Locale locale,
|
SharedPreferences sharedPreferences, Locale locale,
|
||||||
Message message, String accountName,
|
PrivateMessage message, String accountName,
|
||||||
CustomThemeWrapper customThemeWrapper) {
|
CustomThemeWrapper customThemeWrapper) {
|
||||||
mMessage = message;
|
mMessage = message;
|
||||||
mViewPrivateMessagesActivity = viewPrivateMessagesActivity;
|
mViewPrivateMessagesActivity = viewPrivateMessagesActivity;
|
||||||
@ -83,7 +84,6 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
mMarkwon = Markwon.builder(viewPrivateMessagesActivity)
|
mMarkwon = Markwon.builder(viewPrivateMessagesActivity)
|
||||||
.usePlugin(MarkwonInlineParserPlugin.create(plugin -> {
|
.usePlugin(MarkwonInlineParserPlugin.create(plugin -> {
|
||||||
plugin.excludeInlineProcessor(HtmlInlineProcessor.class);
|
plugin.excludeInlineProcessor(HtmlInlineProcessor.class);
|
||||||
plugin.excludeInlineProcessor(BangInlineProcessor.class);
|
|
||||||
}))
|
}))
|
||||||
.usePlugin(new AbstractMarkwonPlugin() {
|
.usePlugin(new AbstractMarkwonPlugin() {
|
||||||
@Override
|
@Override
|
||||||
@ -108,6 +108,8 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
builder.linkColor(customThemeWrapper.getLinkColor());
|
builder.linkColor(customThemeWrapper.getLinkColor());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.usePlugin(GlideImagesPlugin.create(viewPrivateMessagesActivity))
|
||||||
|
.usePlugin(ClickableGlideImagesPlugin.create(viewPrivateMessagesActivity))
|
||||||
.usePlugin(SuperscriptPlugin.create())
|
.usePlugin(SuperscriptPlugin.create())
|
||||||
.usePlugin(StrikethroughPlugin.create())
|
.usePlugin(StrikethroughPlugin.create())
|
||||||
.usePlugin(SpoilerParserPlugin.create(commentColor, commentColor | 0xFF000000))
|
.usePlugin(SpoilerParserPlugin.create(commentColor, commentColor | 0xFF000000))
|
||||||
@ -127,9 +129,9 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
if (position == 0) {
|
if (position == 0) {
|
||||||
return mMessage.getAuthor().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED;
|
return mMessage.getCreatorQualifiedName().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED;
|
||||||
} else {
|
} else {
|
||||||
return mMessage.getReplies().get(position - 1).getAuthor().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED;
|
return mMessage.getReplies().get(position - 1).getCreatorQualifiedName().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +147,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||||
Message message;
|
PrivateMessage message;
|
||||||
if (holder.getBindingAdapterPosition() == 0) {
|
if (holder.getBindingAdapterPosition() == 0) {
|
||||||
message = mMessage;
|
message = mMessage;
|
||||||
} else {
|
} else {
|
||||||
@ -153,12 +155,12 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
}
|
}
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
if (holder instanceof MessageViewHolder) {
|
if (holder instanceof MessageViewHolder) {
|
||||||
mMarkwon.setMarkdown(((MessageViewHolder) holder).messageTextView, message.getBody());
|
mMarkwon.setMarkdown(((MessageViewHolder) holder).messageTextView, message.getContent());
|
||||||
|
|
||||||
if (mShowElapsedTime) {
|
if (mShowElapsedTime) {
|
||||||
((MessageViewHolder) holder).timeTextView.setText(Utils.getElapsedTime(mViewPrivateMessagesActivity, message.getTimeUTC()));
|
((MessageViewHolder) holder).timeTextView.setText(Utils.getElapsedTime(mViewPrivateMessagesActivity, message.getPublished()));
|
||||||
} else {
|
} else {
|
||||||
((MessageViewHolder) holder).timeTextView.setText(Utils.getFormattedTime(mLocale, message.getTimeUTC(), mTimeFormatPattern));
|
((MessageViewHolder) holder).timeTextView.setText(Utils.getFormattedTime(mLocale, message.getPublished(), mTimeFormatPattern));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,26 +168,33 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
((SentMessageViewHolder) holder).messageTextView.setBackground(Utils.getTintedDrawable(mViewPrivateMessagesActivity,
|
((SentMessageViewHolder) holder).messageTextView.setBackground(Utils.getTintedDrawable(mViewPrivateMessagesActivity,
|
||||||
R.drawable.private_message_ballon, mSentMessageBackgroundColor));
|
R.drawable.private_message_ballon, mSentMessageBackgroundColor));
|
||||||
} else if (holder instanceof ReceivedMessageViewHolder) {
|
} else if (holder instanceof ReceivedMessageViewHolder) {
|
||||||
mViewPrivateMessagesActivity.fetchUserAvatar(message.getAuthor(), userAvatarUrl -> {
|
if (!message.getCreatorAvatar().equals("")) {
|
||||||
if (userAvatarUrl == null || userAvatarUrl.equals("")) {
|
mGlide.load(message.getCreatorAvatar())
|
||||||
mGlide.load(R.drawable.subreddit_default_icon)
|
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
|
.error(mGlide.load(R.drawable.subreddit_default_icon)
|
||||||
.into(((ReceivedMessageViewHolder) holder).userAvatarImageView);
|
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
|
||||||
} else {
|
.into(((ReceivedMessageViewHolder) holder).userAvatarImageView);
|
||||||
mGlide.load(userAvatarUrl)
|
} else {
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
|
mViewPrivateMessagesActivity.fetchUserAvatar(message.getCreatorQualifiedName(), userAvatarUrl -> {
|
||||||
.error(mGlide.load(R.drawable.subreddit_default_icon)
|
if (userAvatarUrl == null || userAvatarUrl.equals("")) {
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
|
mGlide.load(R.drawable.subreddit_default_icon)
|
||||||
.into(((ReceivedMessageViewHolder) holder).userAvatarImageView);
|
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
|
||||||
}
|
.into(((ReceivedMessageViewHolder) holder).userAvatarImageView);
|
||||||
});
|
} else {
|
||||||
|
mGlide.load(userAvatarUrl)
|
||||||
|
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
|
||||||
|
.error(mGlide.load(R.drawable.subreddit_default_icon)
|
||||||
|
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
|
||||||
|
.into(((ReceivedMessageViewHolder) holder).userAvatarImageView);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
((ReceivedMessageViewHolder) holder).userAvatarImageView.setOnClickListener(view -> {
|
((ReceivedMessageViewHolder) holder).userAvatarImageView.setOnClickListener(view -> {
|
||||||
if (message.isAuthorDeleted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Intent intent = new Intent(mViewPrivateMessagesActivity, ViewUserDetailActivity.class);
|
Intent intent = new Intent(mViewPrivateMessagesActivity, ViewUserDetailActivity.class);
|
||||||
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getAuthor());
|
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getCreatorName());
|
||||||
|
intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, message.getCreatorQualifiedName());
|
||||||
mViewPrivateMessagesActivity.startActivity(intent);
|
mViewPrivateMessagesActivity.startActivity(intent);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -207,12 +216,12 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessage(Message message) {
|
public void setMessage(PrivateMessage message) {
|
||||||
mMessage = message;
|
mMessage = message;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addReply(Message reply) {
|
public void addReply(PrivateMessage reply) {
|
||||||
int currentSize = getItemCount();
|
int currentSize = getItemCount();
|
||||||
|
|
||||||
if (mMessage != null) {
|
if (mMessage != null) {
|
||||||
@ -273,7 +282,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
copyImageView.setColorFilter(mSecondaryTextColor, android.graphics.PorterDuff.Mode.SRC_IN);
|
copyImageView.setColorFilter(mSecondaryTextColor, android.graphics.PorterDuff.Mode.SRC_IN);
|
||||||
|
|
||||||
copyImageView.setOnClickListener(view -> {
|
copyImageView.setOnClickListener(view -> {
|
||||||
Message message;
|
PrivateMessage message;
|
||||||
if (getBindingAdapterPosition() == 0) {
|
if (getBindingAdapterPosition() == 0) {
|
||||||
message = mMessage;
|
message = mMessage;
|
||||||
} else {
|
} else {
|
||||||
@ -282,7 +291,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt
|
|||||||
if (message != null) {
|
if (message != null) {
|
||||||
ClipboardManager clipboard = (ClipboardManager) mViewPrivateMessagesActivity.getSystemService(Context.CLIPBOARD_SERVICE);
|
ClipboardManager clipboard = (ClipboardManager) mViewPrivateMessagesActivity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
if (clipboard != null) {
|
if (clipboard != null) {
|
||||||
ClipData clip = ClipData.newPlainText("simple text", message.getBody());
|
ClipData clip = ClipData.newPlainText("simple text", message.getContent());
|
||||||
clipboard.setPrimaryClip(clip);
|
clipboard.setPrimaryClip(clip);
|
||||||
if (android.os.Build.VERSION.SDK_INT < 33) {
|
if (android.os.Build.VERSION.SDK_INT < 33) {
|
||||||
Toast.makeText(mViewPrivateMessagesActivity, R.string.copy_success, Toast.LENGTH_SHORT).show();
|
Toast.makeText(mViewPrivateMessagesActivity, R.string.copy_success, Toast.LENGTH_SHORT).show();
|
||||||
|
@ -15,6 +15,10 @@ import eu.toldi.infinityforlemmy.dto.EditCommentDTO;
|
|||||||
import eu.toldi.infinityforlemmy.dto.EditPostDTO;
|
import eu.toldi.infinityforlemmy.dto.EditPostDTO;
|
||||||
import eu.toldi.infinityforlemmy.dto.FollowCommunityDTO;
|
import eu.toldi.infinityforlemmy.dto.FollowCommunityDTO;
|
||||||
import eu.toldi.infinityforlemmy.dto.PostVoteDTO;
|
import eu.toldi.infinityforlemmy.dto.PostVoteDTO;
|
||||||
|
import eu.toldi.infinityforlemmy.dto.PrivateMessageDTO;
|
||||||
|
import eu.toldi.infinityforlemmy.dto.PrivateMessageReadDTO;
|
||||||
|
import eu.toldi.infinityforlemmy.dto.PrivateMessageReportDTO;
|
||||||
|
import eu.toldi.infinityforlemmy.dto.PrivateMessageUpdateDTO;
|
||||||
import eu.toldi.infinityforlemmy.dto.ReadCommentDTO;
|
import eu.toldi.infinityforlemmy.dto.ReadCommentDTO;
|
||||||
import eu.toldi.infinityforlemmy.dto.ReadMessageDTO;
|
import eu.toldi.infinityforlemmy.dto.ReadMessageDTO;
|
||||||
import eu.toldi.infinityforlemmy.dto.ReadPostDTO;
|
import eu.toldi.infinityforlemmy.dto.ReadPostDTO;
|
||||||
@ -246,4 +250,37 @@ public interface LemmyAPI {
|
|||||||
Call<String> getSiteInfo(
|
Call<String> getSiteInfo(
|
||||||
@Query("auth") String auth
|
@Query("auth") String auth
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@GET("api/v3/private_message/list")
|
||||||
|
Call<String> privateMessagesList(
|
||||||
|
@Query("page") Integer page,
|
||||||
|
@Query("limit") Integer limit,
|
||||||
|
@Query("unread_only") Boolean unread_only,
|
||||||
|
@NonNull @Query("auth") String auth
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("api/v3/private_message")
|
||||||
|
Call<String> privateMessageSend(
|
||||||
|
@Body PrivateMessageDTO params
|
||||||
|
);
|
||||||
|
|
||||||
|
@PUT("api/v3/private_message")
|
||||||
|
Call<String> privateMessageEdit(
|
||||||
|
@Body PrivateMessageUpdateDTO params
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("api/v3/private_message/delete")
|
||||||
|
Call<String> privateMessageDelete(
|
||||||
|
@Body PrivateMessageUpdateDTO params
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("api/v3/private_message/mark_as_read")
|
||||||
|
Call<String> privateMessageMarkAsRead(
|
||||||
|
@Body PrivateMessageReadDTO params
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("api/v3/private_message/report")
|
||||||
|
Call<String> privateMessageReport(
|
||||||
|
@Body PrivateMessageReportDTO params
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package eu.toldi.infinityforlemmy.events;
|
package eu.toldi.infinityforlemmy.events;
|
||||||
|
|
||||||
import eu.toldi.infinityforlemmy.message.Message;
|
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||||
|
|
||||||
public class RepliedToPrivateMessageEvent {
|
public class RepliedToPrivateMessageEvent {
|
||||||
public Message newReply;
|
public PrivateMessage newReply;
|
||||||
public int messagePosition;
|
public int messagePosition;
|
||||||
|
|
||||||
public RepliedToPrivateMessageEvent(Message newReply, int messagePosition) {
|
public RepliedToPrivateMessageEvent(PrivateMessage newReply, int messagePosition) {
|
||||||
this.newReply = newReply;
|
this.newReply = newReply;
|
||||||
this.messagePosition = messagePosition;
|
this.messagePosition = messagePosition;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,243 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.fragments;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.paging.PagedList;
|
||||||
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import eu.toldi.infinityforlemmy.FragmentCommunicator;
|
||||||
|
import eu.toldi.infinityforlemmy.Infinity;
|
||||||
|
import eu.toldi.infinityforlemmy.NetworkState;
|
||||||
|
import eu.toldi.infinityforlemmy.R;
|
||||||
|
import eu.toldi.infinityforlemmy.RecyclerViewContentScrollingInterface;
|
||||||
|
import eu.toldi.infinityforlemmy.RedditDataRoomDatabase;
|
||||||
|
import eu.toldi.infinityforlemmy.RetrofitHolder;
|
||||||
|
import eu.toldi.infinityforlemmy.activities.BaseActivity;
|
||||||
|
import eu.toldi.infinityforlemmy.adapters.PrivateMessageRecycleViewAdapter;
|
||||||
|
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
||||||
|
import eu.toldi.infinityforlemmy.customviews.LinearLayoutManagerBugFixed;
|
||||||
|
import eu.toldi.infinityforlemmy.events.RepliedToPrivateMessageEvent;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||||
|
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessageViewModel;
|
||||||
|
|
||||||
|
public class PrivateMessageFragment extends Fragment implements FragmentCommunicator {
|
||||||
|
|
||||||
|
public static final String EXTRA_ACCESS_TOKEN = "EAT";
|
||||||
|
public static final String EXTRA_MESSAGE_WHERE = "EMT";
|
||||||
|
@BindView(R.id.swipe_refresh_layout_inbox_fragment)
|
||||||
|
SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
|
@BindView(R.id.recycler_view_inbox_fragment)
|
||||||
|
RecyclerView mRecyclerView;
|
||||||
|
@BindView(R.id.fetch_messages_info_linear_layout_inbox_fragment)
|
||||||
|
LinearLayout mFetchMessageInfoLinearLayout;
|
||||||
|
@BindView(R.id.fetch_messages_info_image_view_inbox_fragment)
|
||||||
|
ImageView mFetchMessageInfoImageView;
|
||||||
|
@BindView(R.id.fetch_messages_info_text_view_inbox_fragment)
|
||||||
|
TextView mFetchMessageInfoTextView;
|
||||||
|
PrivateMessageViewModel mMessageViewModel;
|
||||||
|
@Inject
|
||||||
|
@Named("no_oauth")
|
||||||
|
RetrofitHolder mRetrofit;
|
||||||
|
@Inject
|
||||||
|
RedditDataRoomDatabase mRedditDataRoomDatabase;
|
||||||
|
@Inject
|
||||||
|
@Named("default")
|
||||||
|
SharedPreferences mSharedPreferences;
|
||||||
|
@Inject
|
||||||
|
CustomThemeWrapper mCustomThemeWrapper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LemmyPrivateMessageAPI mLemmyPrivateMessageAPI;
|
||||||
|
private String mAccessToken;
|
||||||
|
private PrivateMessageRecycleViewAdapter mAdapter;
|
||||||
|
private RequestManager mGlide;
|
||||||
|
private LinearLayoutManagerBugFixed mLinearLayoutManager;
|
||||||
|
private BaseActivity mActivity;
|
||||||
|
|
||||||
|
public PrivateMessageFragment() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
Log.i("PrivateMessageFragment", "onCreateView");
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_inbox, container, false);
|
||||||
|
|
||||||
|
((Infinity) mActivity.getApplication()).getAppComponent().inject(this);
|
||||||
|
|
||||||
|
ButterKnife.bind(this, rootView);
|
||||||
|
|
||||||
|
EventBus.getDefault().register(this);
|
||||||
|
|
||||||
|
applyTheme();
|
||||||
|
|
||||||
|
Bundle arguments = getArguments();
|
||||||
|
if (arguments == null) {
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
mAccessToken = getArguments().getString(EXTRA_ACCESS_TOKEN);
|
||||||
|
mGlide = Glide.with(this);
|
||||||
|
|
||||||
|
if (mActivity.isImmersiveInterface()) {
|
||||||
|
mRecyclerView.setPadding(0, 0, 0, mActivity.getNavBarHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mAdapter = new PrivateMessageRecycleViewAdapter(mActivity, mRetrofit.getRetrofit(), mCustomThemeWrapper, mAccessToken, mLemmyPrivateMessageAPI, () -> mMessageViewModel.refresh());
|
||||||
|
mLinearLayoutManager = new LinearLayoutManagerBugFixed(mActivity);
|
||||||
|
mRecyclerView.setLayoutManager(mLinearLayoutManager);
|
||||||
|
mRecyclerView.setAdapter(mAdapter);
|
||||||
|
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mActivity, mLinearLayoutManager.getOrientation());
|
||||||
|
mRecyclerView.addItemDecoration(dividerItemDecoration);
|
||||||
|
|
||||||
|
if (mActivity instanceof RecyclerViewContentScrollingInterface) {
|
||||||
|
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||||
|
if (dy > 0) {
|
||||||
|
((RecyclerViewContentScrollingInterface) mActivity).contentScrollDown();
|
||||||
|
} else if (dy < 0) {
|
||||||
|
((RecyclerViewContentScrollingInterface) mActivity).contentScrollUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateMessageViewModel.Factory factory = new PrivateMessageViewModel.Factory(mRetrofit.getRetrofit(),
|
||||||
|
getResources().getConfiguration().locale, mAccessToken, mLemmyPrivateMessageAPI);
|
||||||
|
mMessageViewModel = new ViewModelProvider(this, factory).get(PrivateMessageViewModel.class);
|
||||||
|
mMessageViewModel.getPrivateMessages().observe(getViewLifecycleOwner(), messages -> mAdapter.submitList(messages));
|
||||||
|
|
||||||
|
|
||||||
|
mMessageViewModel.getInitialLoadState().observe(getViewLifecycleOwner(), networkState -> {
|
||||||
|
if (networkState.getStatus().equals(NetworkState.Status.SUCCESS)) {
|
||||||
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
|
} else if (networkState.getStatus().equals(NetworkState.Status.FAILED)) {
|
||||||
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
|
mFetchMessageInfoLinearLayout.setOnClickListener(view -> {
|
||||||
|
mFetchMessageInfoLinearLayout.setVisibility(View.GONE);
|
||||||
|
mMessageViewModel.refresh();
|
||||||
|
mAdapter.setNetworkState(null);
|
||||||
|
});
|
||||||
|
showErrorView(R.string.load_messages_failed);
|
||||||
|
} else {
|
||||||
|
mSwipeRefreshLayout.setRefreshing(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
mSwipeRefreshLayout.setOnRefreshListener(this::onRefresh);
|
||||||
|
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showErrorView(int stringResId) {
|
||||||
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
|
mFetchMessageInfoLinearLayout.setVisibility(View.VISIBLE);
|
||||||
|
mFetchMessageInfoTextView.setText(stringResId);
|
||||||
|
mGlide.load(R.drawable.error_image).into(mFetchMessageInfoImageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyTheme() {
|
||||||
|
mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(mCustomThemeWrapper.getCircularProgressBarBackground());
|
||||||
|
mSwipeRefreshLayout.setColorSchemeColors(mCustomThemeWrapper.getColorAccent());
|
||||||
|
mFetchMessageInfoTextView.setTextColor(mCustomThemeWrapper.getSecondaryTextColor());
|
||||||
|
if (mActivity.typeface != null) {
|
||||||
|
mFetchMessageInfoTextView.setTypeface(mActivity.typeface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void goBackToTop() {
|
||||||
|
if (mLinearLayoutManager != null) {
|
||||||
|
mLinearLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markAllMessagesRead() {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
mAdapter.setMarkAllMessagesAsRead(true);
|
||||||
|
|
||||||
|
int previousPosition = -1;
|
||||||
|
if (mLinearLayoutManager != null) {
|
||||||
|
previousPosition = mLinearLayoutManager.findFirstVisibleItemPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
|
||||||
|
mRecyclerView.setAdapter(null);
|
||||||
|
mRecyclerView.setLayoutManager(null);
|
||||||
|
mRecyclerView.setAdapter(mAdapter);
|
||||||
|
mRecyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
|
if (previousPosition > 0) {
|
||||||
|
mRecyclerView.scrollToPosition(previousPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onRefresh() {
|
||||||
|
mMessageViewModel.refresh();
|
||||||
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrivateMessage getMessageByIndex(int index) {
|
||||||
|
if (mMessageViewModel == null || index < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
PagedList<PrivateMessage> messages = mMessageViewModel.getPrivateMessages().getValue();
|
||||||
|
if (messages == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (index >= messages.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
EventBus.getDefault().unregister(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
mActivity = (BaseActivity) context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onRepliedToPrivateMessageEvent(RepliedToPrivateMessageEvent repliedToPrivateMessageEvent) {
|
||||||
|
/* if (mAdapter != null && mWhere.equals(FetchMessage.WHERE_MESSAGES)) {
|
||||||
|
mAdapter.updateMessageReply(repliedToPrivateMessageEvent.newReply, repliedToPrivateMessageEvent.messagePosition);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
@ -220,9 +220,6 @@ public class ParsePost {
|
|||||||
String authorAvatar = (!data.getJSONObject("creator").isNull("avatar")) ? data.getJSONObject("creator").getString("avatar") : null;
|
String authorAvatar = (!data.getJSONObject("creator").isNull("avatar")) ? data.getJSONObject("creator").getString("avatar") : null;
|
||||||
|
|
||||||
Uri uri = Uri.parse(url);
|
Uri uri = Uri.parse(url);
|
||||||
if (uri.getAuthority() == null) {
|
|
||||||
Log.e("ParsePost", "parseData:" + uri.toString());
|
|
||||||
}
|
|
||||||
String path = uri.getPath();
|
String path = uri.getPath();
|
||||||
boolean isVideo = path.endsWith(".mp4") || path.endsWith(".webm") || path.endsWith(".gifv");
|
boolean isVideo = path.endsWith(".mp4") || path.endsWith(".webm") || path.endsWith(".gifv");
|
||||||
|
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
package eu.toldi.infinityforlemmy.utils;
|
package eu.toldi.infinityforlemmy.utils;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
public class LemmyUtils {
|
public class LemmyUtils {
|
||||||
public static String actorID2FullName(String url) {
|
public static String actorID2FullName(String url) {
|
||||||
String[] splitURL = url.split("/");
|
String[] splitURL = url.split("/");
|
||||||
@ -21,4 +30,25 @@ public class LemmyUtils {
|
|||||||
String domain = splitQualifiedName[1];
|
String domain = splitQualifiedName[1];
|
||||||
return "https://" + domain + "/u/" + userName;
|
return "https://" + domain + "/u/" + userName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Long dateStringToMills(String dateStr) {
|
||||||
|
long postTimeMillis = 0;
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
|
postTimeMillis = ZonedDateTime.parse(dateStr,
|
||||||
|
DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.of("Z"))).toInstant().toEpochMilli();
|
||||||
|
} else {
|
||||||
|
dateStr = dateStr.substring(0, dateStr.lastIndexOf(".") + 4) + 'Z';
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
|
||||||
|
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
|
try {
|
||||||
|
Date date = sdf.parse(dateStr);
|
||||||
|
if (date != null) {
|
||||||
|
postTimeMillis = date.getTime();
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return postTimeMillis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,11 @@ public class UploadImageUtils {
|
|||||||
if (uploadMediaResponse.isSuccessful()) {
|
if (uploadMediaResponse.isSuccessful()) {
|
||||||
JSONObject responseObject = new JSONObject(uploadMediaResponse.body());
|
JSONObject responseObject = new JSONObject(uploadMediaResponse.body());
|
||||||
String fileName = responseObject.getJSONArray("files").getJSONObject(0).getString("file");
|
String fileName = responseObject.getJSONArray("files").getJSONObject(0).getString("file");
|
||||||
return mRetrofit.getBaseURL() + "/pictrs/image/" + fileName;
|
String baseURL = mRetrofit.getBaseURL();
|
||||||
|
if (baseURL.endsWith("/")) {
|
||||||
|
baseURL = baseURL.substring(0, baseURL.length() - 1);
|
||||||
|
}
|
||||||
|
return baseURL + "/pictrs/image/" + fileName;
|
||||||
} else {
|
} else {
|
||||||
return "Error: " + uploadMediaResponse.code();
|
return "Error: " + uploadMediaResponse.code();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.dto
|
||||||
|
|
||||||
|
data class PrivateMessageDTO(val recipient_id: Int, val content: String, val auth: String)
|
||||||
|
|
||||||
|
data class PrivateMessageUpdateDTO(
|
||||||
|
val private_message_id: Int,
|
||||||
|
val auth: String,
|
||||||
|
val content: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class PrivateMessageDeleteDTO(
|
||||||
|
val private_message_id: Int,
|
||||||
|
val auth: String,
|
||||||
|
val deleted: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
data class PrivateMessageReadDTO(val private_message_id: Int, val auth: String, val read: Boolean)
|
||||||
|
|
||||||
|
data class PrivateMessageReportDTO(
|
||||||
|
val private_message_id: Int,
|
||||||
|
val auth: String,
|
||||||
|
val reason: String
|
||||||
|
)
|
@ -0,0 +1,153 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.privatemessage
|
||||||
|
|
||||||
|
import eu.toldi.infinityforlemmy.RetrofitHolder
|
||||||
|
import eu.toldi.infinityforlemmy.apis.LemmyAPI
|
||||||
|
import eu.toldi.infinityforlemmy.dto.PrivateMessageDTO
|
||||||
|
import eu.toldi.infinityforlemmy.dto.PrivateMessageReadDTO
|
||||||
|
import eu.toldi.infinityforlemmy.utils.LemmyUtils
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class LemmyPrivateMessageAPI(val retrofitHolder: RetrofitHolder) {
|
||||||
|
|
||||||
|
|
||||||
|
fun fetchPrivateMessages(
|
||||||
|
auth: String,
|
||||||
|
page: Int,
|
||||||
|
listener: PrivateMessageFetchedListener,
|
||||||
|
limit: Int = 25,
|
||||||
|
unreadOnly: Boolean = false
|
||||||
|
) {
|
||||||
|
val api = retrofitHolder.retrofit.create(LemmyAPI::class.java)
|
||||||
|
api.privateMessagesList(page, limit, unreadOnly, auth).enqueue(
|
||||||
|
object : retrofit2.Callback<String> {
|
||||||
|
override fun onResponse(
|
||||||
|
call: retrofit2.Call<String>,
|
||||||
|
response: retrofit2.Response<String>
|
||||||
|
) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
val jresponse = JSONObject(response.body()!!);
|
||||||
|
val privateMessages = jresponse.getJSONArray("private_messages")
|
||||||
|
val privateMessageList = mutableListOf<PrivateMessage>()
|
||||||
|
for (i in 0 until privateMessages.length()) {
|
||||||
|
val privateMessage =
|
||||||
|
parsePrivateMessage(privateMessages.getJSONObject(i))
|
||||||
|
privateMessageList.add(privateMessage)
|
||||||
|
}
|
||||||
|
listener.onPrivateMessageFetchedSuccess(privateMessageList)
|
||||||
|
} else {
|
||||||
|
listener.onPrivateMessageFetchedError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: retrofit2.Call<String>, t: Throwable) {
|
||||||
|
listener.onPrivateMessageFetchedError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun markPrivateMessageAsRead(
|
||||||
|
auth: String,
|
||||||
|
privateMessageId: Int,
|
||||||
|
listener: PrivateMessageMarkedAsReadListener
|
||||||
|
) {
|
||||||
|
val api = retrofitHolder.retrofit.create(LemmyAPI::class.java)
|
||||||
|
api.privateMessageMarkAsRead(PrivateMessageReadDTO(privateMessageId, auth, true)).enqueue(
|
||||||
|
object : retrofit2.Callback<String> {
|
||||||
|
override fun onResponse(
|
||||||
|
call: retrofit2.Call<String>,
|
||||||
|
response: retrofit2.Response<String>
|
||||||
|
) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
listener.onPrivateMessageMarkedAsReadSuccess()
|
||||||
|
} else {
|
||||||
|
listener.onPrivateMessageMarkedAsReadError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: retrofit2.Call<String>, t: Throwable) {
|
||||||
|
listener.onPrivateMessageMarkedAsReadError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendPrivateMessage(
|
||||||
|
auth: String,
|
||||||
|
recipientId: Int,
|
||||||
|
content: String,
|
||||||
|
listener: PrivateMessageSentListener
|
||||||
|
) {
|
||||||
|
val api = retrofitHolder.retrofit.create(LemmyAPI::class.java)
|
||||||
|
|
||||||
|
api.privateMessageSend(PrivateMessageDTO(recipientId, content, auth)).enqueue(
|
||||||
|
object : retrofit2.Callback<String> {
|
||||||
|
override fun onResponse(
|
||||||
|
call: retrofit2.Call<String>,
|
||||||
|
response: retrofit2.Response<String>
|
||||||
|
) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
listener.onPrivateMessageSentSuccess(
|
||||||
|
parsePrivateMessage(
|
||||||
|
JSONObject(response.body()!!).getJSONObject(
|
||||||
|
"private_message_view"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
listener.onPrivateMessageSentError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: retrofit2.Call<String>, t: Throwable) {
|
||||||
|
listener.onPrivateMessageSentError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PrivateMessageSentListener {
|
||||||
|
fun onPrivateMessageSentSuccess(privateMessage: PrivateMessage)
|
||||||
|
fun onPrivateMessageSentError()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PrivateMessageMarkedAsReadListener {
|
||||||
|
fun onPrivateMessageMarkedAsReadSuccess()
|
||||||
|
fun onPrivateMessageMarkedAsReadError()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface PrivateMessageFetchedListener {
|
||||||
|
fun onPrivateMessageFetchedSuccess(privateMessage: List<PrivateMessage>)
|
||||||
|
fun onPrivateMessageFetchedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parsePrivateMessage(jsonObject: JSONObject): PrivateMessage {
|
||||||
|
|
||||||
|
val privateMessage = jsonObject.getJSONObject("private_message")
|
||||||
|
val creator = jsonObject.getJSONObject("creator")
|
||||||
|
val recipient = jsonObject.getJSONObject("recipient")
|
||||||
|
val updated = privateMessage.optString("updated", "")
|
||||||
|
|
||||||
|
return PrivateMessage(
|
||||||
|
id = privateMessage.getInt("id"),
|
||||||
|
creatorId = privateMessage.getInt("creator_id"),
|
||||||
|
recipientId = privateMessage.getInt("recipient_id"),
|
||||||
|
content = privateMessage.getString("content"),
|
||||||
|
deleted = privateMessage.getBoolean("deleted"),
|
||||||
|
read = privateMessage.getBoolean("read"),
|
||||||
|
published = LemmyUtils.dateStringToMills(privateMessage.getString("published")),
|
||||||
|
updated = if (updated == "") {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
LemmyUtils.dateStringToMills(updated)
|
||||||
|
},
|
||||||
|
creatorName = creator.getString("name"),
|
||||||
|
creatorAvatar = creator.optString("avatar", ""),
|
||||||
|
creatorQualifiedName = LemmyUtils.actorID2FullName(creator.getString("actor_id")),
|
||||||
|
recipientName = recipient.getString("name"),
|
||||||
|
recipientAvatar = recipient.optString("avatar", ""),
|
||||||
|
recipientQualifiedName = LemmyUtils.actorID2FullName(recipient.getString("actor_id"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.privatemessage
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.Parcelable
|
||||||
|
|
||||||
|
data class PrivateMessage(
|
||||||
|
val id: Int,
|
||||||
|
val creatorId: Int,
|
||||||
|
val recipientId: Int,
|
||||||
|
val content: String,
|
||||||
|
val deleted: Boolean,
|
||||||
|
var read: Boolean,
|
||||||
|
val published: Long,
|
||||||
|
val updated: Long?,
|
||||||
|
val creatorName: String,
|
||||||
|
val creatorAvatar: String,
|
||||||
|
val creatorQualifiedName: String,
|
||||||
|
val recipientName: String,
|
||||||
|
val recipientAvatar: String,
|
||||||
|
val recipientQualifiedName: String
|
||||||
|
) : Parcelable {
|
||||||
|
fun addReply(reply: PrivateMessage) {
|
||||||
|
replies.add(reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
val replies = mutableListOf<PrivateMessage>()
|
||||||
|
|
||||||
|
constructor(parcel: Parcel) : this(
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readString()!!,
|
||||||
|
parcel.readByte() != 0.toByte(),
|
||||||
|
parcel.readByte() != 0.toByte(),
|
||||||
|
parcel.readLong(),
|
||||||
|
parcel.readValue(Long::class.java.classLoader) as? Long,
|
||||||
|
parcel.readString()!!,
|
||||||
|
parcel.readString()!!,
|
||||||
|
parcel.readString()!!,
|
||||||
|
parcel.readString()!!,
|
||||||
|
parcel.readString()!!,
|
||||||
|
parcel.readString()!!
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeInt(id)
|
||||||
|
parcel.writeInt(creatorId)
|
||||||
|
parcel.writeInt(recipientId)
|
||||||
|
parcel.writeString(content)
|
||||||
|
parcel.writeByte(if (deleted) 1 else 0)
|
||||||
|
parcel.writeByte(if (read) 1 else 0)
|
||||||
|
parcel.writeLong(published)
|
||||||
|
parcel.writeValue(updated)
|
||||||
|
parcel.writeString(creatorName)
|
||||||
|
parcel.writeString(creatorAvatar)
|
||||||
|
parcel.writeString(creatorQualifiedName)
|
||||||
|
parcel.writeString(recipientName)
|
||||||
|
parcel.writeString(recipientAvatar)
|
||||||
|
parcel.writeString(recipientQualifiedName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<PrivateMessage> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): PrivateMessage {
|
||||||
|
return PrivateMessage(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<PrivateMessage?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.privatemessage
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.paging.PageKeyedDataSource
|
||||||
|
import eu.toldi.infinityforlemmy.NetworkState
|
||||||
|
|
||||||
|
|
||||||
|
class PrivateMessageDataSource(
|
||||||
|
private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI,
|
||||||
|
private val accessToken: String
|
||||||
|
) : PageKeyedDataSource<Int, PrivateMessage>() {
|
||||||
|
|
||||||
|
val initialLoadStateLiveData = MutableLiveData<NetworkState>()
|
||||||
|
|
||||||
|
override fun loadInitial(
|
||||||
|
params: LoadInitialParams<Int>,
|
||||||
|
callback: LoadInitialCallback<Int, PrivateMessage>
|
||||||
|
) {
|
||||||
|
mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, 1, object :
|
||||||
|
LemmyPrivateMessageAPI.PrivateMessageFetchedListener {
|
||||||
|
override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) {
|
||||||
|
initialLoadStateLiveData.postValue(NetworkState.LOADED)
|
||||||
|
if (privateMessages.isEmpty()) {
|
||||||
|
callback.onResult(ArrayList(), null, null)
|
||||||
|
} else {
|
||||||
|
callback.onResult(privateMessages, null, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrivateMessageFetchedError() {
|
||||||
|
initialLoadStateLiveData.postValue(
|
||||||
|
NetworkState(
|
||||||
|
NetworkState.Status.FAILED,
|
||||||
|
"Error fetching messages"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadAfter(
|
||||||
|
params: LoadParams<Int>,
|
||||||
|
callback: LoadCallback<Int, PrivateMessage>
|
||||||
|
) {
|
||||||
|
mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, params.key, object :
|
||||||
|
LemmyPrivateMessageAPI.PrivateMessageFetchedListener {
|
||||||
|
override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) {
|
||||||
|
initialLoadStateLiveData.postValue(NetworkState.LOADED)
|
||||||
|
if (privateMessages.isEmpty()) {
|
||||||
|
callback.onResult(ArrayList(), null)
|
||||||
|
} else {
|
||||||
|
callback.onResult(privateMessages, params.key + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrivateMessageFetchedError() {
|
||||||
|
initialLoadStateLiveData.postValue(
|
||||||
|
NetworkState(
|
||||||
|
NetworkState.Status.FAILED,
|
||||||
|
"Error fetching messages"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadBefore(
|
||||||
|
params: LoadParams<Int>,
|
||||||
|
callback: LoadCallback<Int, PrivateMessage>
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refresh() {
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.privatemessage
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.paging.DataSource
|
||||||
|
|
||||||
|
|
||||||
|
class PrivateMessageDataSourceFactory(
|
||||||
|
private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI,
|
||||||
|
private val accessToken: String
|
||||||
|
) : DataSource.Factory<Int, PrivateMessage>() {
|
||||||
|
|
||||||
|
val dataSourceLiveData = MutableLiveData<PrivateMessageDataSource>()
|
||||||
|
|
||||||
|
override fun create(): DataSource<Int, PrivateMessage> {
|
||||||
|
val dataSource = PrivateMessageDataSource(mLemmyPrivateMessageAPI, accessToken)
|
||||||
|
dataSourceLiveData.postValue(dataSource)
|
||||||
|
return dataSource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
|||||||
|
package eu.toldi.infinityforlemmy.privatemessage
|
||||||
|
|
||||||
|
import androidx.lifecycle.Transformations
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.paging.LivePagedListBuilder
|
||||||
|
import androidx.paging.PagedList
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
|
class PrivateMessageViewModel(
|
||||||
|
private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI,
|
||||||
|
private val accessToken: String
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
private val dataSourceFactory =
|
||||||
|
PrivateMessageDataSourceFactory(mLemmyPrivateMessageAPI, accessToken)
|
||||||
|
|
||||||
|
val privateMessages = LivePagedListBuilder(
|
||||||
|
dataSourceFactory, PagedList.Config.Builder()
|
||||||
|
.setPageSize(20)
|
||||||
|
.setEnablePlaceholders(false)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val initialLoadState = Transformations.switchMap(dataSourceFactory.dataSourceLiveData) {
|
||||||
|
it.initialLoadStateLiveData
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refresh() {
|
||||||
|
dataSourceFactory.dataSourceLiveData.value?.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Factory(
|
||||||
|
private val retrofit: Retrofit,
|
||||||
|
private val locale: Locale,
|
||||||
|
private val accessToken: String,
|
||||||
|
private val lemmyPrivateMessageAPI: LemmyPrivateMessageAPI
|
||||||
|
) :
|
||||||
|
ViewModelProvider.NewInstanceFactory() {
|
||||||
|
|
||||||
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
|
return PrivateMessageViewModel(
|
||||||
|
lemmyPrivateMessageAPI,
|
||||||
|
accessToken,
|
||||||
|
) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,77 +23,75 @@
|
|||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.core.widget.NestedScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
android:orientation="vertical">
|
android:layout_weight="1">
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:id="@+id/username_edit_text_send_private_message_activity"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="#00000000"
|
android:orientation="vertical">
|
||||||
android:gravity="top"
|
|
||||||
android:hint="@string/send_message_username_hint"
|
|
||||||
android:inputType="textCapSentences|textMultiLine"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingEnd="16dp"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:textColor="?attr/primaryTextColor"
|
|
||||||
android:textSize="?attr/content_font_18"
|
|
||||||
android:fontFamily="?attr/content_font_family" />
|
|
||||||
|
|
||||||
<View
|
<EditText
|
||||||
android:id="@+id/divider_1_send_private_message_activity"
|
android:id="@+id/username_edit_text_send_private_message_activity"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="16dp" />
|
android:background="#00000000"
|
||||||
|
android:fontFamily="?attr/content_font_family"
|
||||||
|
android:gravity="top"
|
||||||
|
android:hint="@string/send_message_username_hint"
|
||||||
|
android:inputType="textCapSentences|textMultiLine"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="?attr/content_font_18" />
|
||||||
|
|
||||||
<EditText
|
<View
|
||||||
android:id="@+id/subjet_edit_text_send_private_message_activity"
|
android:id="@+id/divider_1_send_private_message_activity"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="1dp"
|
||||||
android:background="#00000000"
|
android:layout_marginBottom="16dp" />
|
||||||
android:gravity="top"
|
|
||||||
android:hint="@string/send_message_subject_hint"
|
|
||||||
android:inputType="textCapSentences|textMultiLine"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingEnd="16dp"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:textColor="?attr/primaryTextColor"
|
|
||||||
android:textSize="?attr/content_font_18"
|
|
||||||
android:maxLength="100"
|
|
||||||
android:fontFamily="?attr/content_font_family" />
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider_2_send_private_message_activity"
|
android:id="@+id/divider_2_send_private_message_activity"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:layout_marginBottom="16dp" />
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/content_edit_text_send_private_message_activity"
|
android:id="@+id/content_edit_text_send_private_message_activity"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="#00000000"
|
android:background="#00000000"
|
||||||
android:gravity="top"
|
android:fontFamily="?attr/content_font_family"
|
||||||
android:hint="@string/send_message_content_hint"
|
android:gravity="top"
|
||||||
android:inputType="textCapSentences|textMultiLine"
|
android:hint="@string/send_message_content_hint"
|
||||||
android:paddingStart="16dp"
|
android:inputType="textCapSentences|textMultiLine"
|
||||||
android:paddingEnd="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingBottom="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:textColor="?attr/primaryTextColor"
|
android:paddingBottom="16dp"
|
||||||
android:textSize="?attr/content_font_18"
|
android:textColor="?attr/primaryTextColor"
|
||||||
android:fontFamily="?attr/content_font_family" />
|
android:textSize="?attr/content_font_18" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/markdown_bottom_bar_recycler_view_send_private_message_activity"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="horizontal"
|
||||||
|
android:layout_gravity="bottom" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
Loading…
Reference in New Issue
Block a user