mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-02 07:08:55 +01:00
Rename project
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public class AndroidComponentUtil {
|
||||
|
||||
public static void toggleComponent(Context context, Class componentClass, boolean enable) {
|
||||
Timber.i((enable ? "Enabling " : "Disabling ") + componentClass.getSimpleName());
|
||||
ComponentName componentName = new ComponentName(context, componentClass);
|
||||
PackageManager pm = context.getPackageManager();
|
||||
pm.setComponentEnabledSetting(componentName,
|
||||
enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
}
|
||||
|
||||
public static boolean isServiceRunning(Context context, Class serviceClass) {
|
||||
ActivityManager manager =
|
||||
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
if (serviceClass.getName().equals(service.service.getClassName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter;
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga;
|
||||
|
||||
public class ChapterRecognition {
|
||||
|
||||
private static final Pattern p1 = Pattern.compile("ch[^0-9]?\\s*(\\d+[\\.,]?\\d*)");
|
||||
private static final Pattern p2 = Pattern.compile("(\\d+[\\.,]?\\d*)");
|
||||
private static final Pattern p3 = Pattern.compile("(\\d+[\\.,]?\\d*\\s*:)");
|
||||
|
||||
private static final Pattern pUnwanted =
|
||||
Pattern.compile("\\b(v|ver|vol|version|volume)\\.?\\s*\\d+\\b");
|
||||
|
||||
public static void parseChapterNumber(Chapter chapter, Manga manga) {
|
||||
if (chapter.chapter_number != -1)
|
||||
return;
|
||||
|
||||
String name = chapter.name.toLowerCase();
|
||||
Matcher matcher;
|
||||
|
||||
// Safest option, the chapter has a token prepended
|
||||
matcher = p1.matcher(name);
|
||||
if (matcher.find()) {
|
||||
chapter.chapter_number = Float.parseFloat(matcher.group(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove anything related to the volume or version
|
||||
name = pUnwanted.matcher(name).replaceAll("");
|
||||
|
||||
List<Float> occurrences;
|
||||
|
||||
// If there's only one number, use it
|
||||
matcher = p2.matcher(name);
|
||||
occurrences = getAllOccurrences(matcher);
|
||||
if (occurrences.size() == 1) {
|
||||
chapter.chapter_number = occurrences.get(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// If it has a colon, the chapter number should be that one
|
||||
matcher = p3.matcher(name);
|
||||
occurrences = getAllOccurrences(matcher);
|
||||
if (occurrences.size() == 1) {
|
||||
chapter.chapter_number = occurrences.get(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// This can lead to issues if two numbers are separated by an space
|
||||
name = name.replaceAll("\\s+", "");
|
||||
|
||||
// Try to remove the manga name from the chapter, and try again
|
||||
String mangaName = replaceIrrelevantCharacters(manga.title);
|
||||
String nameWithoutManga = difference(mangaName, name);
|
||||
if (!nameWithoutManga.isEmpty()) {
|
||||
matcher = p2.matcher(nameWithoutManga);
|
||||
occurrences = getAllOccurrences(matcher);
|
||||
if (occurrences.size() == 1) {
|
||||
chapter.chapter_number = occurrences.get(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO more checks (maybe levenshtein?)
|
||||
|
||||
}
|
||||
|
||||
public static List<Float> getAllOccurrences(Matcher matcher) {
|
||||
List<Float> occurences = new ArrayList<>();
|
||||
while (matcher.find()) {
|
||||
// Match again to get only numbers from the captured text
|
||||
String text = matcher.group();
|
||||
Matcher m = p2.matcher(text);
|
||||
if (m.find()) {
|
||||
try {
|
||||
Float value = Float.parseFloat(m.group(1));
|
||||
if (!occurences.contains(value)) {
|
||||
occurences.add(value);
|
||||
}
|
||||
} catch (NumberFormatException e) { /* Do nothing */ }
|
||||
}
|
||||
}
|
||||
return occurences;
|
||||
}
|
||||
|
||||
public static String replaceIrrelevantCharacters(String str) {
|
||||
return str.replaceAll("\\s+", "").toLowerCase();
|
||||
}
|
||||
|
||||
public static String difference(String str1, String str2) {
|
||||
if (str1 == null) {
|
||||
return str2;
|
||||
}
|
||||
if (str2 == null) {
|
||||
return str1;
|
||||
}
|
||||
int at = indexOfDifference(str1, str2);
|
||||
if (at == -1) {
|
||||
return "";
|
||||
}
|
||||
return str2.substring(at);
|
||||
}
|
||||
public static int indexOfDifference(String str1, String str2) {
|
||||
if (str1 == str2) {
|
||||
return -1;
|
||||
}
|
||||
if (str1 == null || str2 == null) {
|
||||
return 0;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < str1.length() && i < str2.length(); ++i) {
|
||||
if (str1.charAt(i) != str2.charAt(i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < str2.length() || i < str1.length()) {
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
100
app/src/main/java/eu/kanade/tachiyomi/util/DiskUtils.java
Normal file
100
app/src/main/java/eu/kanade/tachiyomi/util/DiskUtils.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
|
||||
public final class DiskUtils {
|
||||
|
||||
private DiskUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static String hashKeyForDisk(String key) {
|
||||
String cacheKey;
|
||||
try {
|
||||
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
|
||||
mDigest.update(key.getBytes());
|
||||
cacheKey = bytesToHexString(mDigest.digest());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
cacheKey = String.valueOf(key.hashCode());
|
||||
}
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
private static String bytesToHexString(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
String hex = Integer.toHexString(0xFF & bytes[i]);
|
||||
if (hex.length() == 1) {
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(hex);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static File saveBufferedSourceToDirectory(BufferedSource bufferedSource, File directory, String name) throws IOException {
|
||||
createDirectory(directory);
|
||||
|
||||
File writeFile = new File(directory, name);
|
||||
if (writeFile.exists()) {
|
||||
if (writeFile.delete()) {
|
||||
writeFile = new File(directory, name);
|
||||
} else {
|
||||
throw new IOException("Failed Deleting Existing File for Overwrite");
|
||||
}
|
||||
}
|
||||
|
||||
BufferedSink bufferedSink = null;
|
||||
try {
|
||||
bufferedSink = Okio.buffer(Okio.sink(writeFile));
|
||||
bufferedSink.writeAll(bufferedSource);
|
||||
} catch (Exception e) {
|
||||
writeFile.delete();
|
||||
throw new IOException("Unable to save image");
|
||||
} finally {
|
||||
if (bufferedSink != null) {
|
||||
bufferedSink.close();
|
||||
}
|
||||
}
|
||||
|
||||
return writeFile;
|
||||
}
|
||||
|
||||
public static void deleteFiles(File inputFile) {
|
||||
if (inputFile.isDirectory()) {
|
||||
for (File childFile : inputFile.listFiles()) {
|
||||
deleteFiles(childFile);
|
||||
}
|
||||
}
|
||||
|
||||
inputFile.delete();
|
||||
}
|
||||
|
||||
public static synchronized void createDirectory(File directory) throws IOException {
|
||||
if (!directory.exists() && !directory.mkdirs()) {
|
||||
throw new IOException("Failed creating directory");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static long getDirectorySize(File f) {
|
||||
long size = 0;
|
||||
if (f.isDirectory()) {
|
||||
for (File file : f.listFiles()) {
|
||||
size += getDirectorySize(file);
|
||||
}
|
||||
} else {
|
||||
size=f.length();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import rx.Observable;
|
||||
import rx.Observable.Operator;
|
||||
import rx.Subscriber;
|
||||
import rx.Subscription;
|
||||
import rx.functions.Func1;
|
||||
import rx.subscriptions.CompositeSubscription;
|
||||
import rx.subscriptions.Subscriptions;
|
||||
|
||||
public class DynamicConcurrentMergeOperator<T, R> implements Operator<R, T> {
|
||||
final Func1<? super T, ? extends Observable<? extends R>> mapper;
|
||||
final Observable<Integer> workerCount;
|
||||
|
||||
public DynamicConcurrentMergeOperator(
|
||||
Func1<? super T, ? extends Observable<? extends R>> mapper,
|
||||
Observable<Integer> workerCount) {
|
||||
this.mapper = mapper;
|
||||
this.workerCount = workerCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subscriber<? super T> call(Subscriber<? super R> t) {
|
||||
DynamicConcurrentMerge<T, R> parent = new DynamicConcurrentMerge<>(t, mapper);
|
||||
t.add(parent);
|
||||
parent.init(workerCount);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
static final class DynamicConcurrentMerge<T, R> extends Subscriber<T> {
|
||||
final Subscriber<? super R> actual;
|
||||
final Func1<? super T, ? extends Observable<? extends R>> mapper;
|
||||
final Queue<T> queue;
|
||||
final CopyOnWriteArrayList<DynamicWorker<T, R>> workers;
|
||||
final CompositeSubscription composite;
|
||||
final AtomicInteger wipActive;
|
||||
final AtomicBoolean once;
|
||||
long id;
|
||||
|
||||
public DynamicConcurrentMerge(Subscriber<? super R> actual,
|
||||
Func1<? super T, ? extends Observable<? extends R>> mapper) {
|
||||
this.actual = actual;
|
||||
this.mapper = mapper;
|
||||
this.queue = new ConcurrentLinkedQueue<>();
|
||||
this.workers = new CopyOnWriteArrayList<>();
|
||||
this.composite = new CompositeSubscription();
|
||||
this.wipActive = new AtomicInteger(1);
|
||||
this.once = new AtomicBoolean();
|
||||
this.add(composite);
|
||||
this.request(0);
|
||||
}
|
||||
|
||||
public void init(Observable<Integer> workerCount) {
|
||||
Subscription wc = workerCount.subscribe(n -> {
|
||||
int n0 = workers.size();
|
||||
if (n0 < n) {
|
||||
for (int i = n0; i < n; i++) {
|
||||
DynamicWorker<T, R> dw = new DynamicWorker<>(++id, this);
|
||||
workers.add(dw);
|
||||
request(1);
|
||||
dw.tryNext();
|
||||
}
|
||||
} else if (n0 > n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
workers.get(i).start();
|
||||
}
|
||||
|
||||
for (int i = n0 - 1; i >= n; i--) {
|
||||
workers.get(i).stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (!once.get() && once.compareAndSet(false, true)) {
|
||||
request(n);
|
||||
}
|
||||
}, this::onError);
|
||||
|
||||
composite.add(wc);
|
||||
}
|
||||
|
||||
void requestMore(long n) {
|
||||
request(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(T t) {
|
||||
queue.offer(t);
|
||||
wipActive.getAndIncrement();
|
||||
for (DynamicWorker<T, R> w : workers) {
|
||||
w.tryNext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
composite.unsubscribe();
|
||||
actual.onError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
if (wipActive.decrementAndGet() == 0) {
|
||||
actual.onCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final class DynamicWorker<T, R> {
|
||||
final long id;
|
||||
final AtomicBoolean running;
|
||||
final DynamicConcurrentMerge<T, R> parent;
|
||||
final AtomicBoolean stop;
|
||||
|
||||
public DynamicWorker(long id, DynamicConcurrentMerge<T, R> parent) {
|
||||
this.id = id;
|
||||
this.parent = parent;
|
||||
this.stop = new AtomicBoolean();
|
||||
this.running = new AtomicBoolean();
|
||||
}
|
||||
|
||||
public void tryNext() {
|
||||
if (!running.get() && running.compareAndSet(false, true)) {
|
||||
T t;
|
||||
if (stop.get()) {
|
||||
parent.workers.remove(this);
|
||||
return;
|
||||
}
|
||||
t = parent.queue.poll();
|
||||
if (t == null) {
|
||||
running.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Observable out = parent.mapper.call(t);
|
||||
|
||||
Subscriber<R> s = new Subscriber<R>() {
|
||||
@Override
|
||||
public void onNext(R t) {
|
||||
parent.actual.onNext(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
parent.onError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
parent.onCompleted();
|
||||
if (parent.wipActive.get() != 0) {
|
||||
running.set(false);
|
||||
parent.requestMore(1);
|
||||
tryNext();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
parent.composite.add(s);
|
||||
s.add(Subscriptions.create(() -> parent.composite.remove(s)));
|
||||
|
||||
// Unchecked assignment to avoid weird Android Studio errors
|
||||
out.subscribe(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
stop.set(false);
|
||||
tryNext();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
stop.set(true);
|
||||
if (running.compareAndSet(false, true)) {
|
||||
parent.workers.remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
public @interface EventBusHook {}
|
||||
50
app/src/main/java/eu/kanade/tachiyomi/util/GLUtil.java
Normal file
50
app/src/main/java/eu/kanade/tachiyomi/util/GLUtil.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLContext;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
|
||||
public class GLUtil {
|
||||
|
||||
public static int getMaxTextureSize() {
|
||||
// Safe minimum default size
|
||||
final int IMAGE_MAX_BITMAP_DIMENSION = 2048;
|
||||
|
||||
// Get EGL Display
|
||||
EGL10 egl = (EGL10) EGLContext.getEGL();
|
||||
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
|
||||
// Initialise
|
||||
int[] version = new int[2];
|
||||
egl.eglInitialize(display, version);
|
||||
|
||||
// Query total number of configurations
|
||||
int[] totalConfigurations = new int[1];
|
||||
egl.eglGetConfigs(display, null, 0, totalConfigurations);
|
||||
|
||||
// Query actual list configurations
|
||||
EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]];
|
||||
egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations);
|
||||
|
||||
int[] textureSize = new int[1];
|
||||
int maximumTextureSize = 0;
|
||||
|
||||
// Iterate through all the configurations to located the maximum texture size
|
||||
for (int i = 0; i < totalConfigurations[0]; i++) {
|
||||
// Only need to check for width since opengl textures are always squared
|
||||
egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize);
|
||||
|
||||
// Keep track of the maximum texture size
|
||||
if (maximumTextureSize < textureSize[0])
|
||||
maximumTextureSize = textureSize[0];
|
||||
}
|
||||
|
||||
// Release
|
||||
egl.eglTerminate(display);
|
||||
|
||||
// Return largest texture size found, or default
|
||||
return Math.max(maximumTextureSize, IMAGE_MAX_BITMAP_DIMENSION);
|
||||
}
|
||||
|
||||
}
|
||||
16
app/src/main/java/eu/kanade/tachiyomi/util/NetworkUtil.java
Normal file
16
app/src/main/java/eu/kanade/tachiyomi/util/NetworkUtil.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
|
||||
public class NetworkUtil {
|
||||
|
||||
public static boolean isNetworkConnected(Context context) {
|
||||
ConnectivityManager cm =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
||||
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
|
||||
}
|
||||
|
||||
}
|
||||
48
app/src/main/java/eu/kanade/tachiyomi/util/Parser.java
Normal file
48
app/src/main/java/eu/kanade/tachiyomi/util/Parser.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
public class Parser {
|
||||
|
||||
@Nullable
|
||||
public static Element element(Element container, String pattern) {
|
||||
return container.select(pattern).first();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String text(Element container, String pattern) {
|
||||
return text(container, pattern, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String text(Element container, String pattern, String defValue) {
|
||||
Element element = container.select(pattern).first();
|
||||
return element != null ? element.text() : defValue;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String allText(Element container, String pattern) {
|
||||
Elements elements = container.select(pattern);
|
||||
return !elements.isEmpty() ? elements.text() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String attr(Element container, String pattern, String attr) {
|
||||
Element element = container.select(pattern).first();
|
||||
return element != null ? element.attr(attr) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String href(Element container, String pattern) {
|
||||
return attr(container, pattern, "href");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String src(Element container, String pattern) {
|
||||
return attr(container, pattern, "src");
|
||||
}
|
||||
|
||||
}
|
||||
32
app/src/main/java/eu/kanade/tachiyomi/util/RxPager.java
Normal file
32
app/src/main/java/eu/kanade/tachiyomi/util/RxPager.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import rx.Observable;
|
||||
import rx.subjects.PublishSubject;
|
||||
|
||||
public class RxPager {
|
||||
|
||||
private final int initialPageCount;
|
||||
private final PublishSubject<Integer> requests = PublishSubject.create();
|
||||
private int requestedCount;
|
||||
|
||||
public RxPager() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public RxPager(int initialPageCount) {
|
||||
this.initialPageCount = initialPageCount;
|
||||
}
|
||||
|
||||
public void requestNext(int page) {
|
||||
requests.onNext(page);
|
||||
}
|
||||
|
||||
public Observable<Integer> pages() {
|
||||
return requests
|
||||
.concatMap(targetPage -> targetPage <= requestedCount ?
|
||||
Observable.<Integer>empty() :
|
||||
Observable.range(requestedCount, targetPage - requestedCount))
|
||||
.startWith(Observable.range(0, initialPageCount))
|
||||
.doOnNext(it -> requestedCount = it + 1);
|
||||
}
|
||||
}
|
||||
24
app/src/main/java/eu/kanade/tachiyomi/util/ToastUtil.java
Normal file
24
app/src/main/java/eu/kanade/tachiyomi/util/ToastUtil.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class ToastUtil {
|
||||
|
||||
public static void showShort(Context context, int resourceId) {
|
||||
Toast.makeText(context, resourceId, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public static void showLong(Context context, int resourceId) {
|
||||
Toast.makeText(context, resourceId, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public static void showShort(Context context, String message) {
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public static void showLong(Context context, String message) {
|
||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
}
|
||||
21
app/src/main/java/eu/kanade/tachiyomi/util/UrlUtil.java
Normal file
21
app/src/main/java/eu/kanade/tachiyomi/util/UrlUtil.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package eu.kanade.tachiyomi.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class UrlUtil {
|
||||
|
||||
public static String getPath(String s) {
|
||||
try {
|
||||
URI uri = new URI(s);
|
||||
String out = uri.getPath();
|
||||
if (uri.getQuery() != null)
|
||||
out += "?" + uri.getQuery();
|
||||
if (uri.getFragment() != null)
|
||||
out += "#" + uri.getFragment();
|
||||
return out;
|
||||
} catch (URISyntaxException e) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user