Automatically split long copied/pasted messages into threads
This commit is contained in:
parent
f5bfb3e250
commit
bfc362ef62
|
@ -774,12 +774,15 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemDraftAdded(int position) {
|
public void onItemDraftAdded(int position, String initialContent) {
|
||||||
Status status = new Status();
|
Status status = new Status();
|
||||||
|
|
||||||
status.id = Helper.generateIdString();
|
status.id = Helper.generateIdString();
|
||||||
status.mentions = statusList.get(position - 1).mentions;
|
status.mentions = statusList.get(position - 1).mentions;
|
||||||
status.visibility = statusList.get(position - 1).visibility;
|
status.visibility = statusList.get(position - 1).visibility;
|
||||||
|
if(initialContent != null) {
|
||||||
|
status.text = initialContent;
|
||||||
|
}
|
||||||
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ComposeActivity.this);
|
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ComposeActivity.this);
|
||||||
boolean unlistedReplies = sharedpreferences.getBoolean(getString(R.string.SET_UNLISTED_REPLIES), true);
|
boolean unlistedReplies = sharedpreferences.getBoolean(getString(R.string.SET_UNLISTED_REPLIES), true);
|
||||||
if (status.visibility.equalsIgnoreCase("public") && unlistedReplies) {
|
if (status.visibility.equalsIgnoreCase("public") && unlistedReplies) {
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package app.fedilab.android.mastodon.helper;
|
||||||
|
/* Copyright 2023 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Fedilab
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import static app.fedilab.android.mastodon.helper.Helper.mentionLongPattern;
|
||||||
|
import static app.fedilab.android.mastodon.helper.Helper.mentionPattern;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
public class ComposeHelper {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to split the toot by dot "." for sentences - adds number at the end automatically
|
||||||
|
*
|
||||||
|
* @param content String initial content
|
||||||
|
* @param maxChars int the max chars per toot
|
||||||
|
* @return ArrayList<String> split toot
|
||||||
|
*/
|
||||||
|
public static ArrayList<String> splitToots(String content, int maxChars) {
|
||||||
|
String[] splitContent = content.split("\\s");
|
||||||
|
|
||||||
|
|
||||||
|
ArrayList<String> mentions = new ArrayList<>();
|
||||||
|
int mentionLength = 0;
|
||||||
|
StringBuilder mentionString = new StringBuilder();
|
||||||
|
Matcher matcher = mentionLongPattern.matcher(content);
|
||||||
|
while (matcher.find()) {
|
||||||
|
String mentionLong = matcher.group(1);
|
||||||
|
if (!mentions.contains(mentionLong)) {
|
||||||
|
mentions.add(mentionLong);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matcher = mentionPattern.matcher(content);
|
||||||
|
while (matcher.find()) {
|
||||||
|
String mention = matcher.group(1);
|
||||||
|
if (!mentions.contains(mention)) {
|
||||||
|
mentions.add(mention);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String mention : mentions) {
|
||||||
|
mentionString.append(mention).append(" ");
|
||||||
|
}
|
||||||
|
mentionLength = mentionString.length() + 1;
|
||||||
|
int maxCharsPerMessage = maxChars - mentionLength;
|
||||||
|
int totalCurrent = 0;
|
||||||
|
ArrayList<String> reply = new ArrayList<>();
|
||||||
|
int index = 0;
|
||||||
|
for (String s : splitContent) {
|
||||||
|
if ((totalCurrent + s.length() + 1) < maxCharsPerMessage) {
|
||||||
|
totalCurrent += (s.length() + 1);
|
||||||
|
} else {
|
||||||
|
if (content.length() > totalCurrent && totalCurrent > 0) {
|
||||||
|
String tempContent = content.substring(0, (totalCurrent));
|
||||||
|
content = content.substring(totalCurrent);
|
||||||
|
|
||||||
|
reply.add(index, tempContent);
|
||||||
|
index++;
|
||||||
|
totalCurrent = s.length() + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (totalCurrent > 0) {
|
||||||
|
reply.add(index, content);
|
||||||
|
}
|
||||||
|
if (reply.size() > 1) {
|
||||||
|
int i = 0;
|
||||||
|
for (String r : reply) {
|
||||||
|
if (mentions.size() > 0) {
|
||||||
|
String tmpMention = mentionString.toString();
|
||||||
|
for (String mention : mentions) {
|
||||||
|
if (r.contains(mention)) {
|
||||||
|
tmpMention = tmpMention.replace(mention, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply.set(i, r + " " + tmpMention);
|
||||||
|
} else {
|
||||||
|
reply.set(i, r);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
}
|
|
@ -89,6 +89,7 @@ import java.util.Date;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -117,6 +118,7 @@ import app.fedilab.android.mastodon.client.entities.app.Languages;
|
||||||
import app.fedilab.android.mastodon.client.entities.app.Quotes;
|
import app.fedilab.android.mastodon.client.entities.app.Quotes;
|
||||||
import app.fedilab.android.mastodon.client.entities.app.StatusDraft;
|
import app.fedilab.android.mastodon.client.entities.app.StatusDraft;
|
||||||
import app.fedilab.android.mastodon.exception.DBException;
|
import app.fedilab.android.mastodon.exception.DBException;
|
||||||
|
import app.fedilab.android.mastodon.helper.ComposeHelper;
|
||||||
import app.fedilab.android.mastodon.helper.Helper;
|
import app.fedilab.android.mastodon.helper.Helper;
|
||||||
import app.fedilab.android.mastodon.helper.MastodonHelper;
|
import app.fedilab.android.mastodon.helper.MastodonHelper;
|
||||||
import app.fedilab.android.mastodon.helper.ThemeHelper;
|
import app.fedilab.android.mastodon.helper.ThemeHelper;
|
||||||
|
@ -467,7 +469,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
holder.binding.addRemoveStatus.setIconResource(R.drawable.ic_compose_thread_add_status);
|
holder.binding.addRemoveStatus.setIconResource(R.drawable.ic_compose_thread_add_status);
|
||||||
holder.binding.addRemoveStatus.setContentDescription(context.getString(R.string.add_status));
|
holder.binding.addRemoveStatus.setContentDescription(context.getString(R.string.add_status));
|
||||||
holder.binding.addRemoveStatus.setOnClickListener(v -> {
|
holder.binding.addRemoveStatus.setOnClickListener(v -> {
|
||||||
manageDrafts.onItemDraftAdded(statusList.size());
|
manageDrafts.onItemDraftAdded(statusList.size(), null);
|
||||||
buttonVisibility(holder);
|
buttonVisibility(holder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -475,7 +477,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
holder.binding.addRemoveStatus.setIconResource(R.drawable.ic_compose_thread_add_status);
|
holder.binding.addRemoveStatus.setIconResource(R.drawable.ic_compose_thread_add_status);
|
||||||
holder.binding.addRemoveStatus.setContentDescription(context.getString(R.string.add_status));
|
holder.binding.addRemoveStatus.setContentDescription(context.getString(R.string.add_status));
|
||||||
holder.binding.addRemoveStatus.setOnClickListener(v -> {
|
holder.binding.addRemoveStatus.setOnClickListener(v -> {
|
||||||
manageDrafts.onItemDraftAdded(statusList.size());
|
manageDrafts.onItemDraftAdded(statusList.size(), null);
|
||||||
buttonVisibility(holder);
|
buttonVisibility(holder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -523,6 +525,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
TextWatcher textw;
|
TextWatcher textw;
|
||||||
AccountsVM accountsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AccountsVM.class);
|
AccountsVM accountsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AccountsVM.class);
|
||||||
SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class);
|
SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class);
|
||||||
|
final boolean[] proceedToSplit = {false};
|
||||||
textw = new TextWatcher() {
|
textw = new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
@ -531,10 +534,33 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
buttonVisibility(holder);
|
buttonVisibility(holder);
|
||||||
|
//Text is copied pasted and the content is greater than the max of the instance
|
||||||
|
int max_car = MastodonHelper.getInstanceMaxChars(context);
|
||||||
|
if (count > max_car) {
|
||||||
|
proceedToSplit[0] = true;
|
||||||
|
ArrayList<String> splitText = ComposeHelper.splitToots(s.toString(), max_car);
|
||||||
|
int statusListSize = statusList.size();
|
||||||
|
int i = 0;
|
||||||
|
for(String message: splitText) {
|
||||||
|
if(i==0) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
manageDrafts.onItemDraftAdded(statusListSize+(i-1), message);
|
||||||
|
buttonVisibility(holder);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
|
String contentString = s.toString();
|
||||||
|
if(proceedToSplit[0]) {
|
||||||
|
int max_car = MastodonHelper.getInstanceMaxChars(context);
|
||||||
|
ArrayList<String> splitText = ComposeHelper.splitToots(contentString, max_car);
|
||||||
|
contentString = splitText.get(0);
|
||||||
|
}
|
||||||
int currentLength = MastodonHelper.countLength(holder);
|
int currentLength = MastodonHelper.countLength(holder);
|
||||||
if (promptDraftListener != null) {
|
if (promptDraftListener != null) {
|
||||||
promptDraftListener.promptDraft();
|
promptDraftListener.promptDraft();
|
||||||
|
@ -553,22 +579,23 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
if (holder.getBindingAdapterPosition() < 0) {
|
if (holder.getBindingAdapterPosition() < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
statusList.get(holder.getBindingAdapterPosition()).text = s.toString();
|
statusList.get(holder.getBindingAdapterPosition()).text = contentString;
|
||||||
if (s.toString().trim().length() < 2) {
|
if (contentString.trim().length() < 2) {
|
||||||
buttonVisibility(holder);
|
buttonVisibility(holder);
|
||||||
}
|
}
|
||||||
//Update cursor position
|
//Update cursor position
|
||||||
//statusList.get(holder.getBindingAdapterPosition()).cursorPosition = holder.binding.content.getSelectionStart();
|
//statusList.get(holder.getBindingAdapterPosition()).cursorPosition = holder.binding.content.getSelectionStart();
|
||||||
if (autocomplete) {
|
if (autocomplete) {
|
||||||
holder.binding.content.removeTextChangedListener(this);
|
holder.binding.content.removeTextChangedListener(this);
|
||||||
|
String finalContentString = contentString;
|
||||||
Thread thread = new Thread() {
|
Thread thread = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String fedilabHugsTrigger = ":fedilab_hugs:";
|
String fedilabHugsTrigger = ":fedilab_hugs:";
|
||||||
String fedilabMorseTrigger = ":fedilab_morse:";
|
String fedilabMorseTrigger = ":fedilab_morse:";
|
||||||
String fedilabQuoteTrigger = ":fedilab_quote:";
|
String fedilabQuoteTrigger = ":fedilab_quote:";
|
||||||
if (s.toString().contains(fedilabHugsTrigger)) {
|
if (finalContentString.contains(fedilabHugsTrigger)) {
|
||||||
newContent[0] = s.toString().replaceAll(Pattern.quote(fedilabHugsTrigger), "").trim();
|
newContent[0] = finalContentString.replaceAll(Pattern.quote(fedilabHugsTrigger), "").trim();
|
||||||
int toFill = 500 - newContent[0].length();
|
int toFill = 500 - newContent[0].length();
|
||||||
if (toFill <= 0) {
|
if (toFill <= 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -589,8 +616,8 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
updateCharacterCount(holder);
|
updateCharacterCount(holder);
|
||||||
};
|
};
|
||||||
mainHandler.post(myRunnable);
|
mainHandler.post(myRunnable);
|
||||||
} else if (s.toString().contains(fedilabMorseTrigger)) {
|
} else if (finalContentString.contains(fedilabMorseTrigger)) {
|
||||||
newContent[0] = s.toString().replaceAll(fedilabMorseTrigger, "").trim();
|
newContent[0] = finalContentString.replaceAll(fedilabMorseTrigger, "").trim();
|
||||||
List<String> mentions = new ArrayList<>();
|
List<String> mentions = new ArrayList<>();
|
||||||
String mentionPattern = "@[a-z0-9_]+(@[a-z0-9.\\-]+[a-z0-9]+)?";
|
String mentionPattern = "@[a-z0-9_]+(@[a-z0-9.\\-]+[a-z0-9]+)?";
|
||||||
final Pattern mPattern = Pattern.compile(mentionPattern, Pattern.CASE_INSENSITIVE);
|
final Pattern mPattern = Pattern.compile(mentionPattern, Pattern.CASE_INSENSITIVE);
|
||||||
|
@ -634,8 +661,8 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
updateCharacterCount(holder);
|
updateCharacterCount(holder);
|
||||||
};
|
};
|
||||||
mainHandler.post(myRunnable);
|
mainHandler.post(myRunnable);
|
||||||
} else if (s.toString().contains(fedilabQuoteTrigger)) {
|
} else if (finalContentString.contains(fedilabQuoteTrigger)) {
|
||||||
newContent[0] = s.toString().replaceAll(fedilabQuoteTrigger, "").trim();
|
newContent[0] = finalContentString.replaceAll(fedilabQuoteTrigger, "").trim();
|
||||||
List<String> mentions = new ArrayList<>();
|
List<String> mentions = new ArrayList<>();
|
||||||
String mentionPattern = "@[a-z0-9_]+(@[a-z0-9.\\-]+[a-z0-9]+)?";
|
String mentionPattern = "@[a-z0-9_]+(@[a-z0-9.\\-]+[a-z0-9]+)?";
|
||||||
final Pattern mPattern = Pattern.compile(mentionPattern, Pattern.CASE_INSENSITIVE);
|
final Pattern mPattern = Pattern.compile(mentionPattern, Pattern.CASE_INSENSITIVE);
|
||||||
|
@ -694,37 +721,35 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
|
|
||||||
if (holder.binding.content.getSelectionStart() != 0)
|
if (holder.binding.content.getSelectionStart() != 0)
|
||||||
currentCursorPosition[0] = holder.binding.content.getSelectionStart();
|
currentCursorPosition[0] = holder.binding.content.getSelectionStart();
|
||||||
if (s.toString().length() == 0)
|
if (contentString.length() == 0)
|
||||||
currentCursorPosition[0] = 0;
|
currentCursorPosition[0] = 0;
|
||||||
//Only check last 15 characters before cursor position to avoid lags
|
//Only check last 15 characters before cursor position to avoid lags
|
||||||
//Less than 15 characters are written before the cursor position
|
//Less than 15 characters are written before the cursor position
|
||||||
searchLength[0] = Math.min(currentCursorPosition[0], searchDeep);
|
searchLength[0] = Math.min(currentCursorPosition[0], searchDeep);
|
||||||
|
|
||||||
|
|
||||||
if (currentCursorPosition[0] - (searchLength[0] - 1) < 0 || currentCursorPosition[0] == 0 || currentCursorPosition[0] > s.toString().length()) {
|
if (currentCursorPosition[0] - (searchLength[0] - 1) < 0 || currentCursorPosition[0] == 0 || currentCursorPosition[0] > contentString.length()) {
|
||||||
updateCharacterCount(holder);
|
updateCharacterCount(holder);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Matcher mathsPatterns = Helper.mathsComposePattern.matcher((s.toString()));
|
Matcher mathsPatterns = Helper.mathsComposePattern.matcher((contentString));
|
||||||
if (mathsPatterns.find()) {
|
if (mathsPatterns.find()) {
|
||||||
if (holder.binding.laTexViewContainer.getChildCount() == 0) {
|
if (holder.binding.laTexViewContainer.getChildCount() == 0) {
|
||||||
MathJaxConfig mathJaxConfig = new MathJaxConfig();
|
MathJaxConfig mathJaxConfig = new MathJaxConfig();
|
||||||
mathJaxConfig.setAutomaticLinebreaks(true);
|
mathJaxConfig.setAutomaticLinebreaks(true);
|
||||||
mathJaxConfig.setInput(TeX);
|
mathJaxConfig.setInput(TeX);
|
||||||
switch (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
|
switch (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
|
||||||
case Configuration.UI_MODE_NIGHT_YES:
|
case Configuration.UI_MODE_NIGHT_YES ->
|
||||||
mathJaxConfig.setTextColor("white");
|
mathJaxConfig.setTextColor("white");
|
||||||
break;
|
case Configuration.UI_MODE_NIGHT_NO ->
|
||||||
case Configuration.UI_MODE_NIGHT_NO:
|
|
||||||
mathJaxConfig.setTextColor("black");
|
mathJaxConfig.setTextColor("black");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
statusList.get(holder.getBindingAdapterPosition()).mathJaxView = new MathJaxView(context, mathJaxConfig);
|
statusList.get(holder.getBindingAdapterPosition()).mathJaxView = new MathJaxView(context, mathJaxConfig);
|
||||||
holder.binding.laTexViewContainer.addView(statusList.get(holder.getBindingAdapterPosition()).mathJaxView);
|
holder.binding.laTexViewContainer.addView(statusList.get(holder.getBindingAdapterPosition()).mathJaxView);
|
||||||
holder.binding.laTexViewContainer.setVisibility(View.VISIBLE);
|
holder.binding.laTexViewContainer.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
if (statusList.get(holder.getBindingAdapterPosition()).mathJaxView != null) {
|
if (statusList.get(holder.getBindingAdapterPosition()).mathJaxView != null) {
|
||||||
statusList.get(holder.getBindingAdapterPosition()).mathJaxView.setInputText(s.toString());
|
statusList.get(holder.getBindingAdapterPosition()).mathJaxView.setInputText(contentString);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -733,7 +758,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
|
|
||||||
String patternh = "^(.|\\s)*(:fedilab_hugs:)";
|
String patternh = "^(.|\\s)*(:fedilab_hugs:)";
|
||||||
final Pattern hPattern = Pattern.compile(patternh);
|
final Pattern hPattern = Pattern.compile(patternh);
|
||||||
Matcher mh = hPattern.matcher((s.toString().substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])));
|
Matcher mh = hPattern.matcher((contentString.substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])));
|
||||||
|
|
||||||
if (mh.matches()) {
|
if (mh.matches()) {
|
||||||
autocomplete = true;
|
autocomplete = true;
|
||||||
|
@ -742,7 +767,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
|
|
||||||
String patternM = "^(.|\\s)*(:fedilab_morse:)";
|
String patternM = "^(.|\\s)*(:fedilab_morse:)";
|
||||||
final Pattern mPattern = Pattern.compile(patternM);
|
final Pattern mPattern = Pattern.compile(patternM);
|
||||||
Matcher mm = mPattern.matcher((s.toString().substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])));
|
Matcher mm = mPattern.matcher((contentString.substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])));
|
||||||
if (mm.matches()) {
|
if (mm.matches()) {
|
||||||
autocomplete = true;
|
autocomplete = true;
|
||||||
return;
|
return;
|
||||||
|
@ -750,13 +775,13 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
|
|
||||||
String patternQ = "^(.|\\s)*(:fedilab_quote:)";
|
String patternQ = "^(.|\\s)*(:fedilab_quote:)";
|
||||||
final Pattern qPattern = Pattern.compile(patternQ);
|
final Pattern qPattern = Pattern.compile(patternQ);
|
||||||
Matcher mq = qPattern.matcher((s.toString().substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])));
|
Matcher mq = qPattern.matcher((contentString.substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])));
|
||||||
if (mq.matches()) {
|
if (mq.matches()) {
|
||||||
autocomplete = true;
|
autocomplete = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] searchInArray = (s.toString().substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])).split("\\s");
|
String[] searchInArray = (contentString.substring(currentCursorPosition[0] - searchLength[0], currentCursorPosition[0])).split("\\s");
|
||||||
if (searchInArray.length < 1) {
|
if (searchInArray.length < 1) {
|
||||||
updateCharacterCount(holder);
|
updateCharacterCount(holder);
|
||||||
return;
|
return;
|
||||||
|
@ -1498,22 +1523,22 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (statusDraft.visibility.toLowerCase()) {
|
switch (statusDraft.visibility.toLowerCase()) {
|
||||||
case "public":
|
case "public" -> {
|
||||||
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_public);
|
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_public);
|
||||||
statusDraft.visibility = MastodonHelper.visibility.PUBLIC.name();
|
statusDraft.visibility = MastodonHelper.visibility.PUBLIC.name();
|
||||||
break;
|
}
|
||||||
case "unlisted":
|
case "unlisted" -> {
|
||||||
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_unlisted);
|
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_unlisted);
|
||||||
statusDraft.visibility = MastodonHelper.visibility.UNLISTED.name();
|
statusDraft.visibility = MastodonHelper.visibility.UNLISTED.name();
|
||||||
break;
|
}
|
||||||
case "private":
|
case "private" -> {
|
||||||
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_private);
|
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_private);
|
||||||
statusDraft.visibility = MastodonHelper.visibility.PRIVATE.name();
|
statusDraft.visibility = MastodonHelper.visibility.PRIVATE.name();
|
||||||
break;
|
}
|
||||||
case "direct":
|
case "direct" -> {
|
||||||
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_direct);
|
holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_direct);
|
||||||
statusDraft.visibility = MastodonHelper.visibility.DIRECT.name();
|
statusDraft.visibility = MastodonHelper.visibility.DIRECT.name();
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.binding.visibilityPanel.setOnTouchListener((view, motionEvent) -> true);
|
holder.binding.visibilityPanel.setOnTouchListener((view, motionEvent) -> true);
|
||||||
|
@ -1582,7 +1607,10 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
else
|
else
|
||||||
statusDraft.text = new SpannableString(Html.fromHtml(statusDraft.content)).toString();
|
statusDraft.text = new SpannableString(Html.fromHtml(statusDraft.content)).toString();
|
||||||
}
|
}
|
||||||
|
int max_car = MastodonHelper.getInstanceMaxChars(context);
|
||||||
holder.binding.content.setText(statusDraft.text);
|
holder.binding.content.setText(statusDraft.text);
|
||||||
|
holder.binding.characterProgress.setMax(max_car);
|
||||||
|
updateCharacterCount(holder);
|
||||||
holder.binding.content.setKeyBoardInputCallbackListener((inputContentInfo, flags, opts) -> {
|
holder.binding.content.setKeyBoardInputCallbackListener((inputContentInfo, flags, opts) -> {
|
||||||
if (inputContentInfo != null) {
|
if (inputContentInfo != null) {
|
||||||
Uri uri = inputContentInfo.getContentUri();
|
Uri uri = inputContentInfo.getContentUri();
|
||||||
|
@ -1694,7 +1722,6 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
if (instanceInfo == null) {
|
if (instanceInfo == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int max_car = MastodonHelper.getInstanceMaxChars(context);
|
|
||||||
holder.binding.characterProgress.setMax(max_car);
|
holder.binding.characterProgress.setMax(max_car);
|
||||||
holder.binding.contentSpoiler.addTextChangedListener(new TextWatcher() {
|
holder.binding.contentSpoiler.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -1917,27 +1944,13 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
composePollBinding.buttonAddOption.setVisibility(View.GONE);
|
composePollBinding.buttonAddOption.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
switch (statusDraft.poll.expire_in) {
|
switch (statusDraft.poll.expire_in) {
|
||||||
case 300:
|
case 300 -> composePollBinding.pollDuration.setSelection(0);
|
||||||
composePollBinding.pollDuration.setSelection(0);
|
case 1800 -> composePollBinding.pollDuration.setSelection(1);
|
||||||
break;
|
case 3600 -> composePollBinding.pollDuration.setSelection(2);
|
||||||
case 1800:
|
case 21600 -> composePollBinding.pollDuration.setSelection(3);
|
||||||
composePollBinding.pollDuration.setSelection(1);
|
case 86400 -> composePollBinding.pollDuration.setSelection(4);
|
||||||
break;
|
case 259200 -> composePollBinding.pollDuration.setSelection(5);
|
||||||
case 3600:
|
case 604800 -> composePollBinding.pollDuration.setSelection(6);
|
||||||
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 (statusDraft.poll.multiple)
|
if (statusDraft.poll.multiple)
|
||||||
composePollBinding.pollType.check(R.id.poll_type_multiple);
|
composePollBinding.pollType.check(R.id.poll_type_multiple);
|
||||||
|
@ -1980,40 +1993,24 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
int poll_duration_pos = composePollBinding.pollDuration.getSelectedItemPosition();
|
int poll_duration_pos = composePollBinding.pollDuration.getSelectedItemPosition();
|
||||||
|
|
||||||
int selected_poll_type_id = composePollBinding.pollType.getCheckedButtonId();
|
int selected_poll_type_id = composePollBinding.pollType.getCheckedButtonId();
|
||||||
String choice1 = composePollBinding.option1.text.getText().toString().trim();
|
String choice1 = Objects.requireNonNull(composePollBinding.option1.text.getText()).toString().trim();
|
||||||
String choice2 = composePollBinding.option2.text.getText().toString().trim();
|
String choice2 = Objects.requireNonNull(composePollBinding.option2.text.getText()).toString().trim();
|
||||||
|
|
||||||
if (choice1.isEmpty() && choice2.isEmpty()) {
|
if (choice1.isEmpty() && choice2.isEmpty()) {
|
||||||
Toasty.error(context, context.getString(R.string.poll_invalid_choices), Toasty.LENGTH_SHORT).show();
|
Toasty.error(context, context.getString(R.string.poll_invalid_choices), Toasty.LENGTH_SHORT).show();
|
||||||
} else if (statusDraft != null) {
|
} else if (statusDraft != null) {
|
||||||
statusDraft.poll = new Poll();
|
statusDraft.poll = new Poll();
|
||||||
statusDraft.poll.multiple = selected_poll_type_id == R.id.poll_type_multiple;
|
statusDraft.poll.multiple = selected_poll_type_id == R.id.poll_type_multiple;
|
||||||
int expire;
|
int expire = switch (poll_duration_pos) {
|
||||||
switch (poll_duration_pos) {
|
case 0 -> 300;
|
||||||
case 0:
|
case 1 -> 1800;
|
||||||
expire = 300;
|
case 2 -> 3600;
|
||||||
break;
|
case 3 -> 21600;
|
||||||
case 1:
|
case 4 -> 86400;
|
||||||
expire = 1800;
|
case 5 -> 259200;
|
||||||
break;
|
case 6 -> 604800;
|
||||||
case 2:
|
default -> 864000;
|
||||||
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;
|
|
||||||
}
|
|
||||||
statusDraft.poll.expire_in = expire;
|
statusDraft.poll.expire_in = expire;
|
||||||
if (promptDraftListener != null) {
|
if (promptDraftListener != null) {
|
||||||
promptDraftListener.promptDraft();
|
promptDraftListener.promptDraft();
|
||||||
|
@ -2094,7 +2091,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ManageDrafts {
|
public interface ManageDrafts {
|
||||||
void onItemDraftAdded(int position);
|
void onItemDraftAdded(int position, String content);
|
||||||
|
|
||||||
void onItemDraftDeleted(Status status, int position);
|
void onItemDraftDeleted(Status status, int position);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue