2020-06-25 16:57:13 +02:00
|
|
|
package app.fedilab.fedilabtube.helper;
|
2020-07-01 16:36:08 +02:00
|
|
|
/* Copyright 2020 Thomas Schneider
|
|
|
|
*
|
|
|
|
* This file is a part of TubeLab
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* TubeLab 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 TubeLab; if not,
|
|
|
|
* see <http://www.gnu.org/licenses>. */
|
2020-06-25 16:57:13 +02:00
|
|
|
|
2020-06-26 19:16:00 +02:00
|
|
|
import android.annotation.SuppressLint;
|
2020-06-26 08:50:49 +02:00
|
|
|
import android.app.Activity;
|
|
|
|
import android.app.DownloadManager;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
2020-07-09 17:57:01 +02:00
|
|
|
import android.content.res.Resources;
|
2020-06-30 11:38:06 +02:00
|
|
|
import android.database.sqlite.SQLiteDatabase;
|
2020-06-26 14:34:39 +02:00
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.graphics.Color;
|
2020-06-26 08:50:49 +02:00
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Environment;
|
2020-07-09 17:57:01 +02:00
|
|
|
import android.util.DisplayMetrics;
|
2020-06-26 14:34:39 +02:00
|
|
|
import android.util.TypedValue;
|
|
|
|
import android.view.View;
|
2020-06-26 08:50:49 +02:00
|
|
|
import android.view.WindowManager;
|
2020-06-26 14:34:39 +02:00
|
|
|
import android.webkit.CookieManager;
|
2020-06-26 08:50:49 +02:00
|
|
|
import android.webkit.URLUtil;
|
2020-06-26 14:34:39 +02:00
|
|
|
import android.webkit.WebChromeClient;
|
|
|
|
import android.webkit.WebSettings;
|
2020-06-26 08:50:49 +02:00
|
|
|
import android.widget.ImageView;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
import androidx.appcompat.app.AlertDialog;
|
2020-06-26 14:34:39 +02:00
|
|
|
import androidx.browser.customtabs.CustomTabsIntent;
|
2020-06-26 08:50:49 +02:00
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
|
|
|
|
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 java.text.DateFormat;
|
|
|
|
import java.text.ParseException;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.Date;
|
|
|
|
import java.util.Locale;
|
|
|
|
import java.util.TimeZone;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
2020-06-30 11:38:06 +02:00
|
|
|
import app.fedilab.fedilabtube.MainActivity;
|
2020-06-26 08:50:49 +02:00
|
|
|
import app.fedilab.fedilabtube.R;
|
2020-06-26 14:34:39 +02:00
|
|
|
import app.fedilab.fedilabtube.WebviewActivity;
|
2020-06-26 08:50:49 +02:00
|
|
|
import app.fedilab.fedilabtube.client.entities.Account;
|
2020-06-30 11:38:06 +02:00
|
|
|
import app.fedilab.fedilabtube.sqlite.AccountDAO;
|
|
|
|
import app.fedilab.fedilabtube.sqlite.Sqlite;
|
2020-06-26 14:34:39 +02:00
|
|
|
import app.fedilab.fedilabtube.webview.CustomWebview;
|
|
|
|
import app.fedilab.fedilabtube.webview.ProxyHelper;
|
2020-06-26 08:50:49 +02:00
|
|
|
import es.dmoral.toasty.Toasty;
|
|
|
|
|
|
|
|
import static android.content.Context.DOWNLOAD_SERVICE;
|
2020-06-25 16:57:13 +02:00
|
|
|
|
|
|
|
public class Helper {
|
|
|
|
|
2020-06-26 14:34:39 +02:00
|
|
|
public static final int RELOAD_MYVIDEOS = 10;
|
|
|
|
public static final String SET_VIDEO_MODE = "set_video_mode";
|
|
|
|
public static final int VIDEO_MODE_TORRENT = 0;
|
|
|
|
public static final int VIDEO_MODE_WEBVIEW = 1;
|
|
|
|
public static final int VIDEO_MODE_DIRECT = 2;
|
2020-06-28 19:11:39 +02:00
|
|
|
public static final int ADD_USER_INTENT = 5;
|
2020-06-26 14:34:39 +02:00
|
|
|
public static final String SET_SHARE_DETAILS = "set_share_details";
|
|
|
|
public static final int DEFAULT_VIDEO_CACHE_MB = 100;
|
2020-06-26 08:50:49 +02:00
|
|
|
public static final String TAG = "mastodon_etalab";
|
2020-07-03 17:04:04 +02:00
|
|
|
public static final String ID = "id";
|
|
|
|
public static final String CLIENT_ID = "client_id";
|
|
|
|
public static final String CLIENT_SECRET = "client_secret";
|
|
|
|
public static final String SCOPES = "scopes";
|
|
|
|
public static final String WEBSITE = "website";
|
|
|
|
public static final String WEBSITE_VALUE = "https://fedilab.app";
|
|
|
|
public static final String CLIENT_NAME_VALUE = "TubeLab";
|
|
|
|
public static final String OAUTH_SCOPES_PEERTUBE = "openid profile";
|
2020-06-26 08:50:49 +02:00
|
|
|
public static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
|
2020-07-03 17:04:04 +02:00
|
|
|
public static final String REDIRECT_URIS = "redirect_uris";
|
2020-06-26 08:50:49 +02:00
|
|
|
|
2020-06-26 14:34:39 +02:00
|
|
|
public static final Pattern hashtagPattern = Pattern.compile("(#[\\w_A-zÀ-ÿ]+)");
|
2020-07-03 17:04:04 +02:00
|
|
|
public static final Pattern redirectPattern = Pattern.compile("externalAuthToken=(\\w+)&username=([\\w.-]+)");
|
2020-06-26 08:50:49 +02:00
|
|
|
public static final String SET_VIDEO_CACHE = "set_video_cache";
|
|
|
|
//Proxy
|
|
|
|
public static final String SET_PROXY_ENABLED = "set_proxy_enabled";
|
|
|
|
public static final String SET_PROXY_TYPE = "set_proxy_type";
|
|
|
|
public static final String SET_PROXY_HOST = "set_proxy_host";
|
|
|
|
public static final String SET_PROXY_PORT = "set_proxy_port";
|
|
|
|
public static final String SET_PROXY_LOGIN = "set_proxy_login";
|
|
|
|
public static final String SET_PROXY_PASSWORD = "set_proxy_password";
|
2020-06-26 14:34:39 +02:00
|
|
|
public static final String INTENT_ACTION = "intent_action";
|
2020-06-26 08:50:49 +02:00
|
|
|
public static final String PREF_KEY_ID = "userID";
|
|
|
|
public static final String PREF_IS_MODERATOR = "is_moderator";
|
|
|
|
public static final String PREF_IS_ADMINISTRATOR = "is_administrator";
|
|
|
|
public static final String PREF_INSTANCE = "instance";
|
|
|
|
public static final String REDIRECT_CONTENT = "urn:ietf:wg:oauth:2.0:oob";
|
|
|
|
public static final int EXTERNAL_STORAGE_REQUEST_CODE = 84;
|
2020-06-26 14:34:39 +02:00
|
|
|
public static final String SET_VIDEOS_PER_PAGE = "set_videos_per_page";
|
|
|
|
public static final String VIDEO_ID = "video_id_update";
|
2020-06-26 08:50:49 +02:00
|
|
|
public static final String CLIENT_NAME = "client_name";
|
|
|
|
public static final String APP_PREFS = "app_prefs";
|
2020-07-03 17:04:04 +02:00
|
|
|
|
2020-06-26 08:50:49 +02:00
|
|
|
public static final int VIDEOS_PER_PAGE = 40;
|
|
|
|
public static final String SET_VIDEO_NSFW = "set_video_nsfw";
|
2020-06-26 14:34:39 +02:00
|
|
|
public static final String SET_EMBEDDED_BROWSER = "set_embedded_browser";
|
|
|
|
public static final String SET_CUSTOM_TABS = "set_custom_tabs";
|
2020-06-26 19:16:00 +02:00
|
|
|
public static final String INTENT_ADD_UPLOADED_MEDIA = "intent_add_uploaded_media";
|
2020-06-27 17:58:13 +02:00
|
|
|
public static final String RECEIVE_ACTION = "receive_action";
|
|
|
|
public static final String SET_UNFOLLOW_VALIDATION = "set_unfollow_validation";
|
2020-06-27 11:21:25 +02:00
|
|
|
//List of available academies
|
2020-06-27 12:23:03 +02:00
|
|
|
|
2020-07-03 17:04:04 +02:00
|
|
|
|
|
|
|
public static String[] openid = {
|
|
|
|
"ac-normandie.fr",
|
2020-07-03 17:12:18 +02:00
|
|
|
"education.fr",
|
2020-07-04 18:06:31 +02:00
|
|
|
"education.gouv.fr"
|
2020-07-03 17:04:04 +02:00
|
|
|
//TODO: remove this one used for tests
|
|
|
|
// "ac-orleans-tours.fr"
|
|
|
|
};
|
|
|
|
|
2020-06-27 12:23:03 +02:00
|
|
|
public static String[] academies = {
|
2020-06-27 11:21:25 +02:00
|
|
|
"ac-aix-marseille.fr",
|
|
|
|
"ac-amiens.fr",
|
|
|
|
"ac-besancon.fr",
|
|
|
|
"ac-bordeaux.fr",
|
2020-06-27 14:39:04 +02:00
|
|
|
"clermont-ferrand.fr",
|
2020-06-27 11:21:25 +02:00
|
|
|
"ac-corse.fr",
|
|
|
|
"ac-creteil.fr",
|
|
|
|
"ac-dijon.fr",
|
|
|
|
"ac-grenoble.fr",
|
2020-06-27 14:39:04 +02:00
|
|
|
"education.fr",
|
2020-06-27 11:21:25 +02:00
|
|
|
"ac-lille.fr",
|
|
|
|
"ac-limoges.fr",
|
|
|
|
"ac-lyon.fr",
|
|
|
|
"ac-mayotte.fr",
|
|
|
|
"ac-montpellier.fr",
|
2020-06-27 14:16:45 +02:00
|
|
|
"ac-nancy.fr",
|
2020-06-27 11:21:25 +02:00
|
|
|
"ac-nantes.fr",
|
|
|
|
"ac-normandie.fr",
|
|
|
|
"ac-orleans-tours.fr",
|
|
|
|
"ac-paris.fr",
|
|
|
|
"ac-poitiers.fr",
|
|
|
|
"outremer.fr",
|
|
|
|
"ac-rennes.fr",
|
|
|
|
"ac-strasbourg.fr",
|
|
|
|
"ac-toulouse.fr",
|
|
|
|
"ac-versailles.fr"
|
2020-06-27 12:23:03 +02:00
|
|
|
};
|
2020-06-27 11:21:25 +02:00
|
|
|
|
2020-06-29 15:43:35 +02:00
|
|
|
|
|
|
|
public static String[] valideEmails = {
|
|
|
|
"ac-aix-marseille.fr",
|
|
|
|
"ac-amiens.fr",
|
|
|
|
"ac-besancon.fr",
|
|
|
|
"ac-bordeaux.fr",
|
|
|
|
"clermont-ferrand.fr",
|
|
|
|
"ac-corse.fr",
|
|
|
|
"ac-creteil.fr",
|
|
|
|
"ac-dijon.fr",
|
|
|
|
"ac-grenoble.fr",
|
|
|
|
"education.fr",
|
|
|
|
"ac-guadeloupe.fr",
|
|
|
|
"ac-guyane.fr",
|
|
|
|
"ac-reunion.fr",
|
|
|
|
"ac-lille.fr",
|
|
|
|
"ac-limoges.fr",
|
|
|
|
"ac-lyon.fr",
|
|
|
|
"ac-martinique.fr",
|
|
|
|
"ac-mayotte.fr",
|
|
|
|
"ac-montpellier.fr",
|
|
|
|
"ac-nancy.fr",
|
|
|
|
"ac-nantes.fr",
|
|
|
|
"ac-normandie.fr",
|
|
|
|
"ac-orleans-tours.fr",
|
|
|
|
"ac-paris.fr",
|
|
|
|
"ac-poitiers.fr",
|
|
|
|
"ac-rennes.fr",
|
|
|
|
"ac-spm.fr",
|
|
|
|
"ac-strasbourg.fr",
|
|
|
|
"ac-toulouse.fr",
|
|
|
|
"ac-versailles.fr",
|
|
|
|
"ac-wf.wf",
|
|
|
|
"monvr.pf",
|
|
|
|
"ac-noumea.nc",
|
|
|
|
"education.gouv.fr",
|
|
|
|
"igesr.gouv.fr"
|
|
|
|
};
|
|
|
|
|
2020-06-25 16:57:13 +02:00
|
|
|
/**
|
|
|
|
* Returns the peertube URL depending of the academic domain name
|
2020-06-27 11:21:25 +02:00
|
|
|
*
|
2020-06-25 16:57:13 +02:00
|
|
|
* @param acad String academic domain name
|
|
|
|
* @return String the peertube URL
|
|
|
|
*/
|
2020-06-28 19:11:39 +02:00
|
|
|
public static String getPeertubeUrl(String acad) {
|
2020-06-29 16:43:20 +02:00
|
|
|
|
|
|
|
if (acad.compareTo("education.gouv.fr") == 0 || acad.compareTo("igesr.gouv.fr") == 0) {
|
|
|
|
acad = "education.fr";
|
|
|
|
} else if (acad.compareTo("ac-nancy-metz.fr") == 0) {
|
|
|
|
acad = "ac-nancy.fr";
|
|
|
|
} else if (acad.compareTo("clermont.fr") == 0) {
|
|
|
|
acad = "clermont-ferrand.fr";
|
|
|
|
} else if (acad.compareTo("ac-wf.wf") == 0 || acad.compareTo("ac-mayotte.fr") == 0 || acad.compareTo("ac-noumea.nc") == 0
|
|
|
|
|| acad.compareTo("ac-guadeloupe.fr") == 0 || acad.compareTo("monvr.pf") == 0 || acad.compareTo("ac-reunion.fr") == 0 ||
|
|
|
|
acad.compareTo("ac-martinique.fr") == 0 || acad.compareTo("ac-guyane.fr") == 0
|
|
|
|
) {
|
|
|
|
acad = "outremer.fr";
|
|
|
|
}
|
2020-07-01 16:36:08 +02:00
|
|
|
if (!acad.contains("ac-lyon.fr")) {
|
2020-07-03 17:04:04 +02:00
|
|
|
//TODO: remove hack for test with openid
|
|
|
|
/*if( acad.contains("orleans-tours.fr")) {
|
|
|
|
return "tube-normandie.beta.education.fr";
|
|
|
|
}*/
|
2020-07-01 15:19:24 +02:00
|
|
|
return "tube-" + acad.replaceAll("ac-|\\.fr", "") + ".beta.education.fr";
|
2020-07-01 16:36:08 +02:00
|
|
|
} else {
|
2020-07-01 15:19:24 +02:00
|
|
|
return "tube.ac-lyon.fr";
|
|
|
|
}
|
2020-06-25 16:57:13 +02:00
|
|
|
}
|
2020-06-26 08:50:49 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the instance of the authenticated user
|
|
|
|
*
|
|
|
|
* @param context Context
|
|
|
|
* @return String domain instance
|
|
|
|
*/
|
|
|
|
public static String getLiveInstance(Context context) {
|
|
|
|
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
2020-07-01 15:19:24 +02:00
|
|
|
String acad = sharedpreferences.getString(Helper.PREF_INSTANCE, "tube.ac-lyon.fr");
|
2020-07-03 17:04:04 +02:00
|
|
|
if (acad.startsWith("tube-")) {
|
|
|
|
return acad;
|
|
|
|
} else {
|
|
|
|
return getPeertubeUrl(acad);
|
|
|
|
}
|
2020-06-26 08:50:49 +02:00
|
|
|
}
|
|
|
|
|
2020-06-26 19:16:00 +02:00
|
|
|
public static String instanceWithProtocol(Context context) {
|
2020-06-27 11:21:25 +02:00
|
|
|
return "https://" + getLiveInstance(context);
|
2020-06-26 08:50:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert String date from Mastodon
|
|
|
|
*
|
|
|
|
* @param date String
|
|
|
|
* @return Date
|
|
|
|
*/
|
|
|
|
public static Date mstStringToDate(String date) throws ParseException {
|
|
|
|
if (date == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
String STRING_DATE_FORMAT;
|
|
|
|
Locale local = Locale.getDefault();
|
|
|
|
if (!date.contains("+")) {
|
|
|
|
STRING_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
|
|
|
|
} else { //GNU date format
|
|
|
|
STRING_DATE_FORMAT = "EEE MMM dd HH:mm:ss ZZZZZ yyyy";
|
|
|
|
local = Locale.ENGLISH;
|
|
|
|
}
|
|
|
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(STRING_DATE_FORMAT, local);
|
|
|
|
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("gmt"));
|
|
|
|
simpleDateFormat.setLenient(true);
|
|
|
|
try {
|
|
|
|
return simpleDateFormat.parse(date);
|
|
|
|
} catch (Exception e) {
|
|
|
|
String newdate = date.split("\\+")[0].trim();
|
|
|
|
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", local);
|
|
|
|
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("gmt"));
|
|
|
|
simpleDateFormat.setLenient(true);
|
|
|
|
return simpleDateFormat.parse(newdate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
|
|
|
*
|
|
|
|
* @param date Date
|
|
|
|
* @return String
|
|
|
|
*/
|
|
|
|
public static String dateToString(Date date) {
|
|
|
|
if (date == null)
|
|
|
|
return null;
|
|
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
|
|
|
return dateFormat.format(date);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert String date from db to Date Object
|
|
|
|
*
|
|
|
|
* @param stringDate date to convert
|
|
|
|
* @return Date
|
|
|
|
*/
|
|
|
|
public static Date stringToDate(Context context, String stringDate) {
|
|
|
|
if (stringDate == null)
|
|
|
|
return null;
|
|
|
|
Locale userLocale;
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
|
userLocale = context.getResources().getConfiguration().getLocales().get(0);
|
|
|
|
} else {
|
|
|
|
userLocale = context.getResources().getConfiguration().locale;
|
|
|
|
}
|
|
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", userLocale);
|
|
|
|
Date date = null;
|
|
|
|
try {
|
|
|
|
date = dateFormat.parse(stringDate);
|
|
|
|
} catch (java.text.ParseException ignored) {
|
|
|
|
|
|
|
|
}
|
|
|
|
return date;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static String secondsToString(int pTime) {
|
|
|
|
|
|
|
|
int hour = pTime / 3600;
|
|
|
|
int min = (pTime - (hour * 3600)) / 60;
|
|
|
|
int sec = pTime - (hour * 3600) - (min * 60);
|
|
|
|
String strHour = "0", strMin = "0", strSec;
|
|
|
|
|
|
|
|
if (hour > 0)
|
|
|
|
strHour = String.format(Locale.getDefault(), "%02d", hour);
|
|
|
|
if (min > 0)
|
|
|
|
strMin = String.format(Locale.getDefault(), "%02d", min);
|
|
|
|
strSec = String.format(Locale.getDefault(), "%02d", sec);
|
|
|
|
if (hour > 0)
|
|
|
|
return String.format(Locale.getDefault(), "%s:%s:%s", strHour, strMin, strSec);
|
|
|
|
else
|
|
|
|
return String.format(Locale.getDefault(), "%s:%s", strMin, strSec);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
|
|
* Returns a String depending of the date
|
|
|
|
* @param context Context
|
|
|
|
* @param dateToot Date
|
|
|
|
* @return String
|
|
|
|
*/
|
|
|
|
public static String dateDiff(Context context, Date dateToot) {
|
|
|
|
Date now = new Date();
|
|
|
|
long diff = now.getTime() - dateToot.getTime();
|
|
|
|
long seconds = diff / 1000;
|
|
|
|
long minutes = seconds / 60;
|
|
|
|
long hours = minutes / 60;
|
|
|
|
long days = hours / 24;
|
|
|
|
long months = days / 30;
|
|
|
|
long years = days / 365;
|
|
|
|
|
|
|
|
String format = DateFormat.getDateInstance(DateFormat.SHORT).format(dateToot);
|
|
|
|
if (years > 0) {
|
|
|
|
return format;
|
|
|
|
} else if (months > 0 || days > 7) {
|
|
|
|
//Removes the year depending of the locale from DateFormat.SHORT format
|
|
|
|
SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
|
|
|
|
df.applyPattern(df.toPattern().replaceAll("[^\\p{Alpha}]*y+[^\\p{Alpha}]*", ""));
|
|
|
|
return df.format(dateToot);
|
|
|
|
} else if (days > 0)
|
|
|
|
return context.getString(R.string.date_day, days);
|
|
|
|
else if (hours > 0)
|
|
|
|
return context.getResources().getString(R.string.date_hours, (int) hours);
|
|
|
|
else if (minutes > 0)
|
|
|
|
return context.getResources().getString(R.string.date_minutes, (int) minutes);
|
|
|
|
else {
|
|
|
|
if (seconds < 0)
|
|
|
|
seconds = 0;
|
|
|
|
return context.getResources().getString(R.string.date_seconds, (int) seconds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-27 17:58:13 +02:00
|
|
|
/**
|
|
|
|
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
|
|
|
*
|
|
|
|
* @param date Date
|
|
|
|
* @return String
|
|
|
|
*/
|
|
|
|
public static String shortDateToString(Date date) {
|
|
|
|
SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
|
|
|
|
return df.format(date);
|
|
|
|
}
|
|
|
|
|
2020-06-26 08:50:49 +02:00
|
|
|
|
|
|
|
public static String withSuffix(long count) {
|
|
|
|
if (count < 1000) return "" + count;
|
|
|
|
int exp = (int) (Math.log(count) / Math.log(1000));
|
|
|
|
Locale locale = null;
|
|
|
|
try {
|
|
|
|
locale = Locale.getDefault();
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
}
|
|
|
|
if (locale != null)
|
|
|
|
return String.format(locale, "%.1f %c",
|
|
|
|
count / Math.pow(1000, exp),
|
|
|
|
"kMGTPE".charAt(exp - 1));
|
|
|
|
else
|
|
|
|
return String.format(Locale.getDefault(), "%.1f %c",
|
|
|
|
count / Math.pow(1000, exp),
|
|
|
|
"kMGTPE".charAt(exp - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void loadGiF(final Context context, Account account, final ImageView imageView) {
|
2020-06-27 11:21:25 +02:00
|
|
|
|
|
|
|
|
2020-06-27 19:08:52 +02:00
|
|
|
if (account == null || account.getAvatar() == null || account.getAvatar().compareTo("null") == 0) {
|
2020-06-27 11:21:25 +02:00
|
|
|
Glide.with(imageView.getContext())
|
|
|
|
.asDrawable()
|
|
|
|
.load(R.drawable.missing_peertube)
|
|
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
|
|
.into(imageView);
|
|
|
|
return;
|
|
|
|
}
|
2020-06-26 08:50:49 +02:00
|
|
|
String url = account.getAvatar();
|
2020-06-27 19:08:52 +02:00
|
|
|
if (url.startsWith("/")) {
|
2020-06-26 19:16:00 +02:00
|
|
|
url = Helper.getLiveInstance(context) + url;
|
2020-06-26 08:50:49 +02:00
|
|
|
}
|
2020-06-28 19:11:39 +02:00
|
|
|
if (!url.startsWith("http")) {
|
2020-06-28 10:02:30 +02:00
|
|
|
url = "https://" + url;
|
|
|
|
}
|
2020-06-26 08:50:49 +02:00
|
|
|
try {
|
|
|
|
Glide.with(imageView.getContext())
|
|
|
|
.load(url)
|
|
|
|
.thumbnail(0.1f)
|
|
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
|
|
.into(imageView);
|
|
|
|
} catch (Exception e) {
|
|
|
|
try {
|
|
|
|
Glide.with(imageView.getContext())
|
|
|
|
.asDrawable()
|
|
|
|
.load(R.drawable.missing_peertube)
|
|
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
|
|
.into(imageView);
|
|
|
|
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-01 15:08:42 +02:00
|
|
|
public static void loadGiF(final Context context, String url, final ImageView imageView) {
|
|
|
|
|
|
|
|
if (url.startsWith("/")) {
|
|
|
|
url = Helper.getLiveInstance(context) + url;
|
|
|
|
}
|
|
|
|
if (!url.startsWith("http")) {
|
|
|
|
url = "https://" + url;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
Glide.with(imageView.getContext())
|
|
|
|
.load(url)
|
|
|
|
.thumbnail(0.1f)
|
|
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
|
|
.into(imageView);
|
|
|
|
} catch (Exception e) {
|
|
|
|
try {
|
|
|
|
Glide.with(imageView.getContext())
|
|
|
|
.asDrawable()
|
|
|
|
.load(R.drawable.missing_peertube)
|
|
|
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
|
|
|
.into(imageView);
|
|
|
|
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-26 08:50:49 +02:00
|
|
|
/**
|
|
|
|
* Manage URLs to open (built-in or external app)
|
|
|
|
*
|
|
|
|
* @param context Context
|
|
|
|
* @param url String url to open
|
|
|
|
*/
|
|
|
|
public static void openBrowser(Context context, String url) {
|
|
|
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
|
|
|
|
boolean embedded_browser = sharedpreferences.getBoolean(Helper.SET_EMBEDDED_BROWSER, true);
|
|
|
|
if (embedded_browser) {
|
|
|
|
Intent intent = new Intent(context, WebviewActivity.class);
|
|
|
|
Bundle b = new Bundle();
|
|
|
|
String finalUrl = url;
|
|
|
|
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
|
|
|
|
finalUrl = "http://" + url;
|
|
|
|
b.putString("url", finalUrl);
|
|
|
|
intent.putExtras(b);
|
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
|
|
context.startActivity(intent);
|
|
|
|
} else {
|
|
|
|
boolean custom_tabs = sharedpreferences.getBoolean(Helper.SET_CUSTOM_TABS, true);
|
|
|
|
if (custom_tabs) {
|
|
|
|
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
|
|
|
CustomTabsIntent customTabsIntent = builder.build();
|
2020-06-26 14:34:39 +02:00
|
|
|
builder.setToolbarColor(ContextCompat.getColor(context, R.color.colorPrimary));
|
2020-06-26 08:50:49 +02:00
|
|
|
try {
|
|
|
|
customTabsIntent.launchUrl(context, Uri.parse(url));
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
|
|
intent.setData(Uri.parse(url));
|
|
|
|
try {
|
|
|
|
context.startActivity(intent);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-26 19:16:00 +02:00
|
|
|
@SuppressLint("SetJavaScriptEnabled")
|
2020-06-26 14:34:39 +02:00
|
|
|
public static CustomWebview initializeWebview(Activity activity, int webviewId, View rootView) {
|
|
|
|
|
|
|
|
CustomWebview webView;
|
|
|
|
if (rootView == null) {
|
|
|
|
webView = activity.findViewById(webviewId);
|
|
|
|
} else {
|
|
|
|
webView = rootView.findViewById(webviewId);
|
|
|
|
}
|
|
|
|
final SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
|
|
|
|
|
|
|
webView.getSettings().setJavaScriptEnabled(true);
|
|
|
|
webView.getSettings().setUseWideViewPort(true);
|
|
|
|
webView.getSettings().setLoadWithOverviewMode(true);
|
|
|
|
webView.getSettings().setSupportZoom(true);
|
|
|
|
webView.getSettings().setDisplayZoomControls(false);
|
|
|
|
webView.getSettings().setBuiltInZoomControls(true);
|
|
|
|
webView.getSettings().setAllowContentAccess(true);
|
|
|
|
webView.getSettings().setLoadsImagesAutomatically(true);
|
|
|
|
webView.getSettings().setSupportMultipleWindows(false);
|
|
|
|
webView.getSettings().setMediaPlaybackRequiresUserGesture(true);
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
|
|
CookieManager cookieManager = CookieManager.getInstance();
|
|
|
|
cookieManager.setAcceptThirdPartyCookies(webView, false);
|
|
|
|
}
|
|
|
|
webView.setBackgroundColor(Color.TRANSPARENT);
|
|
|
|
webView.getSettings().setAppCacheEnabled(true);
|
|
|
|
webView.getSettings().setDatabaseEnabled(true);
|
|
|
|
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
|
|
|
|
webView.setWebChromeClient(new WebChromeClient() {
|
|
|
|
@Override
|
|
|
|
public Bitmap getDefaultVideoPoster() {
|
|
|
|
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
boolean proxyEnabled = sharedpreferences.getBoolean(Helper.SET_PROXY_ENABLED, false);
|
|
|
|
if (proxyEnabled) {
|
|
|
|
String host = sharedpreferences.getString(Helper.SET_PROXY_HOST, "127.0.0.1");
|
|
|
|
int port = sharedpreferences.getInt(Helper.SET_PROXY_PORT, 8118);
|
|
|
|
ProxyHelper.setProxy(activity, webView, host, port, WebviewActivity.class.getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
return webView;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-26 08:50:49 +02:00
|
|
|
/**
|
|
|
|
* Manage downloads with URLs
|
|
|
|
*
|
|
|
|
* @param context Context
|
|
|
|
* @param url String download url
|
|
|
|
*/
|
|
|
|
public static void manageDownloads(final Context context, final String url) {
|
|
|
|
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
|
|
final DownloadManager.Request request;
|
|
|
|
try {
|
|
|
|
request = new DownloadManager.Request(Uri.parse(url.trim()));
|
|
|
|
} catch (Exception e) {
|
|
|
|
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
final String fileName = URLUtil.guessFileName(url, null, null);
|
|
|
|
builder.setMessage(context.getResources().getString(R.string.download_file, fileName));
|
|
|
|
builder.setCancelable(false)
|
|
|
|
.setPositiveButton(context.getString(R.string.yes), (dialog, id) -> {
|
|
|
|
request.allowScanningByMediaScanner();
|
|
|
|
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
|
|
|
|
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
|
|
|
DownloadManager dm = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
|
|
|
|
assert dm != null;
|
|
|
|
dm.enqueue(request);
|
|
|
|
dialog.dismiss();
|
|
|
|
})
|
|
|
|
.setNegativeButton(context.getString(R.string.cancel), (dialog, id) -> dialog.cancel());
|
|
|
|
AlertDialog alert = builder.create();
|
|
|
|
if (alert.getWindow() != null)
|
|
|
|
alert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
|
|
|
alert.show();
|
|
|
|
}
|
|
|
|
|
2020-06-26 14:34:39 +02:00
|
|
|
|
2020-06-30 11:38:06 +02:00
|
|
|
/**
|
|
|
|
* Log out the authenticated user by removing its token
|
|
|
|
*
|
|
|
|
* @param activity Activity
|
|
|
|
*/
|
|
|
|
public static void logoutCurrentUser(Activity activity, Account account) {
|
|
|
|
SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
|
|
|
|
|
|
|
SQLiteDatabase db = Sqlite.getInstance(activity.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
|
|
|
if (account != null) {
|
|
|
|
new AccountDAO(activity, db).removeUser(account);
|
|
|
|
}
|
|
|
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
|
|
|
editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, null);
|
|
|
|
editor.putString(Helper.CLIENT_ID, null);
|
|
|
|
editor.putString(Helper.CLIENT_SECRET, null);
|
|
|
|
editor.putString(Helper.PREF_KEY_ID, null);
|
|
|
|
editor.putBoolean(Helper.PREF_IS_MODERATOR, false);
|
|
|
|
editor.putBoolean(Helper.PREF_IS_ADMINISTRATOR, false);
|
|
|
|
editor.putString(Helper.PREF_INSTANCE, null);
|
|
|
|
editor.putString(Helper.ID, null);
|
|
|
|
editor.apply();
|
|
|
|
Intent mainActivity = new Intent(activity, MainActivity.class);
|
|
|
|
mainActivity.putExtra(Helper.INTENT_ACTION, Helper.ADD_USER_INTENT);
|
|
|
|
activity.startActivity(mainActivity);
|
|
|
|
activity.finish();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-29 17:59:36 +02:00
|
|
|
public static int getAttColor(Context context, int attColor) {
|
|
|
|
TypedValue typedValue = new TypedValue();
|
|
|
|
context.getTheme().resolveAttribute(attColor, typedValue, true);
|
|
|
|
return ContextCompat.getColor(context, typedValue.resourceId);
|
|
|
|
}
|
|
|
|
|
2020-06-27 11:21:25 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns boolean depending if the user is authenticated
|
|
|
|
*
|
|
|
|
* @param context Context
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
public static boolean isLoggedIn(Context context) {
|
|
|
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
|
|
|
String prefKeyOauthTokenT = sharedpreferences.getString(PREF_KEY_OAUTH_TOKEN, null);
|
|
|
|
return (prefKeyOauthTokenT != null);
|
|
|
|
}
|
|
|
|
|
2020-07-09 17:57:01 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts dp to pixel
|
|
|
|
*
|
|
|
|
* @param dp float - the value in dp to convert
|
|
|
|
* @param context Context
|
|
|
|
* @return float - the converted value in pixel
|
|
|
|
*/
|
|
|
|
public static float convertDpToPixel(float dp, Context context) {
|
|
|
|
Resources resources = context.getResources();
|
|
|
|
DisplayMetrics metrics = resources.getDisplayMetrics();
|
|
|
|
return dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean isTablet(Context context) {
|
|
|
|
return context.getResources().getBoolean(R.bool.is_tablet);
|
|
|
|
}
|
|
|
|
|
2020-06-25 16:57:13 +02:00
|
|
|
}
|