605 lines
26 KiB
Java
605 lines
26 KiB
Java
package app.fedilab.android.mastodon.helper;
|
|
/* Copyright 2021 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.BaseMainActivity.instanceInfo;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.util.Patterns;
|
|
import android.view.View;
|
|
import android.widget.ImageView;
|
|
import android.widget.Toast;
|
|
|
|
import androidx.annotation.DrawableRes;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.appcompat.app.AlertDialog;
|
|
import androidx.lifecycle.LifecycleOwner;
|
|
import androidx.lifecycle.ViewModelProvider;
|
|
import androidx.lifecycle.ViewModelStoreOwner;
|
|
import androidx.preference.PreferenceManager;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
import androidx.work.Data;
|
|
import androidx.work.OneTimeWorkRequest;
|
|
import androidx.work.WorkManager;
|
|
|
|
import com.bumptech.glide.Glide;
|
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
|
import com.bumptech.glide.request.RequestOptions;
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
import com.google.gson.annotations.SerializedName;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
import java.util.GregorianCalendar;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import app.fedilab.android.BaseMainActivity;
|
|
import app.fedilab.android.R;
|
|
import app.fedilab.android.activities.MainActivity;
|
|
import app.fedilab.android.databinding.DatetimePickerBinding;
|
|
import app.fedilab.android.mastodon.client.entities.api.Account;
|
|
import app.fedilab.android.mastodon.client.entities.api.Pagination;
|
|
import app.fedilab.android.mastodon.client.entities.api.RelationShip;
|
|
import app.fedilab.android.mastodon.client.entities.api.Status;
|
|
import app.fedilab.android.mastodon.client.entities.app.ScheduledBoost;
|
|
import app.fedilab.android.mastodon.exception.DBException;
|
|
import app.fedilab.android.mastodon.jobs.ScheduleBoostWorker;
|
|
import app.fedilab.android.mastodon.ui.drawer.ComposeAdapter;
|
|
import app.fedilab.android.mastodon.viewmodel.mastodon.AccountsVM;
|
|
import es.dmoral.toasty.Toasty;
|
|
import okhttp3.Headers;
|
|
|
|
public class MastodonHelper {
|
|
|
|
public static final String CLIENT_ID = "client_id";
|
|
public static final String REDIRECT_URI = "redirect_uri";
|
|
public static final String RESPONSE_TYPE = "response_type";
|
|
public static final String SCOPE = "scope";
|
|
public static final String REDIRECT_CONTENT_WEB = "fedilab://backtofedilab";
|
|
public static final String OAUTH_SCOPES = "read%20write%20follow%20push";
|
|
public static final String OAUTH_SCOPES_ADMIN = "read%20write%20follow%20push%20admin:read%20admin:write";
|
|
|
|
public static final int ACCOUNTS_PER_CALL = 40;
|
|
public static final int STATUSES_PER_CALL = 40;
|
|
public static final int SEARCH_PER_CALL = 20;
|
|
public static final int NOTIFICATIONS_PER_CALL = 30;
|
|
|
|
|
|
public static int accountsPerCall(Context _mContext) {
|
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(_mContext);
|
|
return sharedPreferences.getInt(_mContext.getString(R.string.SET_ACCOUNTS_PER_CALL), ACCOUNTS_PER_CALL);
|
|
}
|
|
|
|
public static int statusesPerCall(Context _mContext) {
|
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(_mContext);
|
|
return sharedPreferences.getInt(_mContext.getString(R.string.SET_STATUSES_PER_CALL), STATUSES_PER_CALL);
|
|
}
|
|
|
|
public static int notificationsPerCall(Context _mContext) {
|
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(_mContext);
|
|
return sharedPreferences.getInt(_mContext.getString(R.string.SET_NOTIFICATIONS_PER_CALL), NOTIFICATIONS_PER_CALL);
|
|
}
|
|
|
|
/**
|
|
* Returns authorisation URL
|
|
*
|
|
* @param instance String instance
|
|
* @param client_id String client id
|
|
* @param admin boolean - Admin scope
|
|
* @return String - Authorisation URL
|
|
*/
|
|
public static String authorizeURL(@NonNull String instance, @NonNull String client_id, boolean admin) {
|
|
String queryString = CLIENT_ID + "=" + client_id;
|
|
queryString += "&" + REDIRECT_URI + "=" + Uri.encode(REDIRECT_CONTENT_WEB);
|
|
queryString += "&" + RESPONSE_TYPE + "=code";
|
|
if (admin) {
|
|
queryString += "&" + SCOPE + "=" + OAUTH_SCOPES_ADMIN;
|
|
} else {
|
|
queryString += "&" + SCOPE + "=" + OAUTH_SCOPES;
|
|
}
|
|
return "https://" + instance + "/oauth/authorize" + "?" + queryString;
|
|
}
|
|
|
|
/**
|
|
* Retrieve pagination from header
|
|
*
|
|
* @param headers Headers
|
|
* @return Pagination
|
|
*/
|
|
public static Pagination getPagination(Headers headers) {
|
|
|
|
Pagination pagination = new Pagination();
|
|
if (headers == null) {
|
|
return pagination;
|
|
}
|
|
String link = headers.get("Link");
|
|
if (link != null) {
|
|
Pattern patternMaxId = Pattern.compile("max_id=([0-9a-zA-Z]+).*");
|
|
Matcher matcherMaxId = patternMaxId.matcher(link);
|
|
if (matcherMaxId.find()) {
|
|
pagination.max_id = matcherMaxId.group(1);
|
|
}
|
|
Pattern patternSinceId = Pattern.compile("since_id=([0-9a-zA-Z]+).*");
|
|
Matcher matcherSinceId = patternSinceId.matcher(link);
|
|
if (matcherSinceId.find()) {
|
|
pagination.since_id = matcherSinceId.group(1);
|
|
}
|
|
Pattern patternMinId = Pattern.compile("min_id=([0-9a-zA-Z]+).*");
|
|
Matcher matcherMinId = patternMinId.matcher(link);
|
|
if (matcherMinId.find()) {
|
|
pagination.min_id = matcherMinId.group(1);
|
|
}
|
|
}
|
|
return pagination;
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve pagination from header
|
|
*
|
|
* @param headers Headers
|
|
* @return Pagination
|
|
*/
|
|
public static Pagination getOffSetPagination(Headers headers) {
|
|
String link = headers.get("Link");
|
|
Pagination pagination = new Pagination();
|
|
if (link != null) {
|
|
Pattern patternMaxId = Pattern.compile("offset=([0-9a-zA-Z]+)\\s?>\\s?;\\s?rel=\"next\"");
|
|
Matcher matcherMaxId = patternMaxId.matcher(link);
|
|
if (matcherMaxId.find()) {
|
|
pagination.max_id = matcherMaxId.group(1);
|
|
}
|
|
}
|
|
return pagination;
|
|
}
|
|
|
|
/*public static Pagination getPaginationNotification(List<Notification> notificationList) {
|
|
Pagination pagination = new Pagination();
|
|
if (notificationList == null || notificationList.size() == 0) {
|
|
return pagination;
|
|
}
|
|
pagination.max_id = notificationList.get(0).id;
|
|
pagination.min_id = String.valueOf(Long.parseLong(notificationList.get(notificationList.size() - 1).id) - 1);
|
|
return pagination;
|
|
}
|
|
|
|
public static Pagination getPaginationStatus(List<Status> statusList) {
|
|
Pagination pagination = new Pagination();
|
|
if (statusList == null || statusList.size() == 0) {
|
|
return pagination;
|
|
}
|
|
pagination.max_id = statusList.get(0).id;
|
|
pagination.min_id = statusList.get(statusList.size() - 1).id;
|
|
return pagination;
|
|
}
|
|
|
|
public static Pagination getPaginationAccount(List<Account> accountList) {
|
|
Pagination pagination = new Pagination();
|
|
if (accountList == null || accountList.size() == 0) {
|
|
return pagination;
|
|
}
|
|
pagination.max_id = accountList.get(0).id;
|
|
pagination.min_id = accountList.get(accountList.size() - 1).id;
|
|
return pagination;
|
|
}
|
|
|
|
public static Pagination getPaginationScheduledStatus(List<ScheduledStatus> scheduledStatusList) {
|
|
Pagination pagination = new Pagination();
|
|
if (scheduledStatusList == null || scheduledStatusList.size() == 0) {
|
|
return pagination;
|
|
}
|
|
pagination.max_id = scheduledStatusList.get(0).id;
|
|
pagination.min_id = scheduledStatusList.get(scheduledStatusList.size() - 1).id;
|
|
return pagination;
|
|
}
|
|
|
|
public static Pagination getPaginationConversation(List<Conversation> conversationList) {
|
|
Pagination pagination = new Pagination();
|
|
if (conversationList == null || conversationList.size() == 0) {
|
|
return pagination;
|
|
}
|
|
pagination.max_id = conversationList.get(0).id;
|
|
pagination.min_id = conversationList.get(conversationList.size() - 1).id;
|
|
return pagination;
|
|
}
|
|
*/
|
|
public static void loadPPMastodon(ImageView view, Account account) {
|
|
loadProfileMediaMastodon(view, account, MediaAccountType.AVATAR);
|
|
}
|
|
|
|
public static void loadProfileMediaMastodon(ImageView view, Account account, MediaAccountType type) {
|
|
loadProfileMediaMastodon(null, view, account, type);
|
|
}
|
|
|
|
public static void loadProfileMediaMastodon(Activity activity, ImageView view, Account account, MediaAccountType type) {
|
|
Context context = view.getContext();
|
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
boolean disableGif = sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_GIF), false);
|
|
@DrawableRes int placeholder = type == MediaAccountType.AVATAR ? R.drawable.ic_person : R.drawable.default_banner;
|
|
if (Helper.isValidContextForGlide(activity != null ? activity : context)) {
|
|
if (account == null) {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asDrawable()
|
|
.load(placeholder)
|
|
.thumbnail(0.1f)
|
|
.placeholder(placeholder)
|
|
.into(view);
|
|
return;
|
|
}
|
|
String targetedUrl = disableGif ? (type == MediaAccountType.AVATAR ? account.avatar_static : account.header_static) : (type == MediaAccountType.AVATAR ? account.avatar : account.header);
|
|
if (targetedUrl != null) {
|
|
if (disableGif || (!targetedUrl.endsWith(".gif"))) {
|
|
try {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asDrawable()
|
|
.load(targetedUrl)
|
|
.thumbnail(0.1f)
|
|
.placeholder(placeholder)
|
|
.into(view);
|
|
} catch (IllegalArgumentException e) {
|
|
e.printStackTrace();
|
|
}
|
|
} else {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asGif()
|
|
.load(targetedUrl)
|
|
.thumbnail(0.1f)
|
|
.placeholder(placeholder)
|
|
.into(view);
|
|
}
|
|
} else {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asDrawable()
|
|
.load(placeholder)
|
|
.thumbnail(0.1f)
|
|
.into(view);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void loadProfileMediaMastodonRound(Activity activity, ImageView view, Account account) {
|
|
Context context = view.getContext();
|
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
boolean disableGif = sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_GIF), false);
|
|
@DrawableRes int placeholder = R.drawable.ic_person;
|
|
if (Helper.isValidContextForGlide(activity != null ? activity : context)) {
|
|
if (account == null) {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asDrawable()
|
|
.load(placeholder)
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(16)))
|
|
.thumbnail(0.1f)
|
|
.placeholder(placeholder)
|
|
.into(view);
|
|
return;
|
|
}
|
|
String targetedUrl = disableGif ? account.avatar_static : account.avatar;
|
|
if (targetedUrl != null) {
|
|
if (disableGif || (!targetedUrl.endsWith(".gif"))) {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asDrawable()
|
|
.load(targetedUrl)
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
.thumbnail(0.1f)
|
|
.placeholder(placeholder)
|
|
.into(view);
|
|
} else {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asGif()
|
|
.load(targetedUrl)
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
.thumbnail(0.1f)
|
|
.placeholder(placeholder)
|
|
.into(view);
|
|
}
|
|
} else {
|
|
Glide.with(activity != null ? activity : context)
|
|
.asDrawable()
|
|
.load(placeholder)
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
.thumbnail(0.1f)
|
|
.into(view);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
|
*
|
|
* @param date Date
|
|
* @return String
|
|
*/
|
|
public static String dateToStringPoll(Date date) {
|
|
if (date == null)
|
|
return null;
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm", Locale.getDefault());
|
|
return dateFormat.format(date);
|
|
}
|
|
|
|
/***
|
|
* Returns a String depending of the date
|
|
* @param context Context
|
|
* @param dateEndPoll Date
|
|
* @return String
|
|
*/
|
|
public static String dateDiffPoll(Context context, Date dateEndPoll) {
|
|
if (dateEndPoll == null) {
|
|
return "";
|
|
}
|
|
Date now = new Date();
|
|
long diff = dateEndPoll.getTime() - now.getTime();
|
|
long seconds = diff / 1000;
|
|
long minutes = seconds / 60;
|
|
long hours = minutes / 60;
|
|
long days = hours / 24;
|
|
|
|
if (days > 0)
|
|
return context.getResources().getQuantityString(R.plurals.date_day_polls, (int) days, (int) days);
|
|
else if (hours > 0)
|
|
return context.getResources().getQuantityString(R.plurals.date_hours_polls, (int) hours, (int) hours);
|
|
else if (minutes > 0)
|
|
return context.getResources().getQuantityString(R.plurals.date_minutes_polls, (int) minutes, (int) minutes);
|
|
else {
|
|
if (seconds < 0)
|
|
seconds = 0;
|
|
return context.getResources().getQuantityString(R.plurals.date_seconds_polls, (int) seconds, (int) seconds);
|
|
}
|
|
}
|
|
|
|
/***
|
|
* Returns the length used when composing a toot
|
|
* @param composeViewHolder ComposeAdapter.ComposeViewHolder itemHolder for compose elements
|
|
* @return int - characters used
|
|
*/
|
|
public static int countLength(ComposeAdapter.ComposeViewHolder composeViewHolder) {
|
|
String content = composeViewHolder.binding.content.getText().toString();
|
|
String cwContent = composeViewHolder.binding.contentSpoiler.getText().toString();
|
|
String contentCount = content;
|
|
contentCount = contentCount.replaceAll("(?i)(^|[^/\\w])@(([a-z0-9_]+)@[a-z0-9.-]+[a-z0-9]+)", "$1@$3");
|
|
Matcher matcherALink = Patterns.WEB_URL.matcher(contentCount);
|
|
while (matcherALink.find()) {
|
|
final String url = matcherALink.group(1);
|
|
if (url != null) {
|
|
contentCount = contentCount.replace(url, "abcdefghijklmnopkrstuvw");
|
|
}
|
|
}
|
|
int contentLength = contentCount.length() - countWithEmoji(content);
|
|
int cwLength = cwContent.length() - countWithEmoji(cwContent);
|
|
return cwLength + contentLength;
|
|
}
|
|
|
|
/**
|
|
* Length used by emoji displayed on the toot
|
|
*
|
|
* @param text String - The current text
|
|
* @return int - Number of characters used by emoji
|
|
*/
|
|
static int countWithEmoji(String text) {
|
|
int emojiCount = 0;
|
|
for (int i = 0; i < text.length(); i++) {
|
|
int type = Character.getType(text.charAt(i));
|
|
if (type == Character.SURROGATE || type == Character.OTHER_SYMBOL) {
|
|
emojiCount++;
|
|
}
|
|
}
|
|
return emojiCount / 2;
|
|
}
|
|
|
|
|
|
/**
|
|
* Schedule a boost or timed mutes
|
|
*
|
|
* @param context Context
|
|
* @param status {@link Status}
|
|
*/
|
|
public static void scheduleBoost(Context context, ScheduleType scheduleType, Status status, Account account, TimedMuted listener) {
|
|
AlertDialog.Builder dialogBuilder = new MaterialAlertDialogBuilder(context);
|
|
DatetimePickerBinding binding = DatetimePickerBinding.inflate(((Activity) context).getLayoutInflater());
|
|
dialogBuilder.setView(binding.getRoot());
|
|
final AlertDialog alertDialogBoost = dialogBuilder.create();
|
|
binding.timePicker.setIs24HourView(true);
|
|
//Buttons management
|
|
binding.dateTimeCancel.setOnClickListener(v -> alertDialogBoost.dismiss());
|
|
binding.dateTimeNext.setOnClickListener(v -> {
|
|
binding.datePicker.setVisibility(View.GONE);
|
|
binding.timePicker.setVisibility(View.VISIBLE);
|
|
binding.dateTimePrevious.setVisibility(View.VISIBLE);
|
|
binding.dateTimeNext.setVisibility(View.GONE);
|
|
binding.dateTimeSet.setVisibility(View.VISIBLE);
|
|
});
|
|
binding.dateTimePrevious.setOnClickListener(v -> {
|
|
binding.datePicker.setVisibility(View.VISIBLE);
|
|
binding.timePicker.setVisibility(View.GONE);
|
|
binding.dateTimePrevious.setVisibility(View.GONE);
|
|
binding.dateTimeNext.setVisibility(View.VISIBLE);
|
|
binding.dateTimeSet.setVisibility(View.GONE);
|
|
});
|
|
binding.dateTimeSet.setOnClickListener(v -> {
|
|
int hour, minute;
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
hour = binding.timePicker.getHour();
|
|
minute = binding.timePicker.getMinute();
|
|
} else {
|
|
hour = binding.timePicker.getCurrentHour();
|
|
minute = binding.timePicker.getCurrentMinute();
|
|
}
|
|
Calendar calendar = new GregorianCalendar(binding.datePicker.getYear(),
|
|
binding.datePicker.getMonth(),
|
|
binding.datePicker.getDayOfMonth(),
|
|
hour,
|
|
minute);
|
|
long time = calendar.getTimeInMillis();
|
|
if ((time - new Date().getTime()) < 60000) {
|
|
if (scheduleType == ScheduleType.BOOST) {
|
|
Toasty.warning(context, context.getString(R.string.toot_scheduled_date), Toast.LENGTH_LONG).show();
|
|
} else {
|
|
Toasty.warning(context, context.getString(R.string.timed_mute_date_error), Toast.LENGTH_LONG).show();
|
|
}
|
|
} else {
|
|
//Schedules the toot
|
|
|
|
long delayToPass = (time - new Date().getTime());
|
|
if (scheduleType == ScheduleType.BOOST) {
|
|
Data inputData = new Data.Builder()
|
|
.putString(Helper.ARG_INSTANCE, BaseMainActivity.currentInstance)
|
|
.putString(Helper.ARG_TOKEN, BaseMainActivity.currentToken)
|
|
.putString(Helper.ARG_USER_ID, BaseMainActivity.currentUserID)
|
|
.putString(Helper.ARG_STATUS_ID, status.reblog != null ? status.reblog.id : status.id)
|
|
.build();
|
|
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(ScheduleBoostWorker.class)
|
|
.setInputData(inputData)
|
|
.setInitialDelay(delayToPass, TimeUnit.MILLISECONDS)
|
|
.build();
|
|
WorkManager.getInstance(context).enqueue(oneTimeWorkRequest);
|
|
ScheduledBoost scheduledBoost = new ScheduledBoost();
|
|
scheduledBoost.userId = BaseMainActivity.currentUserID;
|
|
scheduledBoost.statusId = status.reblog != null ? status.reblog.id : status.id;
|
|
scheduledBoost.scheduledAt = calendar.getTime();
|
|
scheduledBoost.instance = BaseMainActivity.currentInstance;
|
|
scheduledBoost.workerUuid = oneTimeWorkRequest.getId();
|
|
scheduledBoost.status = status.reblog != null ? status.reblog : status;
|
|
try {
|
|
new ScheduledBoost(context).insertScheduledBoost(scheduledBoost);
|
|
} catch (DBException e) {
|
|
e.printStackTrace();
|
|
}
|
|
//Clear content
|
|
Toasty.info(context, context.getString(R.string.boost_scheduled), Toast.LENGTH_LONG).show();
|
|
} else {
|
|
AccountsVM accountsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AccountsVM.class);
|
|
String accountId;
|
|
String acct;
|
|
if (account == null) {
|
|
accountId = status.account.id;
|
|
acct = status.account.acct;
|
|
} else {
|
|
accountId = account.id;
|
|
acct = account.acct;
|
|
}
|
|
accountsVM.mute(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountId, true, (int) delayToPass)
|
|
.observe((LifecycleOwner) context, relationShip -> {
|
|
if (listener != null) {
|
|
listener.onTimedMute(relationShip);
|
|
}
|
|
});
|
|
Toasty.info(context, context.getString(R.string.timed_mute_date, acct, Helper.dateToString(calendar.getTime())), Toast.LENGTH_LONG).show();
|
|
}
|
|
alertDialogBoost.dismiss();
|
|
}
|
|
});
|
|
alertDialogBoost.show();
|
|
}
|
|
|
|
/**
|
|
* Insert a single message depending of its publication date
|
|
*
|
|
* @param adapter - RecyclerView.Adapter<RecyclerView.ViewHolder>
|
|
* @param currentStatusList - Current list of messages List<Status>
|
|
* @param statusToInsert - status to insert - Status
|
|
*/
|
|
public static void insertStatus(RecyclerView.Adapter<RecyclerView.ViewHolder> adapter, List<Status> currentStatusList, Status statusToInsert) {
|
|
if (adapter == null || currentStatusList == null || statusToInsert == null) {
|
|
return;
|
|
}
|
|
int i = 0;
|
|
while (i < currentStatusList.size() && statusToInsert.created_at.before(currentStatusList.get(i).created_at)) {
|
|
i++;
|
|
}
|
|
currentStatusList.add(i, statusToInsert);
|
|
adapter.notifyItemInserted(i);
|
|
}
|
|
|
|
/**
|
|
* Insert a list of messages depending of its publication date
|
|
*
|
|
* @param adapter - RecyclerView.Adapter<RecyclerView.ViewHolder>
|
|
* @param currentStatusList - Current list of messages List<Status>
|
|
* @param statusesToInsert - statuses to insert - List<Status>
|
|
*/
|
|
public static void insertStatuses(RecyclerView.Adapter<RecyclerView.ViewHolder> adapter, List<Status> currentStatusList, List<Status> statusesToInsert) {
|
|
if (adapter == null || currentStatusList == null || statusesToInsert == null || statusesToInsert.size() == 0) {
|
|
return;
|
|
}
|
|
int i = 0;
|
|
while (i < currentStatusList.size() && statusesToInsert.get(statusesToInsert.size() - 1).created_at.before(currentStatusList.get(i).created_at)) {
|
|
i++;
|
|
}
|
|
currentStatusList.addAll(i, statusesToInsert);
|
|
adapter.notifyItemRangeInserted(i, statusesToInsert.size());
|
|
}
|
|
|
|
public static int getInstanceMaxChars(Context context) {
|
|
int max_car;
|
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
int val = sharedpreferences.getInt(context.getString(R.string.SET_MAX_INSTANCE_CHAR) + MainActivity.currentInstance, -1);
|
|
if (val != -1) {
|
|
return val;
|
|
} else {
|
|
if (instanceInfo != null) {
|
|
max_car = instanceInfo.max_toot_chars != null ? Integer.parseInt(instanceInfo.max_toot_chars) : instanceInfo.configuration.statusesConf.max_characters;
|
|
} else {
|
|
max_car = 500;
|
|
}
|
|
}
|
|
return max_car;
|
|
}
|
|
|
|
public enum MediaAccountType {
|
|
AVATAR,
|
|
HEADER
|
|
}
|
|
|
|
public enum visibility {
|
|
@SerializedName("PUBLIC")
|
|
PUBLIC("public"),
|
|
@SerializedName("UNLISTED")
|
|
UNLISTED("unlisted"),
|
|
@SerializedName("PRIVATE")
|
|
PRIVATE("private"),
|
|
@SerializedName("DIRECT")
|
|
DIRECT("direct");
|
|
|
|
private final String value;
|
|
|
|
visibility(String value) {
|
|
this.value = value;
|
|
}
|
|
|
|
public String getValue() {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public enum ScheduleType {
|
|
BOOST,
|
|
TIMED_MUTED
|
|
}
|
|
|
|
public interface TimedMuted {
|
|
void onTimedMute(RelationShip relationShip);
|
|
}
|
|
}
|