some changes for chat

This commit is contained in:
Thomas 2023-02-14 16:21:04 +01:00
parent c001b83fb4
commit c29a2bd07b
11 changed files with 511 additions and 76 deletions

View File

@ -77,6 +77,8 @@ android {
'src/main/res/menus/peertube',
'src/main/res/menus',
'src/main/res/values',
'src/main/res'
]
}

View File

@ -1648,7 +1648,6 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
holder.binding.sensitiveMedia.setChecked(statusDraft.sensitive);
holder.binding.content.addTextChangedListener(initializeTextWatcher(holder));
holder.binding.buttonPoll.setOnClickListener(v -> displayPollPopup(holder, statusDraft, position));
holder.binding.buttonPoll.setOnClickListener(v -> displayPollPopup(holder, statusDraft, position));
if (instanceInfo == null) {
return;
}

View File

@ -211,7 +211,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
//--- DATE ---
holder.binding.lastMessageDate.setText(Helper.dateDiff(context, conversation.last_status.created_at));
boolean chatMode = sharedpreferences.getBoolean(context.getString(R.string.SET_CHAT_FOR_CONVERSATION), false);
boolean chatMode = sharedpreferences.getBoolean(context.getString(R.string.SET_CHAT_FOR_CONVERSATION), true);
holder.binding.statusContent.setOnClickListener(v -> {
Intent intent;
if (chatMode) {

View File

@ -21,20 +21,29 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.RecyclerView;
@ -44,20 +53,25 @@ import org.jetbrains.annotations.NotNull;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.databinding.DrawerStatusChatBinding;
import app.fedilab.android.databinding.LayoutMediaBinding;
import app.fedilab.android.databinding.LayoutPollItemBinding;
import app.fedilab.android.mastodon.activities.MediaActivity;
import app.fedilab.android.mastodon.client.entities.api.Attachment;
import app.fedilab.android.mastodon.client.entities.api.Poll;
import app.fedilab.android.mastodon.client.entities.api.Status;
import app.fedilab.android.mastodon.helper.Helper;
import app.fedilab.android.mastodon.helper.LongClickLinkMovementMethod;
import app.fedilab.android.mastodon.helper.MastodonHelper;
import app.fedilab.android.mastodon.helper.MediaHelper;
import app.fedilab.android.mastodon.helper.ThemeHelper;
import app.fedilab.android.mastodon.viewmodel.mastodon.StatusesVM;
public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@ -81,7 +95,7 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
StatusChatViewHolder holder,
RecyclerView.Adapter<RecyclerView.ViewHolder> adapter,
int mediaPosition, float mediaW, float mediaH, float ratio,
Status statusToDeal, Attachment attachment) {
Status status, Attachment attachment) {
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
final int timeout = sharedpreferences.getInt(context.getString(R.string.SET_NSFW_TIMEOUT), 5);
boolean long_press_media = sharedpreferences.getBoolean(context.getString(R.string.SET_LONG_PRESS_STORE_MEDIA), false);
@ -96,9 +110,9 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
float focusX = 0.f;
float focusY = 0.f;
if (statusToDeal.media_attachments.get(0).meta != null && statusToDeal.media_attachments.get(0).meta.focus != null) {
focusX = statusToDeal.media_attachments.get(0).meta.focus.x;
focusY = statusToDeal.media_attachments.get(0).meta.focus.y;
if (status.media_attachments.get(0).meta != null && status.media_attachments.get(0).meta.focus != null) {
focusX = status.media_attachments.get(0).meta.focus.x;
focusY = status.media_attachments.get(0).meta.focus.y;
}
if (attachment.description != null && attachment.description.trim().length() > 0) {
layoutMediaBinding.media.setContentDescription(attachment.description.trim());
@ -132,22 +146,22 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
layoutMediaBinding.viewDescription.setVisibility(View.GONE);
}
RequestBuilder<Drawable> requestBuilder = prepareRequestBuilder(context, attachment, mediaW * ratio, mediaH * ratio, focusX, focusY, statusToDeal.sensitive, false);
if (!statusToDeal.sensitive || expand_media) {
RequestBuilder<Drawable> requestBuilder = prepareRequestBuilder(context, attachment, mediaW * ratio, mediaH * ratio, focusX, focusY, status.sensitive, false);
if (!status.sensitive || expand_media) {
layoutMediaBinding.viewHide.setImageResource(R.drawable.ic_baseline_visibility_24);
} else {
layoutMediaBinding.viewHide.setImageResource(R.drawable.ic_baseline_visibility_off_24);
}
requestBuilder.load(attachment.preview_url).into(layoutMediaBinding.media);
if (statusToDeal.sensitive) {
if (status.sensitive) {
Helper.changeDrawableColor(context, layoutMediaBinding.viewHide, ThemeHelper.getAttColor(context, R.attr.colorError));
} else {
Helper.changeDrawableColor(context, layoutMediaBinding.viewHide, R.color.white);
}
layoutMediaBinding.media.setOnClickListener(v -> {
if (statusToDeal.sensitive && !expand_media) {
statusToDeal.sensitive = false;
if (status.sensitive && !expand_media) {
status.sensitive = false;
int position = holder.getBindingAdapterPosition();
adapter.notifyItemChanged(position);
@ -157,7 +171,7 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
}
public void onFinish() {
statusToDeal.sensitive = true;
status.sensitive = true;
adapter.notifyItemChanged(position);
}
}.start();
@ -167,15 +181,15 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
Intent mediaIntent = new Intent(context, MediaActivity.class);
Bundle b = new Bundle();
b.putInt(Helper.ARG_MEDIA_POSITION, mediaPosition);
b.putSerializable(Helper.ARG_MEDIA_ARRAY, new ArrayList<>(statusToDeal.media_attachments));
b.putSerializable(Helper.ARG_MEDIA_ARRAY, new ArrayList<>(status.media_attachments));
mediaIntent.putExtras(b);
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation((Activity) context, layoutMediaBinding.media, statusToDeal.media_attachments.get(0).url);
.makeSceneTransitionAnimation((Activity) context, layoutMediaBinding.media, status.media_attachments.get(0).url);
// start the new activity
context.startActivity(mediaIntent, options.toBundle());
});
layoutMediaBinding.viewHide.setOnClickListener(v -> {
statusToDeal.sensitive = !statusToDeal.sensitive;
status.sensitive = !status.sensitive;
adapter.notifyItemChanged(holder.getBindingAdapterPosition());
});
@ -208,7 +222,7 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
StatusChatViewHolder holder = (StatusChatViewHolder) viewHolder;
Status status = statusList.get(position);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
holder.binding.messageContent.setText(
status.getSpanContent(context,
new WeakReference<>(holder.binding.messageContent),
@ -228,23 +242,190 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
MastodonHelper.loadPPMastodon(holder.binding.userPp, status.account);
holder.binding.date.setText(Helper.longDateToString(status.created_at));
//Owner account
int textColor;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
if (status.account.id.equals(MainActivity.currentUserID)) {
holder.binding.mainContainer.setBackgroundResource(R.drawable.bubble_right_tail);
textColor = R.attr.colorOnPrimary;
layoutParams.setMargins((int) Helper.convertDpToPixel(50, context), (int) Helper.convertDpToPixel(12, context), 0, 0);
layoutParams.setMargins((int) Helper.convertDpToPixel(50, context), (int) Helper.convertDpToPixel(12, context), 0, 0);
holder.binding.date.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
holder.binding.messageContent.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
holder.binding.userName.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
} else {
holder.binding.mainContainer.setBackgroundResource(R.drawable.bubble_left_tail);
layoutParams.setMargins(0, (int) Helper.convertDpToPixel(12, context), (int) Helper.convertDpToPixel(50, context), 0);
textColor = R.attr.colorOnSecondary;
holder.binding.date.setTextColor(ContextCompat.getColor(context, R.color.black));
holder.binding.messageContent.setTextColor(ContextCompat.getColor(context, R.color.black));
holder.binding.userName.setTextColor(ContextCompat.getColor(context, R.color.black));
}
holder.binding.mainContainer.setLayoutParams(layoutParams);
holder.binding.date.setTextColor(ThemeHelper.getAttColor(context, textColor));
holder.binding.messageContent.setTextColor(ThemeHelper.getAttColor(context, textColor));
holder.binding.userName.setTextColor(ThemeHelper.getAttColor(context, textColor));
final float scale = sharedpreferences.getFloat(context.getString(R.string.SET_FONT_SCALE), 1.1f);
if (status.poll != null && status.poll.options != null) {
holder.binding.poll.pollInfo.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
holder.binding.poll.refresh.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class);
if (status.poll.voted || status.poll.expired) {
holder.binding.poll.submitVote.setVisibility(View.GONE);
holder.binding.poll.rated.setVisibility(View.VISIBLE);
holder.binding.poll.multipleChoice.setVisibility(View.GONE);
holder.binding.poll.singleChoiceRadioGroup.setVisibility(View.GONE);
int greaterValue = 0;
for (Poll.PollItem pollItem : status.poll.options) {
if (pollItem.votes_count > greaterValue)
greaterValue = pollItem.votes_count;
}
holder.binding.poll.rated.removeAllViews();
List<Integer> ownvotes = status.poll.own_votes;
int j = 0;
if (status.poll.voters_count == 0 && status.poll.votes_count > 0) {
status.poll.voters_count = status.poll.votes_count;
}
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
for (Poll.PollItem pollItem : status.poll.options) {
@NonNull LayoutPollItemBinding pollItemBinding = LayoutPollItemBinding.inflate(inflater, holder.binding.poll.rated, true);
double value = ((double) (pollItem.votes_count * 100) / (double) status.poll.voters_count);
pollItemBinding.pollItemPercent.setText(String.format("%s %%", (int) value));
pollItemBinding.pollItemText.setText(
pollItem.getSpanTitle(context, status,
new WeakReference<>(pollItemBinding.pollItemText)),
TextView.BufferType.SPANNABLE);
pollItemBinding.pollItemPercent.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
pollItemBinding.pollItemText.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
pollItemBinding.pollItemValue.setProgress((int) value);
if (pollItem.votes_count == greaterValue) {
pollItemBinding.pollItemPercent.setTypeface(null, Typeface.BOLD);
pollItemBinding.pollItemText.setTypeface(null, Typeface.BOLD);
}
if (ownvotes != null && ownvotes.contains(j)) {
Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_baseline_check_24);
assert img != null;
img.setColorFilter(ThemeHelper.getAttColor(context, R.attr.colorPrimary), PorterDuff.Mode.SRC_IN);
img.setBounds(0, 0, (int) (20 * scale + 0.5f), (int) (20 * scale + 0.5f));
pollItemBinding.pollItemText.setCompoundDrawables(null, null, img, null);
}
j++;
}
} else {
if (status.poll.voters_count == 0 && status.poll.votes_count > 0) {
status.poll.voters_count = status.poll.votes_count;
}
holder.binding.poll.rated.setVisibility(View.GONE);
holder.binding.poll.submitVote.setVisibility(View.VISIBLE);
if (status.poll.multiple) {
if ((holder.binding.poll.multipleChoice).getChildCount() > 0)
(holder.binding.poll.multipleChoice).removeAllViews();
for (Poll.PollItem pollOption : status.poll.options) {
CheckBox cb = new CheckBox(context);
cb.setText(
pollOption.getSpanTitle(context, status,
new WeakReference<>(cb)),
TextView.BufferType.SPANNABLE);
holder.binding.poll.multipleChoice.addView(cb);
cb.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
}
holder.binding.poll.multipleChoice.setVisibility(View.VISIBLE);
holder.binding.poll.singleChoiceRadioGroup.setVisibility(View.GONE);
} else {
if ((holder.binding.poll.singleChoiceRadioGroup).getChildCount() > 0)
(holder.binding.poll.singleChoiceRadioGroup).removeAllViews();
for (Poll.PollItem pollOption : status.poll.options) {
RadioButton rb = new RadioButton(context);
rb.setText(
pollOption.getSpanTitle(context, status,
new WeakReference<>(rb)),
TextView.BufferType.SPANNABLE);
rb.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnSecondary));
holder.binding.poll.singleChoiceRadioGroup.addView(rb);
}
holder.binding.poll.singleChoiceRadioGroup.setVisibility(View.VISIBLE);
holder.binding.poll.multipleChoice.setVisibility(View.GONE);
}
holder.binding.poll.submitVote.setVisibility(View.VISIBLE);
holder.binding.poll.submitVote.setOnClickListener(v -> {
int[] choice;
if (status.poll.multiple) {
ArrayList<Integer> choices = new ArrayList<>();
int choicesCount = holder.binding.poll.multipleChoice.getChildCount();
for (int i1 = 0; i1 < choicesCount; i1++) {
if (holder.binding.poll.multipleChoice.getChildAt(i1) != null && holder.binding.poll.multipleChoice.getChildAt(i1) instanceof CheckBox) {
if (((CheckBox) holder.binding.poll.multipleChoice.getChildAt(i1)).isChecked()) {
choices.add(i1);
}
}
}
choice = new int[choices.size()];
Iterator<Integer> iterator = choices.iterator();
for (int i1 = 0; i1 < choice.length; i1++) {
choice[i1] = iterator.next();
}
if (choice.length == 0)
return;
} else {
choice = new int[1];
choice[0] = -1;
int choicesCount = holder.binding.poll.singleChoiceRadioGroup.getChildCount();
for (int i1 = 0; i1 < choicesCount; i1++) {
if (holder.binding.poll.singleChoiceRadioGroup.getChildAt(i1) != null && holder.binding.poll.singleChoiceRadioGroup.getChildAt(i1) instanceof RadioButton) {
if (((RadioButton) holder.binding.poll.singleChoiceRadioGroup.getChildAt(i1)).isChecked()) {
choice[0] = i1;
}
}
}
if (choice[0] == -1)
return;
}
//Vote on the poll
statusesVM.votePoll(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, status.poll.id, choice)
.observe((LifecycleOwner) context, poll -> {
if (poll != null) {
int i = 0;
for (Poll.PollItem item : status.poll.options) {
if (item.span_title != null) {
poll.options.get(i).span_title = item.span_title;
} else {
poll.options.get(i).span_title = new SpannableString(item.title);
}
i++;
}
status.poll = poll;
notifyItemChanged(holder.getBindingAdapterPosition());
}
});
});
}
holder.binding.poll.refreshPoll.setOnClickListener(v -> statusesVM.getPoll(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, status.poll.id)
.observe((LifecycleOwner) context, poll -> {
if (poll != null) {
//Store span elements
int i = 0;
for (Poll.PollItem item : status.poll.options) {
if (item.span_title != null) {
poll.options.get(i).span_title = item.span_title;
} else {
poll.options.get(i).span_title = new SpannableString(item.title);
}
i++;
}
status.poll = poll;
notifyItemChanged(holder.getBindingAdapterPosition());
}
}));
holder.binding.poll.pollContainer.setVisibility(View.VISIBLE);
String pollInfo = context.getResources().getQuantityString(R.plurals.number_of_voters, status.poll.voters_count, status.poll.voters_count);
if (status.poll.expired) {
pollInfo += " - " + context.getString(R.string.poll_finish_at, MastodonHelper.dateToStringPoll(status.poll.expires_at));
} else {
pollInfo += " - " + context.getString(R.string.poll_finish_in, MastodonHelper.dateDiffPoll(context, status.poll.expires_at));
}
holder.binding.poll.pollInfo.setText(pollInfo);
} else {
holder.binding.poll.pollContainer.setVisibility(View.GONE);
}
holder.binding.userName.setText(
status.account.getSpanDisplayName(context,
new WeakReference<>(holder.binding.userName)),

View File

@ -37,10 +37,15 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatEditText;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
@ -68,12 +73,15 @@ import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.databinding.ComposeAttachmentItemBinding;
import app.fedilab.android.databinding.ComposePollBinding;
import app.fedilab.android.databinding.ComposePollItemBinding;
import app.fedilab.android.databinding.FragmentDirectMessageBinding;
import app.fedilab.android.databinding.PopupMediaDescriptionBinding;
import app.fedilab.android.mastodon.activities.ComposeActivity;
import app.fedilab.android.mastodon.client.entities.api.Attachment;
import app.fedilab.android.mastodon.client.entities.api.Context;
import app.fedilab.android.mastodon.client.entities.api.Mention;
import app.fedilab.android.mastodon.client.entities.api.Poll;
import app.fedilab.android.mastodon.client.entities.api.Status;
import app.fedilab.android.mastodon.client.entities.app.StatusDraft;
import app.fedilab.android.mastodon.exception.DBException;
@ -84,6 +92,7 @@ import app.fedilab.android.mastodon.jobs.ComposeWorker;
import app.fedilab.android.mastodon.services.ThreadMessageService;
import app.fedilab.android.mastodon.ui.drawer.StatusDirectMessageAdapter;
import app.fedilab.android.mastodon.viewmodel.mastodon.StatusesVM;
import es.dmoral.toasty.Toasty;
public class FragmentMastodonDirectMessage extends Fragment {
@ -155,7 +164,7 @@ public class FragmentMastodonDirectMessage extends Fragment {
statusesVM.getContext(user_instance, user_token, focusedStatus.id)
.observe(getViewLifecycleOwner(), this::initializeContextView);
}
binding.buttonCloseAttachmentPanel.setOnClickListener(v -> binding.attachmentChoicesPanel.setVisibility(View.GONE));
statusCompose = new Status();
binding.buttonAttach.setOnClickListener(v -> {
@ -176,6 +185,7 @@ public class FragmentMastodonDirectMessage extends Fragment {
binding.attachmentChoicesPanel.setVisibility(View.VISIBLE);
binding.buttonAttach.setChecked(false);
});
binding.buttonPoll.setOnClickListener(v -> displayPollPopup());
binding.buttonAttachAudio.setOnClickListener(v -> {
binding.attachmentChoicesPanel.setVisibility(View.GONE);
pickupMedia(ComposeActivity.mediaType.AUDIO);
@ -195,6 +205,7 @@ public class FragmentMastodonDirectMessage extends Fragment {
binding.sendButton.setOnClickListener(v -> {
statusCompose.submitted = true;
statusCompose.text = binding.text.getText().toString();
onSubmit(prepareDraft(statusCompose, MainActivity.currentInstance, MainActivity.currentUserID));
});
LocalBroadcastManager.getInstance(requireActivity()).registerReceiver(broadcast_data, new IntentFilter(Helper.BROADCAST_DATA));
@ -300,30 +311,266 @@ public class FragmentMastodonDirectMessage extends Fragment {
return statusDraftDB;
}
private Status initiliazeStatus() {
Status status = new Status();
/**
* Display the popup to attach a poll to message
*/
private void displayPollPopup() {
AlertDialog.Builder alertPoll = new MaterialAlertDialogBuilder(requireActivity());
alertPoll.setTitle(R.string.create_poll);
ComposePollBinding composePollBinding = ComposePollBinding.inflate(LayoutInflater.from(requireActivity()), new LinearLayout(requireActivity()), false);
alertPoll.setView(composePollBinding.getRoot());
int max_entry = 4;
int max_length = 25;
final int[] pollCountItem = {2};
if (instanceInfo != null && instanceInfo.configuration != null && instanceInfo.configuration.pollsConf != null) {
max_entry = instanceInfo.configuration.pollsConf.max_options;
max_length = instanceInfo.configuration.pollsConf.max_option_chars;
} else if (instanceInfo != null && instanceInfo.poll_limits != null) {
max_entry = instanceInfo.poll_limits.max_options;
max_length = instanceInfo.poll_limits.max_option_chars;
}
InputFilter[] fArray = new InputFilter[1];
fArray[0] = new InputFilter.LengthFilter(max_length);
composePollBinding.option1.text.setFilters(fArray);
composePollBinding.option1.textLayout.setHint(getString(R.string.poll_choice_s, 1));
composePollBinding.option2.text.setFilters(fArray);
composePollBinding.option2.textLayout.setHint(getString(R.string.poll_choice_s, 2));
composePollBinding.option1.buttonRemove.setVisibility(View.GONE);
composePollBinding.option2.buttonRemove.setVisibility(View.GONE);
int finalMax_entry = max_entry;
composePollBinding.buttonAddOption.setOnClickListener(v -> {
if (pollCountItem[0] < finalMax_entry) {
ComposePollItemBinding composePollItemBinding = ComposePollItemBinding.inflate(LayoutInflater.from(composePollBinding.optionsList.getContext()), composePollBinding.optionsList, false);
if (composePollBinding.pollType.getCheckedButtonId() == R.id.poll_type_multiple)
composePollItemBinding.typeIndicator.setImageResource(R.drawable.ic_compose_poll_option_mark_multiple);
composePollItemBinding.text.setFilters(fArray);
composePollItemBinding.textLayout.setHint(getString(R.string.poll_choice_s, (pollCountItem[0] + 1)));
LinearLayoutCompat viewItem = composePollItemBinding.getRoot();
composePollBinding.optionsList.addView(composePollItemBinding.getRoot());
composePollItemBinding.buttonRemove.setOnClickListener(view -> {
composePollBinding.optionsList.removeView(viewItem);
pollCountItem[0]--;
if (pollCountItem[0] >= finalMax_entry) {
composePollBinding.buttonAddOption.setVisibility(View.GONE);
} else {
composePollBinding.buttonAddOption.setVisibility(View.VISIBLE);
}
int childCount = composePollBinding.optionsList.getChildCount();
for (int i = 0; i < childCount; i++) {
AppCompatEditText title = (composePollBinding.optionsList.getChildAt(i)).findViewById(R.id.text);
title.setHint(getString(R.string.poll_choice_s, i + 1));
}
});
}
pollCountItem[0]++;
if (pollCountItem[0] >= finalMax_entry) {
composePollBinding.buttonAddOption.setVisibility(View.GONE);
} else {
composePollBinding.buttonAddOption.setVisibility(View.VISIBLE);
}
});
ArrayAdapter<CharSequence> pollduration = ArrayAdapter.createFromResource(requireActivity(),
R.array.poll_duration, android.R.layout.simple_spinner_dropdown_item);
composePollBinding.pollDuration.setAdapter(pollduration);
composePollBinding.pollDuration.setSelection(4);
if (statusCompose != null && statusCompose.poll != null && statusCompose.poll.options != null) {
int i = 1;
for (Poll.PollItem pollItem : statusCompose.poll.options) {
if (i == 1) {
if (statusCompose.poll.multiple)
composePollBinding.option1.typeIndicator.setImageResource(R.drawable.ic_compose_poll_option_mark_multiple);
if (pollItem.title != null)
composePollBinding.option1.text.setText(pollItem.title);
} else if (i == 2) {
if (statusCompose.poll.multiple)
composePollBinding.option2.typeIndicator.setImageResource(R.drawable.ic_compose_poll_option_mark_multiple);
if (pollItem.title != null)
composePollBinding.option2.text.setText(pollItem.title);
} else {
ComposePollItemBinding composePollItemBinding = ComposePollItemBinding.inflate(LayoutInflater.from(requireActivity()), new LinearLayout(requireActivity()), false);
if (composePollBinding.pollType.getCheckedButtonId() == R.id.poll_type_multiple)
composePollItemBinding.typeIndicator.setImageResource(R.drawable.ic_compose_poll_option_mark_multiple);
else
composePollItemBinding.typeIndicator.setImageResource(R.drawable.ic_compose_poll_option_mark_single);
composePollItemBinding.text.setFilters(fArray);
composePollItemBinding.textLayout.setHint(getString(R.string.poll_choice_s, (pollCountItem[0] + 1)));
composePollItemBinding.text.setText(pollItem.title);
composePollBinding.optionsList.addView(composePollItemBinding.getRoot());
composePollItemBinding.buttonRemove.setOnClickListener(view -> {
composePollBinding.optionsList.removeView(view);
pollCountItem[0]--;
});
pollCountItem[0]++;
}
i++;
}
if (statusCompose.poll.options.size() >= max_entry) {
composePollBinding.buttonAddOption.setVisibility(View.GONE);
}
switch (statusCompose.poll.expire_in) {
case 300:
composePollBinding.pollDuration.setSelection(0);
break;
case 1800:
composePollBinding.pollDuration.setSelection(1);
break;
case 3600:
composePollBinding.pollDuration.setSelection(2);
break;
case 21600:
composePollBinding.pollDuration.setSelection(3);
break;
case 86400:
composePollBinding.pollDuration.setSelection(4);
break;
case 259200:
composePollBinding.pollDuration.setSelection(5);
break;
case 604800:
composePollBinding.pollDuration.setSelection(6);
break;
}
if (statusCompose.poll.multiple)
composePollBinding.pollType.check(R.id.poll_type_multiple);
else
composePollBinding.pollType.check(R.id.poll_type_single);
}
alertPoll.setNegativeButton(R.string.delete, (dialog, whichButton) -> {
if (statusCompose != null && statusCompose.poll != null) statusCompose.poll = null;
buttonState();
dialog.dismiss();
});
alertPoll.setPositiveButton(R.string.save, null);
final AlertDialog alertPollDiaslog = alertPoll.create();
alertPollDiaslog.setOnShowListener(dialog -> {
composePollBinding.pollType.addOnButtonCheckedListener((group, checkedId, isChecked) -> {
if (isChecked) {
if (checkedId == R.id.poll_type_single) {
if (statusCompose != null && statusCompose.poll != null)
statusCompose.poll.multiple = false;
for (int i = 0; i < composePollBinding.optionsList.getChildCount(); i++) {
ComposePollItemBinding child = ComposePollItemBinding.bind(composePollBinding.optionsList.getChildAt(i));
child.typeIndicator.setImageResource(R.drawable.ic_compose_poll_option_mark_single);
}
} else if (checkedId == R.id.poll_type_multiple) {
if (statusCompose != null && statusCompose.poll != null)
statusCompose.poll.multiple = true;
for (int i = 0; i < composePollBinding.optionsList.getChildCount(); i++) {
ComposePollItemBinding child = ComposePollItemBinding.bind(composePollBinding.optionsList.getChildAt(i));
child.typeIndicator.setImageResource(R.drawable.ic_compose_poll_option_mark_multiple);
}
}
}
});
Button b = alertPollDiaslog.getButton(AlertDialog.BUTTON_POSITIVE);
b.setOnClickListener(view1 -> {
int poll_duration_pos = composePollBinding.pollDuration.getSelectedItemPosition();
int selected_poll_type_id = composePollBinding.pollType.getCheckedButtonId();
String choice1 = composePollBinding.option1.text.getText().toString().trim();
String choice2 = composePollBinding.option2.text.getText().toString().trim();
if (choice1.isEmpty() && choice2.isEmpty()) {
Toasty.error(requireActivity(), getString(R.string.poll_invalid_choices), Toasty.LENGTH_SHORT).show();
} else if (statusCompose != null) {
statusCompose.poll = new Poll();
statusCompose.poll.multiple = selected_poll_type_id == R.id.poll_type_multiple;
int expire;
switch (poll_duration_pos) {
case 0:
expire = 300;
break;
case 1:
expire = 1800;
break;
case 2:
expire = 3600;
break;
case 3:
expire = 21600;
break;
case 4:
expire = 86400;
break;
case 5:
expire = 259200;
break;
case 6:
expire = 604800;
break;
default:
expire = 864000;
}
statusCompose.poll.expire_in = expire;
List<Poll.PollItem> pollItems = new ArrayList<>();
int childCount = composePollBinding.optionsList.getChildCount();
for (int i = 0; i < childCount; i++) {
Poll.PollItem pollItem = new Poll.PollItem();
AppCompatEditText title = (composePollBinding.optionsList.getChildAt(i)).findViewById(R.id.text);
pollItem.title = title.getText().toString();
pollItems.add(pollItem);
}
List<String> options = new ArrayList<>();
boolean doubleTitle = false;
for (Poll.PollItem po : pollItems) {
if (!options.contains(po.title.trim())) {
options.add(po.title.trim());
} else {
doubleTitle = true;
}
}
if (!doubleTitle) {
statusCompose.poll.options = pollItems;
dialog.dismiss();
} else {
Toasty.error(requireActivity(), getString(R.string.poll_duplicated_entry), Toasty.LENGTH_SHORT).show();
}
}
binding.buttonPoll.setVisibility(View.VISIBLE);
buttonState();
});
});
alertPollDiaslog.show();
}
private void initiliazeStatus() {
statusCompose = new Status();
binding.text.setText("");
binding.attachmentsListContainer.removeAllViews();
if (statuses != null && statuses.size() > 0) {
binding.recyclerView.scrollToPosition(statuses.size() - 1);
Status lastStatus = statuses.get(statuses.size() - 1);
status.in_reply_to_id = lastStatus.id;
status.visibility = "direct";
status.mentions = new ArrayList<>();
statusCompose.in_reply_to_id = lastStatus.id;
statusCompose.visibility = "direct";
statusCompose.mentions = new ArrayList<>();
if (lastStatus.account.acct != null && currentAccount.mastodon_account != null && !lastStatus.account.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) {
Mention mention = new Mention();
mention.acct = "@" + lastStatus.account.acct;
mention.url = lastStatus.account.url;
mention.username = lastStatus.account.username;
status.mentions.add(mention);
statusCompose.mentions.add(mention);
}
//There are other mentions to
if (lastStatus.mentions != null && lastStatus.mentions.size() > 0) {
for (Mention mentionTmp : lastStatus.mentions) {
if (currentAccount.mastodon_account != null && !mentionTmp.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) {
status.mentions.add(mentionTmp);
statusCompose.mentions.add(mentionTmp);
}
}
}
}
return status;
manageMentions(statusCompose);
}
/**
@ -353,7 +600,6 @@ public class FragmentMastodonDirectMessage extends Fragment {
}
}
binding.text.setText(statusCompose.text);
statusCompose.cursorPosition = statusCompose.text.length();
if (statusCompose.mentions.size() > 1) {
if (!mentionsAtTop) {
statusCompose.text += "\n";
@ -366,7 +612,7 @@ public class FragmentMastodonDirectMessage extends Fragment {
binding.text.setText(statusCompose.text);
binding.text.requestFocus();
binding.text.post(() -> {
binding.text.setSelection(statusCompose.cursorPosition); //Put cursor at the end
binding.text.setSelection(statusCompose.text.length()); //Put cursor at the end
});
} else {
binding.text.requestFocus();
@ -685,10 +931,9 @@ public class FragmentMastodonDirectMessage extends Fragment {
statuses.addAll(0, context.ancestors);
statusDirectMessageAdapter.notifyItemRangeInserted(0, statusPosition);
statuses.addAll(statusPosition + 1, context.descendants);
initiliazeStatus();
statusDirectMessageAdapter.notifyItemRangeInserted(statusPosition + 1, context.descendants.size());
binding.swipeContainer.setRefreshing(false);
binding.recyclerView.scrollToPosition(statusPosition);
initiliazeStatus();
}
public interface FirstMessage {

View File

@ -6,13 +6,13 @@
android:pivotY="100%"
android:toDegrees="0">
<shape android:shape="rectangle">
<solid android:color="?attr/colorSecondary" />
<solid android:color="@color/chat_other_background" />
</shape>
</rotate>
</item>
<item android:left="5dp">
<shape android:shape="rectangle">
<solid android:color="?attr/colorSecondary" />
<solid android:color="@color/chat_other_background" />
<corners android:radius="5dp" />
</shape>
</item>

View File

@ -6,13 +6,13 @@
android:pivotY="100%"
android:toDegrees="0">
<shape android:shape="rectangle">
<solid android:color="?attr/colorPrimary" />
<solid android:color="?attr/colorSecondary" />
</shape>
</rotate>
</item>
<item android:right="6dp">
<shape android:shape="rectangle">
<solid android:color="?attr/colorPrimary" />
<solid android:color="?attr/colorSecondary" />
<corners android:radius="5dp" />
</shape>
</item>

View File

@ -14,49 +14,40 @@
You should have received a copy of the GNU General Public License along with Fedilab; if not,
see <http://www.gnu.org/licenses>
-->
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
android:orientation="vertical">
<androidx.coordinatorlayout.widget.CoordinatorLayout
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".mastodon.activities.DirectMessageActivity">
android:layout_height="?attr/actionBarSize"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/profile_picture"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="10dp"
android:contentDescription="@string/profile_picture" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:fitsSystemWindows="true">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="end"
android:maxLines="1" />
</androidx.appcompat.widget.Toolbar>
<ImageView
android:id="@+id/profile_picture"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="10dp"
android:contentDescription="@string/profile_picture" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="end"
android:maxLines="1" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment_content_main"
@ -64,5 +55,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.drawerlayout.widget.DrawerLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -64,7 +64,18 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/message_content">
<include
android:id="@+id/poll"
layout="@layout/layout_poll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp" />
<include
android:layout_marginTop="10dp"
android:id="@+id/media"
layout="@layout/layout_drawer_attachments"
android:layout_width="match_parent"

View File

@ -67,6 +67,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.7"
android:id="@+id/refresh"
android:text="@string/tap_here_to_refresh_poll"
tools:ignore="HardcodedText" />

View File

@ -206,4 +206,8 @@
<color name="solarized_md_theme_dark_surfaceTint">#BBD144</color>
<color name="solarized_md_theme_dark_outlineVariant">#46483B</color>
<color name="solarized_md_theme_dark_scrim">#000000</color>
<color name="chat_other_background">#E0E0E0</color>
</resources>