Merge branch 'maintenance' into origin/master
This commit is contained in:
commit
aba0d0be0e
16
.travis.yml
16
.travis.yml
|
@ -30,14 +30,14 @@ addons:
|
|||
- git
|
||||
- ruby
|
||||
|
||||
before_cache:
|
||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
- $HOME/.m2/
|
||||
# before_cache:
|
||||
# - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
# - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||
# cache:
|
||||
# directories:
|
||||
# - $HOME/.gradle/caches/
|
||||
# - $HOME/.gradle/wrapper/
|
||||
# - $HOME/.m2/
|
||||
|
||||
before_install:
|
||||
- ./travis/scripts/decode_private_configs.sh
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/twidere/localized.svg)](https://crowdin.com/project/twidere)
|
||||
[<img a src="https://c5.patreon.com/external/logo/become_a_patron_button.png" width="100" herf="https://www.patreon.com/bePatron?u=36020799"/>](https://www.patreon.com/bePatron?u=36020799)
|
||||
|
||||
Material Design ready and feature rich Twitter/Mastodon/StatusNet/Fanfou app for Android 4.4+. Enjoy Fediverse now!
|
||||
Material Design ready and feature rich Twitter/Mastodon/StatusNet/Fanfou app for Android 4.1+. Enjoy Fediverse now!
|
||||
|
||||
Twidere-Android is maintained by community and supporter including [Dimension](https://dimension.im/).
|
||||
|
||||
|
|
58
build.gradle
58
build.gradle
|
@ -8,7 +8,7 @@ buildscript {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||
classpath 'com.android.tools.build:gradle:4.0.0'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
|
@ -17,13 +17,13 @@ buildscript {
|
|||
allprojects {
|
||||
ext {
|
||||
projectGroupId = 'org.mariotaku.twidere'
|
||||
projectVersionCode = 512
|
||||
projectVersionName = '4.1.3'
|
||||
projectVersionCode = 513
|
||||
projectVersionName = '4.1.4'
|
||||
|
||||
globalCompileSdkVersion = 29
|
||||
globalBuildToolsVersion = "29.0.3"
|
||||
|
||||
globalMinSdkVersion = 19
|
||||
globalMinSdkVersion = 16
|
||||
globalTargetSdkVersion = 29
|
||||
}
|
||||
|
||||
|
@ -39,54 +39,18 @@ subprojects {
|
|||
buildscript {
|
||||
ext {
|
||||
kotlinVersion = '1.3.72'
|
||||
pluginVersions = [
|
||||
AndroidSvgDrawable: '3.0.0',
|
||||
PlayServices : '4.3.3',
|
||||
]
|
||||
libVersions = [
|
||||
sharedVersions = [
|
||||
Kotlin : "${kotlinVersion}",
|
||||
SupportTest : '1.0.0',
|
||||
MariotakuCommons : '0.9.20',
|
||||
RestFu : '0.9.60',
|
||||
ObjectCursor : '0.9.21',
|
||||
PlayServices : '17.0.0',
|
||||
MapsUtils : '0.6.2',
|
||||
DropboxCoreSdk : '3.1.3',
|
||||
GoogleDriveApi : 'v3-rev193-1.25.0',
|
||||
Exoplayer : '2.11.4',
|
||||
Toro : '2.1.0',
|
||||
|
||||
LoganSquare : '1.3.7',
|
||||
IABv3 : '1.1.0',
|
||||
Mime4J : '0.7.2',
|
||||
OkHttp : '3.8.1',
|
||||
Stetho : '1.5.0',
|
||||
OSMDroid : '5.6.5',
|
||||
LeakCanary : '2.1',
|
||||
TwitterText : '1.14.7',
|
||||
MediaViewerLibrary : '0.9.23',
|
||||
MultiValueSwitch : '0.9.8',
|
||||
PickNCrop : '0.9.27',
|
||||
AndroidGIFDrawable : '1.2.6',
|
||||
KPreferences : '0.9.7',
|
||||
Kovenant : '3.3.0',
|
||||
Jackson : '2.7.4',
|
||||
ParcelablePlease : '1.0.2',
|
||||
Chameleon : '0.9.28',
|
||||
UniqR : '0.9.4',
|
||||
SQLiteQB : '0.9.15',
|
||||
Glide : '4.11.0',
|
||||
GlideOkHttp3 : '4.11.0',
|
||||
GlideTransformations : '4.1.0',
|
||||
AndroidImageCropper : '2.4.6',
|
||||
|
||||
ExportablePreferences: '0.9.7',
|
||||
ACRA : '4.9.2',
|
||||
AbstractTask : '0.9.5',
|
||||
Dagger : '2.11',
|
||||
StethoBeanShellREPL : '0.1',
|
||||
MessageBubbleView : '3.5',
|
||||
MariotakuCommons : '0.9.20',
|
||||
ObjectCursor : '0.9.21',
|
||||
RestFu : '0.9.60',
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
org.gradle.jvmargs=-Xmx3584m
|
||||
#https://github.com/TwidereProject/Twidere-Android/issues/963
|
||||
android.enableAapt2=false
|
||||
# android.enableAapt2=false
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableJetifier=true
|
||||
android.jetifier.blacklist=android-4.1.1.4.jar
|
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -82,6 +82,7 @@ esac
|
|||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
|
@ -129,6 +130,7 @@ fi
|
|||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
|
|
|
@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%*
|
|||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
# limitations under the License.
|
||||
#
|
||||
org.gradle.jvmargs=-Xmx3584m
|
||||
org.gradle.parallel=false
|
||||
kotlin.incremental=false
|
||||
kotlin.compiler.execution.strategy=in-process
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableJetifier=true
|
||||
android.jetifier.blacklist=android-4.1.1.4.jar
|
|
@ -38,8 +38,8 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,12 +58,19 @@ android {
|
|||
versionCode projectVersionCode
|
||||
versionName projectVersionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
encoding = 'UTF-8'
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -72,23 +79,23 @@ dependencies {
|
|||
|
||||
|
||||
/** Third-party dependencies **/
|
||||
implementation "com.bluelinelabs:logansquare:${libVersions['LoganSquare']}"
|
||||
annotationProcessor "com.bluelinelabs:logansquare-compiler:${libVersions['LoganSquare']}"
|
||||
implementation "com.fasterxml.jackson.core:jackson-core:2.7.4"
|
||||
implementation "com.hannesdorfmann.parcelableplease:annotation:${libVersions['ParcelablePlease']}"
|
||||
annotationProcessor "com.hannesdorfmann.parcelableplease:processor:${libVersions['ParcelablePlease']}"
|
||||
implementation "com.bluelinelabs:logansquare:${sharedVersions['LoganSquare']}"
|
||||
annotationProcessor "com.bluelinelabs:logansquare-compiler:${sharedVersions['LoganSquare']}"
|
||||
implementation "com.fasterxml.jackson.core:jackson-core:${sharedVersions['Jackson']}"
|
||||
implementation "com.hannesdorfmann.parcelableplease:annotation:${sharedVersions['ParcelablePlease']}"
|
||||
annotationProcessor "com.hannesdorfmann.parcelableplease:processor:${sharedVersions['ParcelablePlease']}"
|
||||
|
||||
|
||||
/** Custom dependencies **/
|
||||
implementation "com.github.mariotaku.RestFu:library:${libVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth:${libVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth2:${libVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.ObjectCursor:core:${libVersions['ObjectCursor']}"
|
||||
annotationProcessor "com.github.mariotaku.ObjectCursor:processor:${libVersions['ObjectCursor']}"
|
||||
implementation "com.github.mariotaku.ExportablePreferences:core:${libVersions['ExportablePreferences']}"
|
||||
annotationProcessor "com.github.mariotaku.ExportablePreferences:processor:${libVersions['ExportablePreferences']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${libVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${libVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.ExportablePreferences:core:${sharedVersions['ExportablePreferences']}"
|
||||
annotationProcessor "com.github.mariotaku.ExportablePreferences:processor:${sharedVersions['ExportablePreferences']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${sharedVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${sharedVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.ObjectCursor:core:${sharedVersions['ObjectCursor']}"
|
||||
annotationProcessor "com.github.mariotaku.ObjectCursor:processor:${sharedVersions['ObjectCursor']}"
|
||||
implementation "com.github.mariotaku.RestFu:library:${sharedVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth:${sharedVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth2:${sharedVersions['RestFu']}"
|
||||
}
|
||||
|
||||
install {
|
||||
|
|
|
@ -206,7 +206,7 @@ public class MicroBlogException extends Exception implements TwitterResponse, Ht
|
|||
try {
|
||||
final String retryAfterStr = httpResponse.getHeader("Retry-After");
|
||||
if (retryAfterStr != null) {
|
||||
retryAfter = Integer.valueOf(retryAfterStr);
|
||||
retryAfter = Integer.parseInt(retryAfterStr);
|
||||
}
|
||||
} catch (final NumberFormatException ignore) {
|
||||
}
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
|
||||
package org.mariotaku.microblog.library.mastodon.model;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
|
||||
|
||||
/**
|
||||
* {@see https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md#attachment}
|
||||
|
@ -59,6 +62,9 @@ public class Attachment {
|
|||
@JsonField(name = "text_url")
|
||||
String textUrl;
|
||||
|
||||
@JsonField(name = "meta")
|
||||
MetaInfo meta;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -83,6 +89,51 @@ public class Attachment {
|
|||
return textUrl;
|
||||
}
|
||||
|
||||
public MetaInfo getMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
public static class MetaInfo {
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "focus")
|
||||
@Nullable
|
||||
public FocusInfo focus;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "original")
|
||||
@Nullable
|
||||
public MetaDataInfo original;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "small")
|
||||
@Nullable
|
||||
public MetaDataInfo small;
|
||||
|
||||
@JsonObject
|
||||
public static class FocusInfo {
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "x")
|
||||
public float x;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "y")
|
||||
public float y;
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
public static class MetaDataInfo {
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "width")
|
||||
public long width;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "height")
|
||||
public long height;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "aspect")
|
||||
public float aspect;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Attachment{" +
|
||||
|
|
|
@ -64,7 +64,7 @@ public class CardDataMap implements ValueMap {
|
|||
@Override
|
||||
public String[] keys() {
|
||||
final Set<String> keySet = map.keySet();
|
||||
return keySet.toArray(new String[keySet.size()]);
|
||||
return keySet.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,7 +37,6 @@ import java.util.List;
|
|||
@Keep
|
||||
public class IDs$$JsonObjectMapper extends JsonMapper<IDs> {
|
||||
|
||||
@SuppressWarnings("TryWithIdenticalCatches")
|
||||
@Override
|
||||
public IDs parse(JsonParser jsonParser) throws IOException {
|
||||
IDs instance = new IDs();
|
||||
|
|
|
@ -61,11 +61,8 @@ public final class ResponseList$$JsonObjectMapper<T> extends JsonMapper<Response
|
|||
|
||||
@Override
|
||||
public void parseField(ResponseList<T> instance, String fieldName, JsonParser jsonParser) throws IOException {
|
||||
switch (fieldName) {
|
||||
case "results": {
|
||||
instance.addAll(m84ClassJsonMapper.parseList(jsonParser));
|
||||
break;
|
||||
}
|
||||
if ("results".equals(fieldName)) {
|
||||
instance.addAll(m84ClassJsonMapper.parseList(jsonParser));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ public class UniversalSearchResult {
|
|||
index.end = jsonParser.nextIntValue(-1);
|
||||
list.add(index);
|
||||
}
|
||||
return list.toArray(new Index[list.size()]);
|
||||
return list.toArray(new Index[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -52,12 +52,9 @@ public final class InternalParseUtil {
|
|||
accessLevel = TwitterResponse.AccessLevel.READ_WRITE;
|
||||
break;
|
||||
case 25:
|
||||
// “read-write-directmessages” (Read, Write, & Direct
|
||||
// Message)
|
||||
accessLevel = TwitterResponse.AccessLevel.READ_WRITE_DIRECTMESSAGES;
|
||||
break;
|
||||
case 26:
|
||||
// “read-write-privatemessages” (Read, Write, & Direct
|
||||
// “read-write-directmessages” (Read, Write, & Direct
|
||||
// Message)
|
||||
accessLevel = TwitterResponse.AccessLevel.READ_WRITE_DIRECTMESSAGES;
|
||||
break;
|
||||
|
|
|
@ -64,8 +64,8 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
|||
String ETAG_MASTODON_APPS_PREFERENCES_NAME = "mastodon_apps";
|
||||
String ACCOUNT_PREFERENCES_NAME_PREFIX = "account_preferences_";
|
||||
|
||||
String TWITTER_CONSUMER_KEY = "wmtrtTaVOjUnH5pWQp4LDI5Qs";
|
||||
String TWITTER_CONSUMER_SECRET = "E9Q9u2yK0COJae2tLcNEdY75OPA3bxqJiGZQztraHaQUtoI2cu";
|
||||
String TWITTER_CONSUMER_KEY = "MUUBibXUognm6e9vbzrUIqPkt";
|
||||
String TWITTER_CONSUMER_SECRET = "l2uWAgQkoHvDfM2PrRFx2WN4h7QIUIktmxyeTAqRo6TkGCtNKy";
|
||||
|
||||
String YANDEX_KEY = "trnsl.1.1.20200513T065609Z.8e72845b632aa04f.fe1297e42c152de9e8773e1bc71162b1e498e2a8";
|
||||
|
||||
|
|
|
@ -56,6 +56,5 @@ public @interface FilterScope {
|
|||
|
||||
// Contains all flags
|
||||
int ALL = 0xFFFFFFFF;
|
||||
@SuppressWarnings("PointlessBitwiseExpression")
|
||||
int DEFAULT = ALL & ~(TARGET_NAME | TARGET_DESCRIPTION);
|
||||
}
|
||||
|
|
|
@ -291,6 +291,8 @@ public interface SharedPreferenceConstants {
|
|||
String KEY_AUTO_HIDE_TABS = "auto_hide_tabs";
|
||||
@ExportablePreference(BOOLEAN)
|
||||
String KEY_HIDE_CARD_NUMBERS = "hide_card_numbers";
|
||||
@ExportablePreference(BOOLEAN)
|
||||
String KEY_SHOW_LINK_PREVIEW = "show_link_preview";
|
||||
|
||||
// Internal preferences
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ import java.util.Arrays;
|
|||
@JsonObject
|
||||
@ParcelablePlease
|
||||
public class ParcelableMedia implements Parcelable {
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
@JsonField(name = "url")
|
||||
@ParcelableThisPlease
|
||||
|
|
|
@ -31,7 +31,6 @@ import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
|||
@ParcelablePlease
|
||||
public class ParcelableMediaUpdate implements Parcelable {
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
@JsonField(name = "uri")
|
||||
public String uri;
|
||||
|
|
|
@ -20,11 +20,11 @@ package org.mariotaku.twidere.model;
|
|||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import androidx.annotation.IntDef;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.LongDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
@ -52,13 +52,7 @@ import java.util.Comparator;
|
|||
@ParcelablePlease
|
||||
public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus>, Cloneable {
|
||||
|
||||
public static final Comparator<ParcelableStatus> REVERSE_COMPARATOR = new Comparator<ParcelableStatus>() {
|
||||
|
||||
@Override
|
||||
public int compare(final ParcelableStatus object1, final ParcelableStatus object2) {
|
||||
return object2.compareTo(object1);
|
||||
}
|
||||
};
|
||||
public static final Comparator<ParcelableStatus> REVERSE_COMPARATOR = (object1, object2) -> object2.compareTo(object1);
|
||||
public static final Creator<ParcelableStatus> CREATOR = new Creator<ParcelableStatus>() {
|
||||
@Override
|
||||
public ParcelableStatus createFromParcel(Parcel source) {
|
||||
|
@ -75,13 +69,11 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
@CursorField(value = Statuses._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
|
||||
public long _id;
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@JsonField(name = "id")
|
||||
@CursorField(Statuses.ID)
|
||||
@NonNull
|
||||
public String id;
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
|
||||
@CursorField(value = Statuses.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
|
||||
@NonNull
|
||||
|
@ -98,7 +90,6 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
@JsonField(name = "timestamp")
|
||||
@CursorField(Statuses.TIMESTAMP)
|
||||
public long timestamp;
|
||||
@SuppressWarnings("NullableProblems")
|
||||
|
||||
@JsonField(name = "user_id", typeConverter = UserKeyConverter.class)
|
||||
@CursorField(value = Statuses.USER_KEY, converter = UserKeyCursorFieldConverter.class)
|
||||
|
@ -527,6 +518,9 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
@JsonField(name = "external_url")
|
||||
public String external_url;
|
||||
|
||||
@JsonField(name = "entities_url")
|
||||
public String[] entities_url;
|
||||
|
||||
@JsonField(name = "quoted_external_url")
|
||||
public String quoted_external_url;
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ import java.util.Arrays;
|
|||
@JsonObject
|
||||
public class ParcelableStatusUpdate implements Parcelable {
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@JsonField(name = "accounts")
|
||||
@NonNull
|
||||
@ParcelableThisPlease
|
||||
|
|
|
@ -45,7 +45,6 @@ public class ParcelableTrend implements Parcelable {
|
|||
|
||||
@CursorField(value = CachedTrends._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
|
||||
long _id;
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
|
||||
@CursorField(value = CachedTrends.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
|
||||
|
|
|
@ -35,10 +35,8 @@ import java.io.IOException;
|
|||
public abstract class ConversationExtras implements Parcelable {
|
||||
public static ConversationExtras parse(@NonNull final String extrasType, @Nullable final String json) throws IOException {
|
||||
if (json == null) return null;
|
||||
switch (extrasType) {
|
||||
case ExtrasType.TWITTER_OFFICIAL: {
|
||||
return LoganSquare.parse(json, TwitterOfficialConversationExtras.class);
|
||||
}
|
||||
if (ExtrasType.TWITTER_OFFICIAL.equals(extrasType)) {
|
||||
return LoganSquare.parse(json, TwitterOfficialConversationExtras.class);
|
||||
}
|
||||
return LoganSquare.parse(json, DefaultConversationExtras.class);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class UserKeysConverter implements TypeConverter<UserKey[]> {
|
|||
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
|
||||
list.add(UserKey.valueOf(jsonParser.getValueAsString()));
|
||||
}
|
||||
return list.toArray(new UserKey[list.size()]);
|
||||
return list.toArray(new UserKey[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,12 @@ android {
|
|||
minSdkVersion globalMinSdkVersion
|
||||
targetSdkVersion globalTargetSdkVersion
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
encoding = 'UTF-8'
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -314,7 +314,7 @@ public class NyanDrawingHelper {
|
|||
public void dispatchOnDraw(final Canvas canvas) {
|
||||
final int w = canvas.getWidth(), h = canvas.getHeight();
|
||||
if (w <= 0 || h <= 0) return;
|
||||
for (final Star star : mStars.toArray(new Star[mStars.size()])) {
|
||||
for (final Star star : mStars.toArray(new Star[0])) {
|
||||
final int col = star.nextColumn(), row = star.nextRow();
|
||||
final float y = (row + 0.5f) * (h / mStarRows), x = (col + 0.5f) * (w / mStarCols);
|
||||
drawStar(canvas, x, y, star.nextFrame());
|
||||
|
|
|
@ -25,7 +25,7 @@ buildscript {
|
|||
|
||||
if (enableGoogleVariant) {
|
||||
// START Non-FOSS component
|
||||
classpath "com.google.gms:google-services:${pluginVersions['PlayServices']}"
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
// END Non-FOSS component
|
||||
}
|
||||
}
|
||||
|
@ -91,9 +91,6 @@ android {
|
|||
signingConfig signingConfigs.twidere
|
||||
}
|
||||
|
||||
multiDexEnabled true
|
||||
minifyEnabled false
|
||||
shrinkResources false
|
||||
resValue("bool", "debug", "true")
|
||||
}
|
||||
release {
|
||||
|
@ -101,7 +98,6 @@ android {
|
|||
signingConfig signingConfigs.twidere
|
||||
}
|
||||
|
||||
multiDexEnabled true
|
||||
minifyEnabled false
|
||||
shrinkResources false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
|
@ -115,6 +111,7 @@ android {
|
|||
}
|
||||
|
||||
compileOptions {
|
||||
encoding = 'UTF-8'
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
@ -145,7 +142,6 @@ android {
|
|||
exclude 'sdk-version.txt'
|
||||
exclude 'build-data.properties'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task buildTranslationArray {
|
||||
|
@ -153,16 +149,16 @@ task buildTranslationArray {
|
|||
foundLocales.append("new String[]{")
|
||||
|
||||
fileTree("src/main/res-localized").visit { FileVisitDetails details ->
|
||||
if(details.file.path.endsWith("strings.xml")){
|
||||
def languageCode = details.file.parentFile.name.replaceAll('values-','').replaceAll('-r','-')
|
||||
languageCode = (languageCode == "values") ? "en" : languageCode;
|
||||
if (details.file.path.endsWith("strings.xml")) {
|
||||
def languageCode = details.file.parentFile.name.replaceAll('values-', '').replaceAll('-r', '-')
|
||||
languageCode = (languageCode == "values") ? "en" : languageCode
|
||||
foundLocales.append("\"").append(languageCode).append("\"").append(",")
|
||||
}
|
||||
}
|
||||
|
||||
foundLocales.append("}")
|
||||
//Don't forget to remove the trailing comma
|
||||
def foundLocalesString = foundLocales.toString().replaceAll(',}','}')
|
||||
def foundLocalesString = foundLocales.toString().replaceAll(',}', '}')
|
||||
android.defaultConfig.buildConfigField "String[]", "TRANSLATION_ARRAY", foundLocalesString
|
||||
}
|
||||
|
||||
|
@ -175,12 +171,25 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
|||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
libVersions = [
|
||||
Kovenant : '3.3.0',
|
||||
Mime4J : '0.7.2',
|
||||
Dagger : '2.28',
|
||||
Exoplayer : '2.11.5',
|
||||
Glide : '4.11.0',
|
||||
MediaViewerLibrary: '0.9.23',
|
||||
PlayServices : '17.0.0',
|
||||
Stetho : '1.5.1',
|
||||
]
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':twidere.component.common')
|
||||
implementation project(':twidere.component.nyan')
|
||||
|
||||
/** Kotlin **/
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${libVersions['Kotlin']}"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${sharedVersions['Kotlin']}"
|
||||
implementation "nl.komponents.kovenant:kovenant:${libVersions['Kovenant']}"
|
||||
implementation "nl.komponents.kovenant:kovenant-android:${libVersions['Kovenant']}"
|
||||
implementation "nl.komponents.kovenant:kovenant-combine:${libVersions['Kovenant']}"
|
||||
|
@ -189,103 +198,104 @@ dependencies {
|
|||
|
||||
/** Android support **/
|
||||
implementation 'androidx.annotation:annotation:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0-alpha01'
|
||||
implementation 'androidx.browser:browser:1.2.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.core:core:1.2.0'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'androidx.drawerlayout:drawerlayout:1.1.0-alpha01'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.1.0'
|
||||
implementation "androidx.preference:preference:1.1.1"
|
||||
implementation 'androidx.exifinterface:exifinterface:1.2.0'
|
||||
implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.palette:palette:1.0.0'
|
||||
implementation 'androidx.palette:palette-ktx:1.0.0'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
|
||||
|
||||
/** Third-party dependencies **/
|
||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
implementation "com.twitter:twitter-text:${libVersions['TwitterText']}"
|
||||
implementation 'com.twitter:twitter-text:1.14.7'
|
||||
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0'
|
||||
implementation 'com.squareup:otto:1.3.8'
|
||||
implementation 'dnsjava:dnsjava:2.1.8'
|
||||
implementation 'com.commonsware.cwac:layouts:0.4.3'
|
||||
implementation 'dnsjava:dnsjava:2.1.9'
|
||||
implementation 'com.commonsware.cwac:layouts:0.4.5'
|
||||
implementation 'com.rengwuxian.materialedittext:library:2.1.4'
|
||||
implementation 'com.pnikosis:materialish-progress:1.7'
|
||||
implementation 'com.github.uucky:ColorPicker-Android:0.9.7@aar'
|
||||
implementation "pl.droidsonroids.gif:android-gif-drawable:${libVersions['AndroidGIFDrawable']}"
|
||||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
|
||||
implementation 'com.sprylab.android.texturevideoview:texturevideoview:1.2.1'
|
||||
implementation 'com.squareup:pollexor:2.0.4'
|
||||
implementation 'org.apache.commons:commons-text:1.8'
|
||||
implementation "org.apache.james:apache-mime4j-core:${libVersions['Mime4J']}"
|
||||
implementation "org.apache.james:apache-mime4j-storage:${libVersions['Mime4J']}"
|
||||
implementation "com.bluelinelabs:logansquare:${libVersions['LoganSquare']}"
|
||||
kapt "com.bluelinelabs:logansquare-compiler:${libVersions['LoganSquare']}"
|
||||
implementation "com.fasterxml.jackson.core:jackson-core:2.7.4"
|
||||
implementation "com.hannesdorfmann.parcelableplease:annotation:${libVersions['ParcelablePlease']}"
|
||||
kapt "com.hannesdorfmann.parcelableplease:processor:${libVersions['ParcelablePlease']}"
|
||||
implementation "com.squareup.okhttp3:okhttp:${libVersions['OkHttp']}"
|
||||
implementation "com.squareup.okio:okio:2.4.3"
|
||||
implementation "com.bluelinelabs:logansquare:${sharedVersions['LoganSquare']}"
|
||||
kapt "com.bluelinelabs:logansquare-compiler:${sharedVersions['LoganSquare']}"
|
||||
implementation "com.fasterxml.jackson.core:jackson-core:${sharedVersions['Jackson']}"
|
||||
implementation "com.hannesdorfmann.parcelableplease:annotation:${sharedVersions['ParcelablePlease']}"
|
||||
kapt "com.hannesdorfmann.parcelableplease:processor:${sharedVersions['ParcelablePlease']}"
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.12.12'
|
||||
implementation 'com.squareup.okio:okio:2.6.0'
|
||||
implementation 'com.lnikkila:extendedtouchview:0.1.1'
|
||||
implementation "com.google.dagger:dagger:${libVersions['Dagger']}"
|
||||
kapt "com.google.dagger:dagger-compiler:${libVersions['Dagger']}"
|
||||
implementation 'org.attoparser:attoparser:2.0.4.RELEASE'
|
||||
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.9.1'
|
||||
implementation 'net.ypresto.androidtranscoder:android-transcoder:0.2.0'
|
||||
implementation 'org.attoparser:attoparser:2.0.5.RELEASE'
|
||||
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.0'
|
||||
implementation 'net.ypresto.androidtranscoder:android-transcoder:0.3.0'
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
implementation "com.google.android.exoplayer:exoplayer-core:${libVersions['Exoplayer']}"
|
||||
implementation "com.google.android.exoplayer:exoplayer-ui:${libVersions['Exoplayer']}"
|
||||
implementation "com.google.android.exoplayer:extension-okhttp:${libVersions['Exoplayer']}"
|
||||
implementation "com.github.bumptech.glide:glide:${libVersions['Glide']}"
|
||||
implementation "com.github.bumptech.glide:okhttp3-integration:${libVersions['GlideOkHttp3']}@aar"
|
||||
implementation "com.github.bumptech.glide:okhttp3-integration:${libVersions['Glide']}@aar"
|
||||
kapt "com.github.bumptech.glide:compiler:${libVersions['Glide']}"
|
||||
implementation "jp.wasabeef:glide-transformations:${libVersions['GlideTransformations']}"
|
||||
implementation "com.theartofdev.edmodo:android-image-cropper:${libVersions['AndroidImageCropper']}"
|
||||
implementation 'jp.wasabeef:glide-transformations:4.1.0'
|
||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
|
||||
|
||||
|
||||
/** Custom dependencies **/
|
||||
implementation 'com.github.mariotaku:AbstractTask:0.9.5'
|
||||
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
||||
implementation "com.github.mariotaku:MessageBubbleView:${libVersions['MessageBubbleView']}"
|
||||
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
||||
implementation "com.github.mariotaku.MediaViewerLibrary:base:${libVersions['MediaViewerLibrary']}"
|
||||
implementation "com.github.mariotaku.MediaViewerLibrary:subsample-image-view:${libVersions['MediaViewerLibrary']}"
|
||||
implementation "com.github.mariotaku:SQLiteQB:${libVersions['SQLiteQB']}"
|
||||
implementation "com.github.mariotaku.ObjectCursor:core:${libVersions['ObjectCursor']}"
|
||||
kapt "com.github.mariotaku.ObjectCursor:processor:${libVersions['ObjectCursor']}"
|
||||
implementation "com.github.mariotaku.ExportablePreferences:core:${libVersions['ExportablePreferences']}"
|
||||
implementation "com.github.mariotaku:AbstractTask:${libVersions['AbstractTask']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:parcel:${libVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:io:${libVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:text:${libVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:text-kotlin:${libVersions['MariotakuCommons']}"
|
||||
implementation("com.github.mariotaku.CommonsLibrary:emojione-android:${libVersions['MariotakuCommons']}") {
|
||||
implementation "com.github.mariotaku.ExportablePreferences:core:${sharedVersions['ExportablePreferences']}"
|
||||
implementation("com.github.mariotaku.CommonsLibrary:emojione-android:${sharedVersions['MariotakuCommons']}") {
|
||||
exclude group: 'org.apache.commons', module: 'commons-text'
|
||||
}
|
||||
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${libVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${libVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku:KPreferences:${libVersions['KPreferences']}"
|
||||
implementation "com.github.mariotaku.UniqR:android:${libVersions['UniqR']}"
|
||||
implementation "com.github.mariotaku:PickNCrop:${libVersions['PickNCrop']}"
|
||||
implementation "com.github.mariotaku.RestFu:library:${libVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth:${libVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth2:${libVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:okhttp3:${libVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:logansquare:${libVersions['RestFu']}"
|
||||
implementation "com.github.Tlaster:Chameleon:${libVersions['Chameleon']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:io:${sharedVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${sharedVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${sharedVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:parcel:${sharedVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:text:${sharedVersions['MariotakuCommons']}"
|
||||
implementation "com.github.mariotaku.CommonsLibrary:text-kotlin:${sharedVersions['MariotakuCommons']}"
|
||||
implementation 'com.github.mariotaku:KPreferences:0.9.8'
|
||||
implementation "com.github.mariotaku.MediaViewerLibrary:base:${libVersions['MediaViewerLibrary']}"
|
||||
implementation "com.github.mariotaku.MediaViewerLibrary:subsample-image-view:${libVersions['MediaViewerLibrary']}"
|
||||
implementation 'com.github.mariotaku:MessageBubbleView:3.5'
|
||||
implementation "com.github.mariotaku.ObjectCursor:core:${sharedVersions['ObjectCursor']}"
|
||||
kapt "com.github.mariotaku.ObjectCursor:processor:${sharedVersions['ObjectCursor']}"
|
||||
implementation 'com.github.mariotaku:PickNCrop:0.9.27'
|
||||
implementation "com.github.mariotaku.RestFu:library:${sharedVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:logansquare:${sharedVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth:${sharedVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:oauth2:${sharedVersions['RestFu']}"
|
||||
implementation "com.github.mariotaku.RestFu:okhttp3:${sharedVersions['RestFu']}"
|
||||
implementation 'com.github.mariotaku:SQLiteQB:0.9.15'
|
||||
implementation 'com.github.mariotaku.UniqR:android:0.9.4'
|
||||
implementation 'com.github.Tlaster:Chameleon:0.9.28'
|
||||
|
||||
|
||||
/** Flavor dependencies **/
|
||||
fdroidImplementation "org.osmdroid:osmdroid-android:${libVersions['OSMDroid']}"
|
||||
fdroidImplementation "ch.acra:acra:${libVersions['ACRA']}"
|
||||
fdroidImplementation 'org.osmdroid:osmdroid-android:5.6.5'
|
||||
fdroidImplementation 'ch.acra:acra:4.11'
|
||||
|
||||
if (enableGoogleVariant) {
|
||||
// START Non-FOSS component
|
||||
googleImplementation "com.google.android.gms:play-services-ads:${libVersions['PlayServices']}"
|
||||
googleImplementation "com.google.android.gms:play-services-auth:${libVersions['PlayServices']}"
|
||||
googleImplementation "com.google.android.gms:play-services-maps:${libVersions['PlayServices']}"
|
||||
googleImplementation "com.google.maps.android:android-maps-utils:${libVersions['MapsUtils']}"
|
||||
googleImplementation "com.anjlab.android.iab.v3:library:${libVersions['IABv3']}"
|
||||
googleImplementation "com.dropbox.core:dropbox-core-sdk:${libVersions['DropboxCoreSdk']}"
|
||||
googleImplementation("com.google.apis:google-api-services-drive:${libVersions['GoogleDriveApi']}") {
|
||||
googleImplementation 'com.google.maps.android:android-maps-utils:0.6.2'
|
||||
googleImplementation 'com.anjlab.android.iab.v3:library:1.1.0'
|
||||
googleImplementation 'com.dropbox.core:dropbox-core-sdk:3.1.3'
|
||||
googleImplementation('com.google.apis:google-api-services-drive:v3-rev195-1.25.0') {
|
||||
exclude group: 'org.apache.httpcomponents'
|
||||
}
|
||||
implementation 'com.google.guava:guava:28.2-android'
|
||||
|
@ -294,9 +304,9 @@ dependencies {
|
|||
|
||||
debugImplementation "com.facebook.stetho:stetho:${libVersions['Stetho']}"
|
||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:${libVersions['Stetho']}"
|
||||
debugImplementation "com.github.mariotaku:StethoBeanShellREPL:${libVersions['StethoBeanShellREPL']}"
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:${libVersions['LeakCanary']}"
|
||||
debugImplementation('com.jayway.jsonpath:json-path:2.2.0') {
|
||||
debugImplementation 'com.github.mariotaku:StethoBeanShellREPL:0.5'
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
|
||||
debugImplementation('com.jayway.jsonpath:json-path:2.4.0') {
|
||||
exclude group: 'net.minidev', module: 'json-smart'
|
||||
}
|
||||
// Stetho dependency, see https://g.co/androidstudio/app-test-app-conflict
|
||||
|
|
|
@ -316,9 +316,9 @@ class AccountsDumperPlugin(val context: Context) : DumperPlugin {
|
|||
return JsonPath.parse(JsonSerializer.serialize(details), configuration)
|
||||
}
|
||||
|
||||
private fun Any.prettyPrint() = when {
|
||||
this is JSONObject -> toString(4)
|
||||
this is JSONArray -> toString(4)
|
||||
private fun Any.prettyPrint() = when (this) {
|
||||
is JSONObject -> toString(4)
|
||||
is JSONArray -> toString(4)
|
||||
else -> toString()
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
"auth_type": "oauth",
|
||||
"same_oauth_url": true,
|
||||
"no_version_suffix": false,
|
||||
"consumer_key": "wmtrtTaVOjUnH5pWQp4LDI5Qs",
|
||||
"consumer_secret": "E9Q9u2yK0COJae2tLcNEdY75OPA3bxqJiGZQztraHaQUtoI2cu",
|
||||
"consumer_key": "MUUBibXUognm6e9vbzrUIqPkt",
|
||||
"consumer_secret": "l2uWAgQkoHvDfM2PrRFx2WN4h7QIUIktmxyeTAqRo6TkGCtNKy",
|
||||
"sign_up_url": "https://twitter.com/signup"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.text.translate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Executes a sequence of translators one after the other. Execution ends whenever
|
||||
* the first translator consumes codepoints from the input.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public class AggregateTranslator extends CharSequenceTranslator {
|
||||
|
||||
/**
|
||||
* Translator list.
|
||||
*/
|
||||
private final List<CharSequenceTranslator> translators = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Specify the translators to be used at creation time.
|
||||
*
|
||||
* @param translators CharSequenceTranslator array to aggregate
|
||||
*/
|
||||
public AggregateTranslator(final CharSequenceTranslator... translators) {
|
||||
if (translators != null) {
|
||||
for (CharSequenceTranslator translator : translators) {
|
||||
if (translator != null) {
|
||||
this.translators.add(translator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The first translator to consume codepoints from the input is the 'winner'.
|
||||
* Execution stops with the number of consumed codepoints being returned.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
|
||||
for (final CharSequenceTranslator translator : translators) {
|
||||
final int consumed = translator.translate(input, index, out);
|
||||
if (consumed != 0) {
|
||||
return consumed;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.text.translate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* An API for translating text.
|
||||
* Its core use is to escape and unescape text. Because escaping and unescaping
|
||||
* is completely contextual, the API does not present two separate signatures.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class CharSequenceTranslator {
|
||||
|
||||
/**
|
||||
* Array containing the hexadecimal alphabet.
|
||||
*/
|
||||
static final char[] HEX_DIGITS = new char[]{'0', '1', '2', '3',
|
||||
'4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B',
|
||||
'C', 'D', 'E', 'F'};
|
||||
|
||||
/**
|
||||
* Translate a set of codepoints, represented by an int index into a CharSequence,
|
||||
* into another set of codepoints. The number of codepoints consumed must be returned,
|
||||
* and the only IOExceptions thrown must be from interacting with the Writer so that
|
||||
* the top level API may reliably ignore StringWriter IOExceptions.
|
||||
*
|
||||
* @param input CharSequence that is being translated
|
||||
* @param index int representing the current point of translation
|
||||
* @param out Writer to translate the text to
|
||||
* @return int count of codepoints consumed
|
||||
* @throws IOException if and only if the Writer produces an IOException
|
||||
*/
|
||||
public abstract int translate(CharSequence input, int index, Writer out) throws IOException;
|
||||
|
||||
/**
|
||||
* Helper for non-Writer usage.
|
||||
*
|
||||
* @param input CharSequence to be translated
|
||||
* @return String output of translation
|
||||
*/
|
||||
public final String translate(final CharSequence input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final StringWriter writer = new StringWriter(input.length() * 2);
|
||||
translate(input, writer);
|
||||
return writer.toString();
|
||||
} catch (final IOException ioe) {
|
||||
// this should never ever happen while writing to a StringWriter
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate an input onto a Writer. This is intentionally final as its algorithm is
|
||||
* tightly coupled with the abstract method of this class.
|
||||
*
|
||||
* @param input CharSequence that is being translated
|
||||
* @param out Writer to translate the text to
|
||||
* @throws IOException if and only if the Writer produces an IOException
|
||||
*/
|
||||
public final void translate(final CharSequence input, final Writer out) throws IOException {
|
||||
if (out == null) throw new IllegalArgumentException("The Writer must not be null");
|
||||
if (input == null) {
|
||||
return;
|
||||
}
|
||||
int pos = 0;
|
||||
final int len = input.length();
|
||||
while (pos < len) {
|
||||
final int consumed = translate(input, pos, out);
|
||||
if (consumed == 0) {
|
||||
// inlined implementation of Character.toChars(Character.codePointAt(input, pos))
|
||||
// avoids allocating temp char arrays and duplicate checks
|
||||
final char c1 = input.charAt(pos);
|
||||
out.write(c1);
|
||||
pos++;
|
||||
if (Character.isHighSurrogate(c1) && pos < len) {
|
||||
final char c2 = input.charAt(pos);
|
||||
if (Character.isLowSurrogate(c2)) {
|
||||
out.write(c2);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// contract with translators is that they have to understand codepoints
|
||||
// and they just took care of a surrogate pair
|
||||
for (int pt = 0; pt < consumed; pt++) {
|
||||
pos += Character.charCount(Character.codePointAt(input, pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a merger of this translator with another set of
|
||||
* translators. Useful in customizing the standard functionality.
|
||||
*
|
||||
* @param translators CharSequenceTranslator array of translators to merge with this one
|
||||
* @return CharSequenceTranslator merging this translator with the others
|
||||
*/
|
||||
public final CharSequenceTranslator with(final CharSequenceTranslator... translators) {
|
||||
final CharSequenceTranslator[] newArray = new CharSequenceTranslator[translators.length + 1];
|
||||
newArray[0] = this;
|
||||
System.arraycopy(translators, 0, newArray, 1, translators.length);
|
||||
return new AggregateTranslator(newArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns an upper case hexadecimal <code>String</code> for the given
|
||||
* character.</p>
|
||||
*
|
||||
* @param codepoint The codepoint to convert.
|
||||
* @return An upper case hexadecimal <code>String</code>
|
||||
*/
|
||||
public static String hex(final int codepoint) {
|
||||
return Integer.toHexString(codepoint).toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.text.translate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Helper subclass to CharSequenceTranslator to allow for translations that
|
||||
* will replace up to one character at a time.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class CodePointTranslator extends CharSequenceTranslator {
|
||||
|
||||
/**
|
||||
* Implementation of translate that maps onto the abstract translate(int, Writer) method.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final int translate(final CharSequence input, final int index, final Writer out) throws IOException {
|
||||
final int codepoint = Character.codePointAt(input, index);
|
||||
final boolean consumed = translate(codepoint, out);
|
||||
return consumed ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the specified codepoint into another.
|
||||
*
|
||||
* @param codepoint int character input to translate
|
||||
* @param out Writer to optionally push the translated output to
|
||||
* @return boolean as to whether translation occurred or not
|
||||
* @throws IOException if and only if the Writer produces an IOException
|
||||
*/
|
||||
public abstract boolean translate(int codepoint, Writer out) throws IOException;
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.text.translate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Translates a value using a lookup table.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public class LookupTranslator extends CharSequenceTranslator {
|
||||
|
||||
/** The mapping to be used in translation. */
|
||||
private final Map<String, String> lookupMap;
|
||||
/** The first character of each key in the lookupMap. */
|
||||
private final HashSet<Character> prefixSet;
|
||||
/** The length of the shortest key in the lookupMap. */
|
||||
private final int shortest;
|
||||
/** The length of the longest key in the lookupMap. */
|
||||
private final int longest;
|
||||
|
||||
/**
|
||||
* Define the lookup table to be used in translation
|
||||
*
|
||||
* Note that, as of Lang 3.1 (the orgin of this code), the key to the lookup
|
||||
* table is converted to a java.lang.String. This is because we need the key
|
||||
* to support hashCode and equals(Object), allowing it to be the key for a
|
||||
* HashMap. See LANG-882.
|
||||
*
|
||||
* @param lookupMap Map<CharSequence, CharSequence> table of translator
|
||||
* mappings
|
||||
*/
|
||||
public LookupTranslator(final Map<CharSequence, CharSequence> lookupMap) {
|
||||
if (lookupMap == null) {
|
||||
throw new InvalidParameterException("lookupMap cannot be null");
|
||||
}
|
||||
this.lookupMap = new HashMap<>();
|
||||
this.prefixSet = new HashSet<>();
|
||||
int currentShortest = Integer.MAX_VALUE;
|
||||
int currentLongest = 0;
|
||||
Iterator<Map.Entry<CharSequence, CharSequence>> it = lookupMap.entrySet().iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<CharSequence, CharSequence> pair = it.next();
|
||||
this.lookupMap.put(pair.getKey().toString(), pair.getValue().toString());
|
||||
this.prefixSet.add(pair.getKey().charAt(0));
|
||||
final int sz = pair.getKey().length();
|
||||
if (sz < currentShortest) {
|
||||
currentShortest = sz;
|
||||
}
|
||||
if (sz > currentLongest) {
|
||||
currentLongest = sz;
|
||||
}
|
||||
}
|
||||
this.shortest = currentShortest;
|
||||
this.longest = currentLongest;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
|
||||
// check if translation exists for the input at position index
|
||||
if (prefixSet.contains(input.charAt(index))) {
|
||||
int max = longest;
|
||||
if (index + longest > input.length()) {
|
||||
max = input.length() - index;
|
||||
}
|
||||
// implement greedy algorithm by trying maximum match first
|
||||
for (int i = max; i >= shortest; i--) {
|
||||
final CharSequence subSeq = input.subSequence(index, index + i);
|
||||
final String result = lookupMap.get(subSeq.toString());
|
||||
|
||||
if (result != null) {
|
||||
out.write(result);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.text.translate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Translate XML numeric entities of the form &#[xX]?\d+;? to
|
||||
* the specific codepoint.
|
||||
*
|
||||
* Note that the semi-colon is optional.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public class NumericEntityUnescaper extends CharSequenceTranslator {
|
||||
|
||||
/** NumericEntityUnescaper option enum. */
|
||||
public enum OPTION { semiColonRequired, semiColonOptional, errorIfNoSemiColon }
|
||||
|
||||
/** EnumSet of OPTIONS, given from the constructor. */
|
||||
private final EnumSet<OPTION> options;
|
||||
|
||||
/**
|
||||
* Create a UnicodeUnescaper.
|
||||
*
|
||||
* The constructor takes a list of options, only one type of which is currently
|
||||
* available (whether to allow, error or ignore the semi-colon on the end of a
|
||||
* numeric entity to being missing).
|
||||
*
|
||||
* For example, to support numeric entities without a ';':
|
||||
* new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.semiColonOptional)
|
||||
* and to throw an IllegalArgumentException when they're missing:
|
||||
* new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.errorIfNoSemiColon)
|
||||
*
|
||||
* Note that the default behaviour is to ignore them.
|
||||
*
|
||||
* @param options to apply to this unescaper
|
||||
*/
|
||||
public NumericEntityUnescaper(final OPTION... options) {
|
||||
if (options.length > 0) {
|
||||
this.options = EnumSet.copyOf(Arrays.asList(options));
|
||||
} else {
|
||||
this.options = EnumSet.of(OPTION.semiColonRequired);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the passed in option is currently set.
|
||||
*
|
||||
* @param option to check state of
|
||||
* @return whether the option is set
|
||||
*/
|
||||
public boolean isSet(final OPTION option) {
|
||||
return options != null && options.contains(option);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
|
||||
final int seqEnd = input.length();
|
||||
// Uses -2 to ensure there is something after the &#
|
||||
if (input.charAt(index) == '&' && index < seqEnd - 2 && input.charAt(index + 1) == '#') {
|
||||
int start = index + 2;
|
||||
boolean isHex = false;
|
||||
|
||||
final char firstChar = input.charAt(start);
|
||||
if (firstChar == 'x' || firstChar == 'X') {
|
||||
start++;
|
||||
isHex = true;
|
||||
|
||||
// Check there's more than just an x after the &#
|
||||
if (start == seqEnd) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int end = start;
|
||||
// Note that this supports character codes without a ; on the end
|
||||
while (end < seqEnd && (input.charAt(end) >= '0' && input.charAt(end) <= '9'
|
||||
|| input.charAt(end) >= 'a' && input.charAt(end) <= 'f'
|
||||
|| input.charAt(end) >= 'A' && input.charAt(end) <= 'F')) {
|
||||
end++;
|
||||
}
|
||||
|
||||
final boolean semiNext = end != seqEnd && input.charAt(end) == ';';
|
||||
|
||||
if (!semiNext) {
|
||||
if (isSet(OPTION.semiColonRequired)) {
|
||||
return 0;
|
||||
} else {
|
||||
if (isSet(OPTION.errorIfNoSemiColon)) {
|
||||
throw new IllegalArgumentException("Semi-colon required at end of numeric entity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int entityValue;
|
||||
try {
|
||||
if (isHex) {
|
||||
entityValue = Integer.parseInt(input.subSequence(start, end).toString(), 16);
|
||||
} else {
|
||||
entityValue = Integer.parseInt(input.subSequence(start, end).toString(), 10);
|
||||
}
|
||||
} catch (final NumberFormatException nfe) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (entityValue > 0xFFFF) {
|
||||
final char[] chrs = Character.toChars(entityValue);
|
||||
out.write(chrs[0]);
|
||||
out.write(chrs[1]);
|
||||
} else {
|
||||
out.write(entityValue);
|
||||
}
|
||||
|
||||
return 2 + end - start + (isHex ? 1 : 0) + (semiNext ? 1 : 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -91,6 +91,7 @@ public interface Constants extends TwidereConstants {
|
|||
String TWIDERE_PREVIEW_NAME = "Twidere Project";
|
||||
String TWIDERE_PREVIEW_SCREEN_NAME = "TwidereProject";
|
||||
String TWIDERE_PREVIEW_TEXT_HTML = "Twidere is an open source twitter client for Android, see <a href='https://github.com/mariotaku/twidere'>github.com/mariotak…</a>";
|
||||
String TWIDERE_PREVIEW_LINK_URI = "https://github.com/TwidereProject/Twidere-Android";
|
||||
String TWIDERE_PREVIEW_TEXT_UNESCAPED = "Twidere is an open source twitter client for Android, see github.com/mariotak…";
|
||||
String TWIDERE_PREVIEW_SOURCE = "Twidere for Android";
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
|
|||
* instantiating views.
|
||||
*/
|
||||
public ArrayAdapter(Context context, int resource) {
|
||||
init(context, resource, new ArrayList<T>());
|
||||
init(context, resource, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,12 +84,9 @@ public class ExtendedDividerItemDecoration extends RecyclerView.ItemDecoration {
|
|||
}
|
||||
|
||||
public void setPadding(final int left, final int top, final int right, final int bottom) {
|
||||
mPadding = new Padding() {
|
||||
@Override
|
||||
public boolean get(int position, Rect rect) {
|
||||
rect.set(left, top, right, bottom);
|
||||
return true;
|
||||
}
|
||||
mPadding = (position, rect) -> {
|
||||
rect.set(left, top, right, bottom);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -66,12 +66,9 @@ public final class DataExportImportTypeSelectorDialogFragment extends BaseDialog
|
|||
|
||||
@Override
|
||||
public final void onClick(final DialogInterface dialog, final int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
final int flags = getCheckedFlags();
|
||||
onPositiveButtonClicked(flags);
|
||||
break;
|
||||
}
|
||||
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||
final int flags = getCheckedFlags();
|
||||
onPositiveButtonClicked(flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,14 +118,11 @@ public class FileSelectorDialogFragment extends BaseDialogFragment implements Lo
|
|||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
}
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
@Override
|
||||
public void onShow(final DialogInterface dialog) {
|
||||
final AlertDialog alertDialog = (AlertDialog) dialog;
|
||||
DialogExtensionsKt.applyTheme(alertDialog);
|
||||
final ListView listView = alertDialog.getListView();
|
||||
listView.setOnItemClickListener(FileSelectorDialogFragment.this);
|
||||
}
|
||||
dialog.setOnShowListener(dialog1 -> {
|
||||
final AlertDialog alertDialog = (AlertDialog) dialog1;
|
||||
DialogExtensionsKt.applyTheme(alertDialog);
|
||||
final ListView listView = alertDialog.getListView();
|
||||
listView.setOnItemClickListener(FileSelectorDialogFragment.this);
|
||||
});
|
||||
return dialog;
|
||||
}
|
||||
|
@ -268,12 +265,9 @@ public class FileSelectorDialogFragment extends BaseDialogFragment implements Lo
|
|||
private final String[] extensions;
|
||||
private final Pattern extensions_regex;
|
||||
|
||||
private static final Comparator<File> NAME_COMPARATOR = new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(final File file1, final File file2) {
|
||||
final Locale loc = Locale.getDefault();
|
||||
return file1.getName().toLowerCase(loc).compareTo(file2.getName().toLowerCase(loc));
|
||||
}
|
||||
private static final Comparator<File> NAME_COMPARATOR = (file1, file2) -> {
|
||||
final Locale loc = Locale.getDefault();
|
||||
return file1.getName().toLowerCase(loc).compareTo(file2.getName().toLowerCase(loc));
|
||||
};
|
||||
|
||||
public FilesLoader(final Context context, final File path, final String[] extensions) {
|
||||
|
|
|
@ -24,7 +24,6 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -66,12 +65,10 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
|||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.reset: {
|
||||
final DialogFragment f = new ResetKeyboardShortcutConfirmDialogFragment();
|
||||
f.show(getFragmentManager(), "reset_keyboard_shortcut_confirm");
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.reset) {
|
||||
final DialogFragment f = new ResetKeyboardShortcutConfirmDialogFragment();
|
||||
f.show(getFragmentManager(), "reset_keyboard_shortcut_confirm");
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
@ -90,12 +87,7 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
|||
mAction = action;
|
||||
setPersistent(false);
|
||||
setTitle(KeyboardShortcutsHandler.getActionLabel(context, action));
|
||||
mPreferencesChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
updateSummary();
|
||||
}
|
||||
};
|
||||
mPreferencesChangeListener = (preferences, key) -> updateSummary();
|
||||
updateSummary();
|
||||
}
|
||||
|
||||
|
@ -103,8 +95,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
|||
protected void onClick() {
|
||||
final Context context = getContext();
|
||||
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_CONTEXT_TAG(), mContextTag);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_KEY_ACTION(), mAction);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_CONTEXT_TAG, mContextTag);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_KEY_ACTION, mAction);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
@ -132,11 +124,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
|||
implements OnClickListener {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
keyboardShortcutsHandler.reset();
|
||||
break;
|
||||
}
|
||||
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||
keyboardShortcutsHandler.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,12 +137,7 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
|||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, this);
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
@Override
|
||||
public void onShow(final DialogInterface dialog) {
|
||||
DialogExtensionsKt.applyTheme((AlertDialog) dialog);
|
||||
}
|
||||
});
|
||||
dialog.setOnShowListener(dialog1 -> DialogExtensionsKt.applyTheme((AlertDialog) dialog1));
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,24 +47,21 @@ public class ThemedListPreferenceDialogFragmentCompat extends ThemedPreferenceDi
|
|||
}
|
||||
mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
|
||||
builder.setSingleChoiceItems(entries, mClickedDialogEntryIndex,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
mClickedDialogEntryIndex = which;
|
||||
/*
|
||||
* Clicking on an item simulates the positive button
|
||||
* click, and dismisses the dialog.
|
||||
*/
|
||||
ThemedListPreferenceDialogFragmentCompat.this.onClick(dialog,
|
||||
DialogInterface.BUTTON_POSITIVE);
|
||||
dialog.dismiss();
|
||||
}
|
||||
(dialog, which) -> {
|
||||
mClickedDialogEntryIndex = which;
|
||||
/*
|
||||
* Clicking on an item simulates the positive button
|
||||
* click, and dismisses the dialog.
|
||||
*/
|
||||
ThemedListPreferenceDialogFragmentCompat.this.onClick(dialog,
|
||||
DialogInterface.BUTTON_POSITIVE);
|
||||
dialog.dismiss();
|
||||
});
|
||||
/*
|
||||
* The typical interaction for list-based dialogs is to have
|
||||
* click-on-an-item dismiss the dialog instead of the user having to
|
||||
* press 'Ok'.
|
||||
*/
|
||||
//noinspection ConstantConditions
|
||||
builder.setPositiveButton(null, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ public class ObjectCursorLoader<T> extends FixedAsyncTaskLoader<List<T>> {
|
|||
return new ObjectCursor<>(cursor, indices, mUseCache);
|
||||
}
|
||||
|
||||
@SuppressWarnings("TryWithIdenticalCatches")
|
||||
@NonNull
|
||||
private ObjectCursor.CursorIndices<T> createIndices(final Cursor cursor) {
|
||||
return ObjectCursor.indicesFrom(cursor, mObjectClass);
|
||||
|
|
|
@ -447,7 +447,7 @@ public class CronExpression {
|
|||
if (match) {
|
||||
list.add(str.substring(start, i));
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,11 +92,7 @@ public abstract class DrawableHolder {
|
|||
}
|
||||
|
||||
public static DrawableHolder parse(String str) {
|
||||
DrawableHolder icon = builtin(str);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
return null;
|
||||
return builtin(str);
|
||||
}
|
||||
|
||||
public static List<DrawableHolder> builtins() {
|
||||
|
|
|
@ -100,12 +100,7 @@ abstract class MultiSelectListPreference extends DialogPreference implements IDi
|
|||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
builder.setMultiChoiceItems(mNames, mValues, this);
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
@Override
|
||||
public void onShow(final DialogInterface dialog) {
|
||||
DialogExtensionsKt.applyTheme((AlertDialog) dialog);
|
||||
}
|
||||
});
|
||||
dialog.setOnShowListener(dialog1 -> DialogExtensionsKt.applyTheme((AlertDialog) dialog1));
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.mariotaku.twidere.preference;
|
|||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -78,19 +77,9 @@ public class SettingsImportExportPreference extends DialogPreference implements
|
|||
entries[1] = context.getString(R.string.export_settings);
|
||||
values[0] = new Intent(context, DataImportActivity.class);
|
||||
values[1] = new Intent(context, DataExportActivity.class);
|
||||
builder.setItems(entries, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
startActivity(values[which]);
|
||||
}
|
||||
});
|
||||
builder.setItems(entries, (dialog, which) -> startActivity(values[which]));
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
@Override
|
||||
public void onShow(final DialogInterface dialog) {
|
||||
DialogExtensionsKt.applyTheme((AlertDialog) dialog);
|
||||
}
|
||||
});
|
||||
dialog.setOnShowListener(dialog1 -> DialogExtensionsKt.applyTheme((AlertDialog) dialog1));
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@ package org.mariotaku.twidere.preference;
|
|||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
|
@ -17,7 +15,6 @@ import android.util.AttributeSet;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
|
@ -160,42 +157,33 @@ public class ThemeBackgroundPreference extends DialogPreference implements Const
|
|||
final SharedPreferences preferences = preference.getSharedPreferences();
|
||||
preference.setValue(preference.getPersistedString(null));
|
||||
builder.setTitle(preference.getDialogTitle());
|
||||
builder.setSingleChoiceItems(preference.mBackgroundEntries, preference.getValueIndex(), new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
preference.setSelectedOption(which);
|
||||
updateAlphaVisibility();
|
||||
}
|
||||
builder.setSingleChoiceItems(preference.mBackgroundEntries, preference.getValueIndex(), (dialog, which) -> {
|
||||
preference.setSelectedOption(which);
|
||||
updateAlphaVisibility();
|
||||
});
|
||||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, this);
|
||||
final Dialog dialog = builder.create();
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
@Override
|
||||
public void onShow(DialogInterface dialog) {
|
||||
final AlertDialog alertDialog = (AlertDialog) dialog;
|
||||
DialogExtensionsKt.applyTheme(alertDialog);
|
||||
if (preferences != null) {
|
||||
final LayoutInflater inflater = alertDialog.getLayoutInflater();
|
||||
final ListView listView = alertDialog.getListView();
|
||||
assert listView != null;
|
||||
final ViewGroup listViewParent = (ViewGroup) listView.getParent();
|
||||
listViewParent.removeView(listView);
|
||||
final View view = inflater.inflate(R.layout.dialog_theme_background_preference, listViewParent);
|
||||
((ViewGroup) view.findViewById(R.id.list_container)).addView(listView);
|
||||
mAlphaContainer = view.findViewById(R.id.alpha_container);
|
||||
mAlphaSlider = view.findViewById(R.id.alpha_slider);
|
||||
mAlphaSlider.setMax(MAX_ALPHA - MIN_ALPHA);
|
||||
mAlphaSlider.setProgress(preferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA) - MIN_ALPHA);
|
||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
preference.setSelectedOption(position);
|
||||
updateAlphaVisibility();
|
||||
}
|
||||
});
|
||||
dialog.setOnShowListener(dialog1 -> {
|
||||
final AlertDialog alertDialog = (AlertDialog) dialog1;
|
||||
DialogExtensionsKt.applyTheme(alertDialog);
|
||||
if (preferences != null) {
|
||||
final LayoutInflater inflater = alertDialog.getLayoutInflater();
|
||||
final ListView listView = alertDialog.getListView();
|
||||
assert listView != null;
|
||||
final ViewGroup listViewParent = (ViewGroup) listView.getParent();
|
||||
listViewParent.removeView(listView);
|
||||
final View view = inflater.inflate(R.layout.dialog_theme_background_preference, listViewParent);
|
||||
((ViewGroup) view.findViewById(R.id.list_container)).addView(listView);
|
||||
mAlphaContainer = view.findViewById(R.id.alpha_container);
|
||||
mAlphaSlider = view.findViewById(R.id.alpha_slider);
|
||||
mAlphaSlider.setMax(MAX_ALPHA - MIN_ALPHA);
|
||||
mAlphaSlider.setProgress(preferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA) - MIN_ALPHA);
|
||||
listView.setOnItemClickListener((parent, view1, position, id) -> {
|
||||
preference.setSelectedOption(position);
|
||||
updateAlphaVisibility();
|
||||
}
|
||||
});
|
||||
updateAlphaVisibility();
|
||||
}
|
||||
});
|
||||
return dialog;
|
||||
|
|
|
@ -31,7 +31,6 @@ import androidx.annotation.Nullable;
|
|||
import org.mariotaku.twidere.constant.IntentConstants;
|
||||
import org.mariotaku.twidere.util.ServiceUtils.ServiceToken;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
|
@ -73,12 +72,7 @@ public abstract class AbsServiceInterface<I extends IInterface> implements IInte
|
|||
final Intent intent = new Intent(IntentConstants.INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
||||
final ComponentName component = ComponentName.unflattenFromString(mShortenerName);
|
||||
intent.setComponent(component);
|
||||
final FutureTask<Boolean> futureTask = new FutureTask<>(new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
return mIInterface != null;
|
||||
}
|
||||
});
|
||||
final FutureTask<Boolean> futureTask = new FutureTask<>(() -> mIInterface != null);
|
||||
mToken = ServiceUtils.bindToService(mContext, intent, new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder obj) {
|
||||
|
@ -112,7 +106,6 @@ public abstract class AbsServiceInterface<I extends IInterface> implements IInte
|
|||
}
|
||||
|
||||
public interface CheckServiceAction {
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
void check(@Nullable Bundle metaData) throws CheckServiceException;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
@ -169,7 +170,7 @@ public class DataImportExportUtils implements Constants {
|
|||
ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
|
||||
int flags = 0;
|
||||
List<String> entryNames = new ArrayList<>();
|
||||
ZipEntry entry = null;
|
||||
ZipEntry entry;
|
||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||
entryNames.add(entry.getName());
|
||||
}
|
||||
|
@ -203,11 +204,11 @@ public class DataImportExportUtils implements Constants {
|
|||
try (InputStream inputStream = context.getContentResolver().openInputStream(src.getUri());
|
||||
ZipInputStream zipInputStream = new ZipInputStream(inputStream)
|
||||
) {
|
||||
ZipEntry entry = null;
|
||||
ZipEntry entry;
|
||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
byte[] buffer = new byte[1024];
|
||||
int read = 0;
|
||||
int read;
|
||||
while ((read = zipInputStream.read(buffer, 0, 1024)) >= 0) {
|
||||
stringBuilder.append(new String(buffer, 0, read));
|
||||
}
|
||||
|
@ -292,7 +293,15 @@ public class DataImportExportUtils implements Constants {
|
|||
@NonNull final String preferencesName, @NonNull final String entryName,
|
||||
@NonNull final SharedPreferencesProcessStrategy strategy,
|
||||
@NonNull final String data) throws IOException {
|
||||
if (!Objects.equals(entry.getName(), entryName)) return;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (!Objects.equals(entry.getName(), entryName)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (entry.getName().equals(entryName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final JsonParser jsonParser = LoganSquare.JSON_FACTORY.createParser(data);
|
||||
if (jsonParser.getCurrentToken() == null) {
|
||||
jsonParser.nextToken();
|
||||
|
@ -327,7 +336,15 @@ public class DataImportExportUtils implements Constants {
|
|||
@NonNull final String data,
|
||||
@NonNull final ContentResolverProcessStrategy<List<T>> strategy)
|
||||
throws IOException {
|
||||
if (!Objects.equals(entry.getName(), entryName)) return;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (!Objects.equals(entry.getName(), entryName)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (entry.getName().equals(entryName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
List<T> itemsList = JsonSerializer.parseList(data, itemCls);
|
||||
strategy.importItem(context.getContentResolver(), itemsList);
|
||||
}
|
||||
|
@ -352,7 +369,15 @@ public class DataImportExportUtils implements Constants {
|
|||
@NonNull final String data,
|
||||
@NonNull final ContentResolverProcessStrategy<T> strategy)
|
||||
throws IOException {
|
||||
if (!Objects.equals(entry.getName(), entryName)) return;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (!Objects.equals(entry.getName(), entryName)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (entry.getName().equals(entryName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
T item = JsonSerializer.parse(data, itemCls);
|
||||
strategy.importItem(context.getContentResolver(), item);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ public class MouseScrollDirectionDecider {
|
|||
}
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
private class InternalHorizontalScrollView extends HorizontalScrollView {
|
||||
private static class InternalHorizontalScrollView extends HorizontalScrollView {
|
||||
|
||||
private final int factor;
|
||||
private final MouseScrollDirectionDecider decider;
|
||||
|
|
|
@ -133,7 +133,7 @@ public class MultiSelectManager {
|
|||
userKeys.add(((ParcelableStatus) item).user_key);
|
||||
}
|
||||
}
|
||||
return userKeys.toArray(new UserKey[userKeys.size()]);
|
||||
return userKeys.toArray(new UserKey[0]);
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
|
|
|
@ -113,7 +113,7 @@ public class NotificationManagerWrapper {
|
|||
|
||||
}
|
||||
|
||||
private class PostedNotification {
|
||||
private static class PostedNotification {
|
||||
private final String tag;
|
||||
private final int id;
|
||||
|
||||
|
|
|
@ -112,13 +112,11 @@ public class RecyclerViewNavigationHelper implements KeyboardShortcutCallback {
|
|||
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
|
||||
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
|
||||
if (action == null) return false;
|
||||
switch (action) {
|
||||
case ACTION_NAVIGATION_TOP: {
|
||||
if (iface != null) {
|
||||
iface.scrollToStart();
|
||||
}
|
||||
return true;
|
||||
if (ACTION_NAVIGATION_TOP.equals(action)) {
|
||||
if (iface != null) {
|
||||
iface.scrollToStart();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -325,7 +325,7 @@ public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
|
|||
return false;
|
||||
}
|
||||
|
||||
class PendingDismissData implements Comparable<PendingDismissData> {
|
||||
static class PendingDismissData implements Comparable<PendingDismissData> {
|
||||
public int position;
|
||||
public View view;
|
||||
|
||||
|
@ -391,12 +391,9 @@ public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
|
|||
}
|
||||
});
|
||||
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||
dismissView.setLayoutParams(lp);
|
||||
}
|
||||
animator.addUpdateListener(valueAnimator -> {
|
||||
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||
dismissView.setLayoutParams(lp);
|
||||
});
|
||||
|
||||
mPendingDismisses.add(new PendingDismissData(dismissPosition, dismissView));
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.mariotaku.twidere.util.collection;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
|
@ -253,8 +254,7 @@ public class CompactHashSet<E> extends java.util.AbstractSet<E> {
|
|||
@Override
|
||||
public void clear() {
|
||||
elements = 0;
|
||||
for (int ix = 0; ix < objects.length; ix++)
|
||||
objects[ix] = null;
|
||||
Arrays.fill(objects, null);
|
||||
freecells = objects.length;
|
||||
modCount++;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public class ContentResolverUtils {
|
|||
|
||||
public static int bulkInsert(@NonNull final ContentResolver resolver, @NonNull final Uri uri,
|
||||
@NonNull final Collection<ContentValues> values) {
|
||||
return bulkInsert(resolver, uri, values.toArray(new ContentValues[values.size()]));
|
||||
return bulkInsert(resolver, uri, values.toArray(new ContentValues[0]));
|
||||
}
|
||||
|
||||
public static int bulkInsert(@NonNull final ContentResolver resolver, @NonNull final Uri uri,
|
||||
|
|
|
@ -107,7 +107,7 @@ public final class DatabaseUpgradeHelper {
|
|||
newInsertColsList.add(newCol);
|
||||
}
|
||||
}
|
||||
final String[] newInsertCols = newInsertColsList.toArray(new String[newInsertColsList.size()]);
|
||||
final String[] newInsertCols = newInsertColsList.toArray(new String[0]);
|
||||
if (!TwidereArrayUtils.contains(newInsertCols, notNullCols)) return null;
|
||||
qb.columns(newInsertCols);
|
||||
final Columns.Column[] oldDataCols = new Columns.Column[newInsertCols.length];
|
||||
|
|
|
@ -15,12 +15,7 @@ public class ImgurProvider implements Provider {
|
|||
public boolean supports(@NonNull String link) {
|
||||
final String authority = UriUtils.getAuthority(link);
|
||||
if (authority == null) return false;
|
||||
switch (authority) {
|
||||
case "i.imgur.com":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return "i.imgur.com".equals(authority);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -28,13 +23,11 @@ public class ImgurProvider implements Provider {
|
|||
public ParcelableMedia from(@NonNull String url) {
|
||||
final String authority = UriUtils.getAuthority(url);
|
||||
if (authority == null) return null;
|
||||
switch (authority) {
|
||||
case "i.imgur.com": {
|
||||
final String path = UriUtils.getPath(url);
|
||||
if (path == null) return null;
|
||||
ParcelableMedia media = new ParcelableMedia();
|
||||
media.url = url;
|
||||
}
|
||||
if ("i.imgur.com".equals(authority)) {
|
||||
final String path = UriUtils.getPath(url);
|
||||
if (path == null) return null;
|
||||
ParcelableMedia media = new ParcelableMedia();
|
||||
media.url = url;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -47,13 +47,8 @@ public final class ViewSupport {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void setBackground(final View view, final Drawable background) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
|
||||
view.setBackgroundDrawable(background);
|
||||
} else {
|
||||
ViewAccessorJB.setBackground(view, background);
|
||||
}
|
||||
ViewAccessorJB.setBackground(view, background);
|
||||
}
|
||||
|
||||
public static void setButtonTintList(CompoundButton view, ColorStateList list) {
|
||||
|
@ -97,8 +92,8 @@ public final class ViewSupport {
|
|||
if (cls.isAssignableFrom(view.getClass())) return (T) view;
|
||||
if (view instanceof ViewGroup) {
|
||||
for (int i = 0, j = ((ViewGroup) view).getChildCount(); i < j; i++) {
|
||||
final View found = findViewByType(((ViewGroup) view).getChildAt(i), cls);
|
||||
if (found != null) return (T) found;
|
||||
final T found = findViewByType(((ViewGroup) view).getChildAt(i), cls);
|
||||
if (found != null) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -130,7 +125,6 @@ public final class ViewSupport {
|
|||
}
|
||||
|
||||
static void setBackground(final View view, final Drawable background) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
|
||||
view.setBackground(background);
|
||||
}
|
||||
}
|
||||
|
@ -142,10 +136,8 @@ public final class ViewSupport {
|
|||
|
||||
static void setForeground(final View view, final Drawable foreground) {
|
||||
if (view instanceof FrameLayout) {
|
||||
//noinspection RedundantCast
|
||||
((FrameLayout) view).setForeground(foreground);
|
||||
} else if (view instanceof IForegroundView) {
|
||||
//noinspection RedundantCast
|
||||
((IForegroundView) view).setForeground(foreground);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,12 @@ public class WebSettingsSupport {
|
|||
}
|
||||
|
||||
public static void setAllowUniversalAccessFromFileURLs(final WebSettings settings, final boolean flag) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
|
||||
WebSettingsAccessorSDK16.setAllowUniversalAccessFromFileURLs(settings, flag);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
private static class WebSettingsAccessorSDK16 {
|
||||
private static void setAllowUniversalAccessFromFileURLs(final WebSettings settings, final boolean flag) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
|
||||
settings.setAllowUniversalAccessFromFileURLs(flag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,6 @@ public final class BirthdayView extends LayeredCanvasView {
|
|||
((AnimatedBitmapLayer) layers[2]).setScale(Math.max(1, w / 160));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
||||
final int stripTop = Utils.INSTANCE.getInsetsTopWithoutActionBarHeight(getContext(), insets.top);
|
||||
|
|
|
@ -409,13 +409,11 @@ public class HeaderDrawerLayout extends ViewGroup {
|
|||
if (dy > 0 && mDrawer.canScrollCallback(-dy) && mDrawer.isTouchingScrollableContent()) {
|
||||
if (!mDrawer.isUsingDragHelper()) {
|
||||
// Scrolling up while list still has space to scroll, so make header still
|
||||
mScrollingHeaderByHelper = false;
|
||||
return current;
|
||||
} else {
|
||||
mDrawer.scrollByCallback(-dy);
|
||||
mScrollingHeaderByHelper = false;
|
||||
return current;
|
||||
}
|
||||
mScrollingHeaderByHelper = false;
|
||||
return current;
|
||||
}
|
||||
final int min = mDrawer.getHeaderTopMinimum(), max = mDrawer.getHeaderTopMaximum();
|
||||
if (top < min && mDrawer.isTouchingScrollableContent() && mDrawer.isUsingDragHelper()) {
|
||||
|
|
|
@ -196,17 +196,14 @@ public class ShapedImageView extends AppCompatImageView {
|
|||
contentHeight = contentBottom - contentTop;
|
||||
final int size = Math.min(contentWidth, contentHeight);
|
||||
|
||||
if (OUTLINE_DRAW) {
|
||||
drawShape(canvas, mDestination, 0, mBackgroundPaint);
|
||||
super.onDraw(canvas);
|
||||
} else {
|
||||
if (!OUTLINE_DRAW) {
|
||||
if (mShadowBitmap != null && mDrawShadow) {
|
||||
canvas.drawBitmap(mShadowBitmap, contentLeft + (contentWidth - size) / 2 - mShadowRadius,
|
||||
contentTop + (contentHeight - size) / 2 - mShadowRadius, null);
|
||||
}
|
||||
drawShape(canvas, mDestination, 0, mBackgroundPaint);
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
drawShape(canvas, mDestination, 0, mBackgroundPaint);
|
||||
super.onDraw(canvas);
|
||||
// Then draw the border.
|
||||
if (mBorderEnabled) {
|
||||
drawBorder(canvas, mDestination);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Uses https://github.com/george-steel/android-utils/commit/289aff11e53593a55d780f9f5986e49343a79e55
|
||||
|
||||
package org.oshkimaadziig.george.androidutils;
|
||||
|
||||
import android.text.Spannable;
|
||||
|
@ -33,7 +35,6 @@ import java.util.regex.Pattern;
|
|||
*
|
||||
* @author George T. Steel
|
||||
*/
|
||||
@SuppressWarnings("IfCanBeSwitch")
|
||||
public class SpanFormatter {
|
||||
public static final Pattern FORMAT_SEQUENCE = Pattern.compile("%([0-9]+\\$|<?)([^a-zA-z%]*)([[a-zA-Z%]&&[^tT]]|[tT][a-zA-Z])");
|
||||
|
||||
|
@ -88,10 +89,10 @@ public class SpanFormatter {
|
|||
|
||||
if (typeTerm.equals("%")) {
|
||||
cookedArg = "%";
|
||||
} else if (typeTerm.equals("%")) {
|
||||
} else if (typeTerm.equals("n")) {
|
||||
cookedArg = "\n";
|
||||
} else {
|
||||
int argIdx = 0;
|
||||
int argIdx;
|
||||
if (argTerm.equals("")) argIdx = ++argAt;
|
||||
else if (argTerm.equals("<")) argIdx = argAt;
|
||||
else argIdx = Integer.parseInt(argTerm.substring(0, argTerm.length() - 1)) - 1;
|
||||
|
|
|
@ -25,26 +25,38 @@ import java.util.*
|
|||
@SuppressLint("RestrictedApi")
|
||||
object LocaleHelperAccessor {
|
||||
fun forLanguageTag(str: String): Locale {
|
||||
if (str.contains("-")) {
|
||||
val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (args.size > 2) {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
} else if (args.size > 1) {
|
||||
return Locale(args[0], args[1])
|
||||
} else if (args.size == 1) {
|
||||
return Locale(args[0])
|
||||
when {
|
||||
str.contains("-") -> {
|
||||
val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
when {
|
||||
args.size > 2 -> {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
}
|
||||
args.size > 1 -> {
|
||||
return Locale(args[0], args[1])
|
||||
}
|
||||
args.size == 1 -> {
|
||||
return Locale(args[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (str.contains("_")) {
|
||||
val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (args.size > 2) {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
} else if (args.size > 1) {
|
||||
return Locale(args[0], args[1])
|
||||
} else if (args.size == 1) {
|
||||
return Locale(args[0])
|
||||
str.contains("_") -> {
|
||||
val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
when {
|
||||
args.size > 2 -> {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
}
|
||||
args.size > 1 -> {
|
||||
return Locale(args[0], args[1])
|
||||
}
|
||||
args.size == 1 -> {
|
||||
return Locale(args[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
return Locale(str)
|
||||
}
|
||||
} else {
|
||||
return Locale(str)
|
||||
}
|
||||
|
||||
throw IllegalArgumentException("Can not parse language tag: [$str]")
|
||||
|
|
|
@ -19,8 +19,12 @@
|
|||
|
||||
package androidx.core.view
|
||||
|
||||
fun createWindowInsetsCompat(obj: Any) = WindowInsetsCompat(obj)
|
||||
import android.annotation.TargetApi
|
||||
import android.os.Build
|
||||
import android.view.WindowInsets
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
|
||||
fun createWindowInsetsCompat(obj: Any) = WindowInsetsCompat.toWindowInsetsCompat(obj as WindowInsets)
|
||||
|
||||
val WindowInsetsCompat.unwrapped: Any?
|
||||
@Suppress("RestrictedApi")
|
||||
get() = this.toWindowInsets()
|
|
@ -1,8 +1,5 @@
|
|||
package androidx.loader.app
|
||||
|
||||
import androidx.loader.app.LoaderManager
|
||||
import androidx.loader.app.LoaderManagerImpl
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2016/11/26.
|
||||
*/
|
||||
|
|
|
@ -2,7 +2,6 @@ package androidx.loader.content
|
|||
|
||||
import android.content.Context
|
||||
import android.os.AsyncTask
|
||||
import androidx.loader.content.AsyncTaskLoader
|
||||
import org.mariotaku.twidere.extension.set
|
||||
import org.mariotaku.twidere.util.Analyzer
|
||||
|
||||
|
|
|
@ -19,6 +19,4 @@
|
|||
|
||||
package androidx.recyclerview.widget
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
val RecyclerView.LayoutManager.recyclerView: RecyclerView? get() = mRecyclerView
|
||||
|
|
|
@ -10,23 +10,23 @@ import android.os.Handler
|
|||
|
||||
fun AccountManager.addOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener,
|
||||
handler: Handler? = null, updateImmediately: Boolean = false): Boolean {
|
||||
try {
|
||||
return try {
|
||||
this.addOnAccountsUpdatedListener(listener, handler, updateImmediately)
|
||||
return true
|
||||
true
|
||||
} catch (e: IllegalStateException) {
|
||||
return false
|
||||
false
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun AccountManager.removeOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener): Boolean {
|
||||
try {
|
||||
return try {
|
||||
this.removeOnAccountsUpdatedListener(listener)
|
||||
return true
|
||||
true
|
||||
} catch (e: IllegalStateException) {
|
||||
return false
|
||||
false
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ fun Collection<*>?.isNullOrEmpty(): Boolean {
|
|||
}
|
||||
|
||||
fun <T> MutableCollection<T>.addAllEnhanced(collection: Collection<T>, ignoreDuplicates: Boolean): Boolean {
|
||||
if (ignoreDuplicates) {
|
||||
return addAll(collection.filter { it !in this })
|
||||
return if (ignoreDuplicates) {
|
||||
addAll(collection.filter { it !in this })
|
||||
} else {
|
||||
return addAll(collection)
|
||||
addAll(collection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ fun <E> Collection<E>.contentEquals(other: Collection<E>): Boolean {
|
|||
|
||||
inline fun <reified T> List<T>.subArray(range: IntRange): Array<T> {
|
||||
return Array(range.count()) {
|
||||
this[range.start + it]
|
||||
this[range.first + it]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ fun Context.checkAnySelfPermissionsGranted(vararg permissions: String): Boolean
|
|||
|
||||
fun Context.unregisterReceiverSafe(receiver: BroadcastReceiver?): Boolean {
|
||||
if (receiver == null) return false
|
||||
try {
|
||||
return try {
|
||||
unregisterReceiver(receiver)
|
||||
return true
|
||||
true
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ fun Cursor.safeGetInt(columnIndex: Int, def: Int = -1) = try {
|
|||
def
|
||||
}
|
||||
|
||||
fun Cursor.safeGetString(columnIndex: Int, def: String = "") = try {
|
||||
fun Cursor.safeGetString(columnIndex: Int, def: String = ""): String = try {
|
||||
getString(columnIndex)
|
||||
} catch (e: IllegalStateException) {
|
||||
def
|
||||
|
|
|
@ -58,10 +58,10 @@ val Locale.bcp47Tag: String
|
|||
}
|
||||
|
||||
val bcp47Tag = StringBuilder(language)
|
||||
if (!country.isEmpty()) {
|
||||
if (country.isNotEmpty()) {
|
||||
bcp47Tag.append(SEP).append(country)
|
||||
}
|
||||
if (!variant.isEmpty()) {
|
||||
if (variant.isNotEmpty()) {
|
||||
bcp47Tag.append(SEP).append(variant)
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ fun Number.toLocalizedString(locale: Locale = Locale.getDefault()): String {
|
|||
val Int.nextPowerOf2: Int
|
||||
get() {
|
||||
var n = this
|
||||
if (n <= 0 || n > 1 shl 30) throw IllegalArgumentException("n is invalid: " + n)
|
||||
if (n <= 0 || n > 1 shl 30) throw IllegalArgumentException("n is invalid: $n")
|
||||
n -= 1
|
||||
n = n or (n shr 16)
|
||||
n = n or (n shr 8)
|
||||
|
|
|
@ -6,5 +6,5 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
* Created by mariotaku on 16/8/21.
|
||||
*/
|
||||
fun RecyclerView.Adapter<*>.findPositionByItemId(itemId: Long): Int {
|
||||
return (0 until itemCount).firstOrNull { getItemId(it) == itemId } ?: androidx.recyclerview.widget.RecyclerView.NO_POSITION
|
||||
return (0 until itemCount).firstOrNull { getItemId(it) == itemId } ?: RecyclerView.NO_POSITION
|
||||
}
|
||||
|
|
|
@ -40,5 +40,5 @@ fun InputStream.expectLine(string: String = "", charset: Charset = Charset.defau
|
|||
fun InputStream.expectBytes(bytes: ByteArray): Boolean {
|
||||
val readBytes = ByteArray(bytes.size)
|
||||
read(readBytes)
|
||||
return Arrays.equals(readBytes, bytes)
|
||||
return readBytes.contentEquals(bytes)
|
||||
}
|
|
@ -35,20 +35,24 @@ object InternalActivityCreator {
|
|||
activity.maxSortPosition = activity.minSortPosition
|
||||
activity.createdAt = status.getCreatedAt()
|
||||
|
||||
if (status.getInReplyToUserId() == accountId) {
|
||||
activity.action = Activity.Action.REPLY
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
when {
|
||||
status.getInReplyToUserId() == accountId -> {
|
||||
activity.action = Activity.Action.REPLY
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
|
||||
//TODO set target statuses (in reply to status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
} else if (status.quotedStatus?.user?.id == accountId) {
|
||||
activity.action = Activity.Action.QUOTE
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
} else {
|
||||
activity.action = Activity.Action.MENTION
|
||||
activity.targetUsers = arrayOfNulls<User>(0)
|
||||
activity.targetObjectStatuses = arrayOf(status)
|
||||
//TODO set target statuses (in reply to status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
}
|
||||
status.quotedStatus?.user?.id == accountId -> {
|
||||
activity.action = Activity.Action.QUOTE
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
}
|
||||
else -> {
|
||||
activity.action = Activity.Action.MENTION
|
||||
activity.targetUsers = arrayOfNulls<User>(0)
|
||||
activity.targetObjectStatuses = arrayOf(status)
|
||||
}
|
||||
}
|
||||
activity.sourcesSize = 1
|
||||
activity.sources = arrayOf(status.getUser())
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.mariotaku.twidere.R
|
|||
import org.mariotaku.twidere.TwidereConstants.*
|
||||
import org.mariotaku.twidere.adapter.AccountDetailsAdapter
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.app.TwidereApplication
|
||||
import org.mariotaku.twidere.extension.model.isOAuth
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
|
|
|
@ -13,8 +13,7 @@ class AssistLauncherActivity : Activity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val prefs = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
|
||||
val composeNowAction = prefs.getString(KEY_COMPOSE_NOW_ACTION, VALUE_COMPOSE_NOW_ACTION_COMPOSE)
|
||||
val action = when (composeNowAction) {
|
||||
val action = when (prefs.getString(KEY_COMPOSE_NOW_ACTION, VALUE_COMPOSE_NOW_ACTION_COMPOSE)) {
|
||||
VALUE_COMPOSE_NOW_ACTION_TAKE_PHOTO -> INTENT_ACTION_COMPOSE_TAKE_PHOTO
|
||||
VALUE_COMPOSE_NOW_ACTION_PICK_IMAGE -> INTENT_ACTION_COMPOSE_PICK_IMAGE
|
||||
else -> INTENT_ACTION_COMPOSE
|
||||
|
|
|
@ -27,22 +27,22 @@ import android.graphics.Rect
|
|||
import android.nfc.NfcAdapter
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.view.OnApplyWindowInsetsListener
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.appcompat.app.TwilightManagerAccessor
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback
|
||||
import androidx.appcompat.view.menu.ActionMenuItemView
|
||||
import androidx.appcompat.widget.TwidereActionMenuView
|
||||
import android.util.AttributeSet
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.appcompat.app.TwilightManagerAccessor
|
||||
import androidx.appcompat.view.menu.ActionMenuItemView
|
||||
import androidx.appcompat.widget.TwidereActionMenuView
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.view.OnApplyWindowInsetsListener
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.RequestManager
|
||||
import com.squareup.otto.Bus
|
||||
|
@ -300,7 +300,7 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
|
|||
for (i in 0 until handlerFilter.countDataAuthorities()) {
|
||||
val authorityEntry = handlerFilter.getDataAuthority(i)
|
||||
val port = authorityEntry.port
|
||||
intentFilter.addDataAuthority(authorityEntry.host, if (port < 0) null else Integer.toString(port))
|
||||
intentFilter.addDataAuthority(authorityEntry.host, if (port < 0) null else port.toString())
|
||||
}
|
||||
try {
|
||||
adapter.enableForegroundDispatch(this, intent, arrayOf(intentFilter), null)
|
||||
|
@ -363,7 +363,11 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
|
|||
super.attachBaseContext(newBase)
|
||||
return
|
||||
}
|
||||
super.attachBaseContext(newBase.overriding(locale))
|
||||
val newContext = newBase.overriding(locale)
|
||||
super.attachBaseContext(newContext)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
applyOverrideConfiguration(newContext.resources.configuration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun executeAfterFragmentResumed(useHandler: Boolean, action: (BaseActivity) -> Unit): Promise<Unit, Exception> {
|
||||
|
@ -465,20 +469,20 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
|
|||
}
|
||||
|
||||
private fun newInstance(name: String, context: Context, attrs: AttributeSet): View? {
|
||||
try {
|
||||
return try {
|
||||
val cls = findClass(name) ?: throw ClassNotFoundException(name)
|
||||
val constructor = cls.getConstructor(Context::class.java, AttributeSet::class.java)
|
||||
return constructor.newInstance(context, attrs) as View
|
||||
constructor.newInstance(context, attrs) as View
|
||||
} catch (e: InstantiationException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: IllegalAccessException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: InvocationTargetException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: NoSuchMethodException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: ClassNotFoundException) {
|
||||
return null
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ class ColorPickerDialogActivity : BaseActivity(), Callback {
|
|||
|
||||
companion object {
|
||||
|
||||
val RESULT_CLEARED = -2
|
||||
const val RESULT_CLEARED = -2
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ import java.text.Normalizer
|
|||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.math.abs
|
||||
import android.Manifest.permission as AndroidPermission
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
|
@ -389,11 +390,15 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (requestCode) {
|
||||
REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val src = MediaPickerActivity.getMediaUris(data)
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, false, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = false,
|
||||
deleteSrc = false
|
||||
))
|
||||
val extras = data.getBundleExtra(MediaPickerActivity.EXTRA_EXTRAS)
|
||||
if (extras?.getBoolean(EXTRA_IS_POSSIBLY_SENSITIVE) == true) {
|
||||
possiblySensitive = true
|
||||
|
@ -430,7 +435,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val src = MediaPickerActivity.getMediaUris(data)?.takeIf(Array<Uri>::isNotEmpty) ?:
|
||||
data.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)?.let { arrayOf(it) }
|
||||
if (src != null) {
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, false, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = false,
|
||||
deleteSrc = false
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -508,7 +516,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
replyLabel -> {
|
||||
if (replyLabel.visibility != View.VISIBLE) return
|
||||
replyLabel.setSingleLine(replyLabel.lineCount > 1)
|
||||
replyLabel.isSingleLine = replyLabel.lineCount > 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -806,8 +814,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
private fun extensionIntentItemSelected(item: MenuItem) {
|
||||
val intent = item.intent ?: return
|
||||
try {
|
||||
val action = intent.action
|
||||
when (action) {
|
||||
when (intent.action) {
|
||||
INTENT_ACTION_EXTENSION_COMPOSE -> {
|
||||
val accountKeys = accountsAdapter.selectedAccountKeys
|
||||
intent.putExtra(EXTRA_TEXT, ParseUtils.parseString(editText.text))
|
||||
|
@ -1083,16 +1090,20 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val action = intent.action
|
||||
val hasVisibility = intent.hasExtra(EXTRA_VISIBILITY)
|
||||
val hasAccountKeys: Boolean
|
||||
if (intent.hasExtra(EXTRA_ACCOUNT_KEYS)) {
|
||||
val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS)
|
||||
accountsAdapter.selectedAccountKeys = accountKeys
|
||||
hasAccountKeys = true
|
||||
} else if (intent.hasExtra(EXTRA_ACCOUNT_KEY)) {
|
||||
val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
accountsAdapter.selectedAccountKeys = arrayOf(accountKey)
|
||||
hasAccountKeys = true
|
||||
} else {
|
||||
hasAccountKeys = false
|
||||
when {
|
||||
intent.hasExtra(EXTRA_ACCOUNT_KEYS) -> {
|
||||
val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS)
|
||||
accountsAdapter.selectedAccountKeys = accountKeys
|
||||
hasAccountKeys = true
|
||||
}
|
||||
intent.hasExtra(EXTRA_ACCOUNT_KEY) -> {
|
||||
val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
accountsAdapter.selectedAccountKeys = arrayOf(accountKey)
|
||||
hasAccountKeys = true
|
||||
}
|
||||
else -> {
|
||||
hasAccountKeys = false
|
||||
}
|
||||
}
|
||||
when (action) {
|
||||
Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE -> {
|
||||
|
@ -1101,7 +1112,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val stream = intent.getStreamExtra()
|
||||
if (stream != null) {
|
||||
val src = stream.toTypedArray()
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, true, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = true,
|
||||
deleteSrc = false
|
||||
))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
@ -1110,7 +1124,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val data = intent.data
|
||||
if (data != null) {
|
||||
val src = arrayOf(data)
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, true, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = true,
|
||||
deleteSrc = false
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1146,16 +1163,16 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
INTENT_ACTION_EDIT_DRAFT -> {
|
||||
val draft: Draft? = intent.getParcelableExtra(EXTRA_DRAFT)
|
||||
when (draft?.action_type) {
|
||||
return when (draft?.action_type) {
|
||||
Draft.Action.REPLY -> {
|
||||
return showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
}
|
||||
Draft.Action.QUOTE -> {
|
||||
return showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
}
|
||||
else -> {
|
||||
showDefaultLabelAndHint()
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1785,7 +1802,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
s.setSpan(MarkForDeleteSpan(), start, start + count,
|
||||
Spanned.SPAN_INCLUSIVE_INCLUSIVE)
|
||||
}
|
||||
if (!imageSources.isEmpty()) {
|
||||
if (imageSources.isNotEmpty()) {
|
||||
val intent = ThemedMediaPickerActivity.withThemed(this@ComposeActivity)
|
||||
.getMedia(Uri.parse(imageSources[0]))
|
||||
.build()
|
||||
|
@ -1816,7 +1833,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
})
|
||||
editText.customSelectionActionModeCallback = this
|
||||
editText.imageInputListener = { contentInfo ->
|
||||
val task = AddMediaTask(this, arrayOf(contentInfo.contentUri), null, true, false)
|
||||
val task = AddMediaTask(this, arrayOf(contentInfo.contentUri), null,
|
||||
copySrc = true,
|
||||
deleteSrc = false
|
||||
)
|
||||
task.callback = {
|
||||
contentInfo.releasePermission()
|
||||
}
|
||||
|
@ -1839,8 +1859,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val context = activity!!
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
val context = requireActivity()
|
||||
val builder = AlertDialog.Builder(requireContext())
|
||||
builder.setMessage(R.string.quote_protected_status_warning_message)
|
||||
builder.setPositiveButton(R.string.send_anyway, this)
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
|
@ -1873,8 +1893,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val context = activity!!
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
val context = requireActivity()
|
||||
val builder = AlertDialog.Builder(requireContext())
|
||||
builder.setMessage(getString(R.string.message_format_compose_message_convert_to_status,
|
||||
"@$screenName"))
|
||||
builder.setPositiveButton(R.string.action_send, this)
|
||||
|
@ -1886,7 +1906,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
}
|
||||
|
||||
class AttachedMediaItemTouchHelperCallback(adapter: SimpleItemTouchHelperCallback.ItemTouchHelperAdapter) : SimpleItemTouchHelperCallback(adapter) {
|
||||
class AttachedMediaItemTouchHelperCallback(adapter: ItemTouchHelperAdapter) : SimpleItemTouchHelperCallback(adapter) {
|
||||
|
||||
override fun isLongPressDragEnabled(): Boolean {
|
||||
return true
|
||||
|
@ -1906,7 +1926,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
|
||||
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
|
||||
// Fade out the view as it is swiped out of the parent's bounds
|
||||
val alpha = ALPHA_FULL - Math.abs(dY) / viewHolder.itemView.height.toFloat()
|
||||
val alpha = ALPHA_FULL - abs(dY) / viewHolder.itemView.height.toFloat()
|
||||
viewHolder.itemView.alpha = alpha
|
||||
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
|
||||
} else {
|
||||
|
@ -1924,7 +1944,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
|
||||
companion object {
|
||||
val ALPHA_FULL = 1.0f
|
||||
const val ALPHA_FULL = 1.0f
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1996,7 +2016,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
set(value) {
|
||||
selection.clear()
|
||||
for (accountKey in value) {
|
||||
selection.put(accountKey, true)
|
||||
selection[accountKey] = true
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
@ -2034,7 +2054,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
fun toggleSelection(position: Int) {
|
||||
if (accounts == null || position < 0) return
|
||||
val account = accounts!![position]
|
||||
selection.put(account.key, true != selection[account.key])
|
||||
selection[account.key] = true != selection[account.key]
|
||||
activity.updateAccountSelectionState()
|
||||
activity.updateVisibilityState()
|
||||
activity.updateSummaryTextState()
|
||||
|
@ -2046,7 +2066,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
if (accounts == null || position < 0) return
|
||||
val account = accounts!![position]
|
||||
selection.clear()
|
||||
selection.put(account.key, true != selection[account.key])
|
||||
selection[account.key] = true != selection[account.key]
|
||||
activity.updateAccountSelectionState()
|
||||
activity.updateVisibilityState()
|
||||
activity.updateSummaryTextState()
|
||||
|
@ -2096,12 +2116,12 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
private class DisplayPlaceNameTask : AbstractTask<ParcelableLocation, List<Address>, ComposeActivity>() {
|
||||
|
||||
override fun doLongOperation(location: ParcelableLocation): List<Address>? {
|
||||
try {
|
||||
return try {
|
||||
val activity = callback ?: throw IOException("Interrupted")
|
||||
val gcd = Geocoder(activity, Locale.getDefault())
|
||||
return gcd.getFromLocation(location.latitude, location.longitude, 1)
|
||||
gcd.getFromLocation(location.latitude, location.longitude, 1)
|
||||
} catch (e: IOException) {
|
||||
return null
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2119,13 +2139,16 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
textView.spannable = ParcelableLocationUtils.getHumanReadableString(location, 3)
|
||||
textView.tag = location
|
||||
} else {
|
||||
val tag = textView.tag
|
||||
if (tag is Address) {
|
||||
textView.spannable = tag.locality
|
||||
} else if (tag is NoAddress) {
|
||||
textView.setText(R.string.label_location_your_coarse_location)
|
||||
} else {
|
||||
textView.setText(R.string.getting_location)
|
||||
when (val tag = textView.tag) {
|
||||
is Address -> {
|
||||
textView.spannable = tag.locality
|
||||
}
|
||||
is NoAddress -> {
|
||||
textView.setText(R.string.label_location_your_coarse_location)
|
||||
}
|
||||
else -> {
|
||||
textView.setText(R.string.getting_location)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -105,12 +105,12 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
?: return false
|
||||
// val file = File(folder, fileName)
|
||||
// file.delete()
|
||||
try {
|
||||
return try {
|
||||
DataImportExportUtils.exportData(activity, file, flags)
|
||||
return true
|
||||
true
|
||||
} catch (e: IOException) {
|
||||
Log.w(LOGTAG, e)
|
||||
return false
|
||||
false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val FRAGMENT_TAG = "import_settings_dialog"
|
||||
private const val FRAGMENT_TAG = "import_settings_dialog"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -111,12 +111,12 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
return false
|
||||
}
|
||||
if (!file.isFile) return false
|
||||
try {
|
||||
return try {
|
||||
DataImportExportUtils.importData(activity, file, flags)
|
||||
return true
|
||||
true
|
||||
} catch (e: IOException) {
|
||||
Log.w(LOGTAG, e)
|
||||
return false
|
||||
false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val FRAGMENT_TAG = "import_settings_dialog"
|
||||
private const val FRAGMENT_TAG = "import_settings_dialog"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -152,10 +152,10 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
return 0
|
||||
}
|
||||
if (!file.isFile) return 0
|
||||
try {
|
||||
return DataImportExportUtils.getImportedSettingsFlags(activity, file)
|
||||
return try {
|
||||
DataImportExportUtils.getImportedSettingsFlags(activity, file)
|
||||
} catch (e: IOException) {
|
||||
return 0
|
||||
0
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
|
||||
companion object {
|
||||
|
||||
private val FRAGMENT_TAG = "read_settings_data_dialog"
|
||||
private const val FRAGMENT_TAG = "read_settings_data_dialog"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -87,13 +87,17 @@ class FileSelectorActivity : BaseActivity(), FileSelectorDialogFragment.Callback
|
|||
finish()
|
||||
return
|
||||
}
|
||||
if (checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
|
||||
showPickFileDialog()
|
||||
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
|
||||
val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS)
|
||||
} else {
|
||||
finishWithDeniedMessage()
|
||||
when {
|
||||
checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE) -> {
|
||||
showPickFileDialog()
|
||||
}
|
||||
Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN -> {
|
||||
val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS)
|
||||
}
|
||||
else -> {
|
||||
finishWithDeniedMessage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ import org.mariotaku.twidere.util.premium.ExtraFeaturesService
|
|||
import org.mariotaku.twidere.view.HomeDrawerLayout
|
||||
import org.mariotaku.twidere.view.TabPagerIndicator
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.math.floor
|
||||
|
||||
class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, SupportFragmentCallback,
|
||||
OnLongClickListener, DrawerLayout.DrawerListener {
|
||||
|
@ -422,12 +423,18 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
|||
if (!ViewCompat.getFitsSystemWindows(homeMenu)) {
|
||||
homeContent.setPadding(0, insets.systemWindowInsetTop, 0, 0)
|
||||
}
|
||||
(toolbar.layoutParams as? MarginLayoutParams)?.bottomMargin = insets.systemWindowInsetBottom
|
||||
(actionsButton.layoutParams as? MarginLayoutParams)?.bottomMargin =
|
||||
actionsButtonBottomMargin + insets.systemWindowInsetBottom
|
||||
actionsButtonBottomMargin + if (preferences[tabPositionKey] == SharedPreferenceConstants.VALUE_TAB_POSITION_TOP) {
|
||||
insets.systemWindowInsetBottom
|
||||
} else {
|
||||
0
|
||||
}
|
||||
return insets
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
val tabPosition = handleIntent(intent, false)
|
||||
if (tabPosition >= 0) {
|
||||
mainPager.currentItem = tabPosition.coerceInOr(0 until pagerAdapter.count, 0)
|
||||
|
@ -623,16 +630,22 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
|||
}
|
||||
notifyControlBarOffsetChanged()
|
||||
} else {
|
||||
val layoutparams = toolbar.layoutParams
|
||||
val toolbarMarginBottom = if (layoutparams is MarginLayoutParams) {
|
||||
layoutparams.bottomMargin
|
||||
} else {
|
||||
0
|
||||
}
|
||||
val translationY = if (mainTabs.columns > 1 || !toolbar.isVisible) {
|
||||
0
|
||||
} else {
|
||||
(toolbar.height * (offset - 1)).toInt()
|
||||
((toolbar.height + toolbarMarginBottom) * (offset - 1)).toInt()
|
||||
}
|
||||
toolbar.translationY = -translationY.toFloat()
|
||||
windowOverlay.translationY = -translationY.toFloat()
|
||||
val lp = actionsButton.layoutParams
|
||||
if (lp is MarginLayoutParams) {
|
||||
actionsButton.translationY = (lp.bottomMargin + toolbar.height + actionsButton.height) * (1 - offset)
|
||||
actionsButton.translationY = (lp.bottomMargin + toolbar.height + actionsButton.height + toolbarMarginBottom) * (1 - offset)
|
||||
} else {
|
||||
actionsButton.translationY = actionsButton.height * (1 - offset)
|
||||
}
|
||||
|
@ -848,7 +861,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
|||
"wide" -> resources.getDimension(R.dimen.preferred_tab_column_width_wide)
|
||||
else -> resources.getDimension(R.dimen.preferred_tab_column_width_normal)
|
||||
}
|
||||
mainTabs.columns = Math.floor(1.0 / pagerAdapter.getPageWidth(0)).toInt()
|
||||
mainTabs.columns = floor(1.0 / pagerAdapter.getPageWidth(0)).toInt()
|
||||
} else {
|
||||
mainPager.pageMargin = 0
|
||||
mainPager.setPageMarginDrawable(null)
|
||||
|
@ -1059,7 +1072,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
|||
|
||||
class AutoRefreshConfirmDialogFragment : BaseDialogFragment() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
val builder = AlertDialog.Builder(requireContext())
|
||||
builder.setTitle(R.string.auto_refresh)
|
||||
builder.setMessage(R.string.message_auto_refresh_confirm)
|
||||
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
|
|
|
@ -171,7 +171,7 @@ class ImageCropperActivity : BaseActivity(), CropImageView.OnSetImageUriComplete
|
|||
private fun getResultIntent(uri: Uri?, error: Exception?, sampleSize: Int): Intent {
|
||||
val result = CropImage.ActivityResult(cropImageView.imageUri, uri, error,
|
||||
cropImageView.cropPoints, cropImageView.cropRect, cropImageView.rotatedDegrees,
|
||||
sampleSize)
|
||||
cropImageView.wholeImageRect, sampleSize)
|
||||
val intent = Intent()
|
||||
intent.putExtra(CropImage.CROP_IMAGE_EXTRA_RESULT, result)
|
||||
return intent
|
||||
|
|
|
@ -30,7 +30,7 @@ class InvalidAccountAlertActivity : FragmentActivity() {
|
|||
|
||||
class InvalidAccountAlertDialogFragment : BaseDialogFragment() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
val builder = AlertDialog.Builder(requireContext())
|
||||
builder.setTitle(R.string.title_error_invalid_account)
|
||||
builder.setMessage(R.string.message_error_invalid_account)
|
||||
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
|
|
|
@ -119,7 +119,7 @@ class KeyboardShortcutPreferenceCompatActivity : BaseActivity(), OnClickListener
|
|||
|
||||
companion object {
|
||||
|
||||
val EXTRA_CONTEXT_TAG = "context_tag"
|
||||
val EXTRA_KEY_ACTION = "key_action"
|
||||
const val EXTRA_CONTEXT_TAG = "context_tag"
|
||||
const val EXTRA_KEY_ACTION = "key_action"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import android.os.Build
|
|||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.os.Parcelable
|
||||
import android.provider.MediaStore
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -75,6 +74,8 @@ import org.mariotaku.twidere.view.viewer.MediaSwipeCloseContainer
|
|||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
import android.Manifest.permission as AndroidPermissions
|
||||
|
||||
class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeCloseContainer.Listener,
|
||||
|
@ -146,7 +147,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
activityLayout.statusBarAlpha = offset
|
||||
}
|
||||
try {
|
||||
actionBar.hideOffset = Math.round(controlBarHeight * (1f - offset))
|
||||
actionBar.hideOffset = (controlBarHeight * (1f - offset)).roundToInt()
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
// Some device will throw this exception
|
||||
hideOffsetNotSupported = true
|
||||
|
@ -181,6 +182,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (requestCode) {
|
||||
REQUEST_SHARE_MEDIA -> {
|
||||
ShareProvider.clearTempFiles(this)
|
||||
|
@ -367,10 +369,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
ParcelableMedia.Type.IMAGE -> {
|
||||
val mediaUrl = media.media_url ?: return Fragment.instantiate(this, ExternalBrowserPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
args.putParcelable(EXTRA_MEDIA_URI, Uri.parse(mediaUrl))
|
||||
if (mediaUrl.endsWith(".gif")) {
|
||||
return Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
return if (mediaUrl.endsWith(".gif")) {
|
||||
Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
} else {
|
||||
return Fragment.instantiate(this, ImagePageFragment::class.java.name, args) as MediaViewerFragment
|
||||
Fragment.instantiate(this, ImagePageFragment::class.java.name, args) as MediaViewerFragment
|
||||
}
|
||||
}
|
||||
ParcelableMedia.Type.ANIMATED_GIF, ParcelableMedia.Type.CARD_ANIMATED_GIF -> {
|
||||
|
@ -408,10 +410,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
}
|
||||
|
||||
override fun onSwipeOffsetChanged(offset: Int) {
|
||||
val offsetFactor = 1 - (Math.abs(offset).toFloat() / swipeContainer.height)
|
||||
val offsetFactor = 1 - (abs(offset).toFloat() / swipeContainer.height)
|
||||
swipeContainer.backgroundAlpha = offsetFactor
|
||||
val colorToolbar = overrideTheme.colorToolbar
|
||||
val alpha = Math.round(Color.alpha(colorToolbar) * offsetFactor).coerceIn(0..255)
|
||||
val alpha = (Color.alpha(colorToolbar) * offsetFactor).roundToInt().coerceIn(0..255)
|
||||
activityLayout.statusBarAlpha = alpha / 255f
|
||||
}
|
||||
|
||||
|
@ -450,11 +452,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
}
|
||||
|
||||
private fun instantiateMediaViewerFragment(args: Bundle): MediaViewerFragment {
|
||||
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
|
||||
Fragment.instantiate(this, VideoPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
} else {
|
||||
Fragment.instantiate(this, ExoPlayerPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
}
|
||||
return Fragment.instantiate(this, ExoPlayerPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
}
|
||||
|
||||
private fun processShareIntent(intent: Intent) {
|
||||
|
@ -468,11 +466,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
if (checkAllSelfPermissionsGranted(AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
|
||||
saveToStorage()
|
||||
} else {
|
||||
val permissions: Array<String>
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
|
||||
val permissions: Array<String> = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
|
||||
} else {
|
||||
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
PermissionRequestDialog.show(supportFragmentManager, getString(R.string.message_permission_request_save_media),
|
||||
permissions, REQUEST_PERMISSION_SAVE_MEDIA)
|
||||
|
@ -503,8 +500,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
|
||||
private fun saveToStorage() {
|
||||
val fileInfo = getCurrentCacheFileInfo(saveToStoragePosition) ?: return
|
||||
val type = (fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType
|
||||
val pubDir = when (type) {
|
||||
val pubDir = when ((fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType) {
|
||||
CacheFileType.VIDEO -> {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
||||
|
@ -640,10 +636,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
|
||||
companion object {
|
||||
|
||||
private val REQUEST_SHARE_MEDIA = 201
|
||||
private val REQUEST_PERMISSION_SAVE_MEDIA = 202
|
||||
private val REQUEST_PERMISSION_SHARE_MEDIA = 203
|
||||
private val REQUEST_SELECT_SAVE_MEDIA = 204
|
||||
private const val REQUEST_SHARE_MEDIA = 201
|
||||
private const val REQUEST_PERMISSION_SAVE_MEDIA = 202
|
||||
private const val REQUEST_PERMISSION_SHARE_MEDIA = 203
|
||||
private const val REQUEST_SELECT_SAVE_MEDIA = 204
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
const val FLAG_SYSTEM_UI_HIDE_BARS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||
|
|
|
@ -89,6 +89,7 @@ class PremiumDashboardActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (resultCode) {
|
||||
REQUEST_PURCHASE_EXTRA_FEATURES -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
|
|
|
@ -171,7 +171,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
|||
override fun onDismiss(listView: ListView, reverseSortedPositions: IntArray) {
|
||||
val adapter = suggestionsList.adapter as SuggestionsAdapter
|
||||
val ids = LongArray(reverseSortedPositions.size)
|
||||
for (i in 0 until reverseSortedPositions.size) {
|
||||
for (i in reverseSortedPositions.indices) {
|
||||
val position = reverseSortedPositions[i]
|
||||
val item = adapter.getSuggestionItem(position) ?: return
|
||||
ids[i] = item._id
|
||||
|
@ -215,6 +215,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
|||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (requestCode) {
|
||||
REQUEST_SCAN_QR -> {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
|
@ -504,7 +505,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
|||
private fun getActualPosition(position: Int): Int {
|
||||
var skipped = 0
|
||||
for (i in 0 until removedPositions.size) {
|
||||
if (position + skipped >= removedPositions.get(i)) {
|
||||
if (position + skipped >= removedPositions[i]) {
|
||||
skipped++
|
||||
}
|
||||
}
|
||||
|
@ -537,10 +538,10 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
|||
|
||||
companion object {
|
||||
|
||||
internal val VIEW_TYPE_SEARCH_HISTORY = 0
|
||||
internal val VIEW_TYPE_SAVED_SEARCH = 1
|
||||
internal val VIEW_TYPE_USER_SUGGESTION_ITEM = 2
|
||||
internal val VIEW_TYPE_USER_SCREEN_NAME = 3
|
||||
internal const val VIEW_TYPE_SEARCH_HISTORY = 0
|
||||
internal const val VIEW_TYPE_SAVED_SEARCH = 1
|
||||
internal const val VIEW_TYPE_USER_SUGGESTION_ITEM = 2
|
||||
internal const val VIEW_TYPE_USER_SCREEN_NAME = 3
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.mariotaku.twidere.util.DeviceUtils
|
|||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler
|
||||
import org.mariotaku.twidere.util.ThemeUtils
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartFragmentCallback {
|
||||
|
||||
|
@ -74,8 +75,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
|||
shouldTerminate = savedInstanceState.getBoolean(EXTRA_SHOULD_TERMINATE, shouldTerminate)
|
||||
} else if (intent.getBooleanExtra(EXTRA_SHOULD_TERMINATE, false)) {
|
||||
finishNoRestart()
|
||||
System.exit(0)
|
||||
return
|
||||
exitProcess(0)
|
||||
}
|
||||
|
||||
val backgroundOption = currentThemeBackgroundOption
|
||||
|
@ -349,8 +349,8 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
|||
|
||||
companion object {
|
||||
|
||||
val VIEW_TYPE_PREFERENCE_ENTRY = 0
|
||||
val VIEW_TYPE_HEADER_ENTRY = 1
|
||||
const val VIEW_TYPE_PREFERENCE_ENTRY = 0
|
||||
const val VIEW_TYPE_HEADER_ENTRY = 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
|||
|
||||
class RestartConfirmDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(activity!!)
|
||||
val builder = AlertDialog.Builder(requireActivity())
|
||||
if (arguments?.getBoolean(EXTRA_SHOULD_TERMINATE) == true) {
|
||||
builder.setMessage(R.string.app_terminate_confirm)
|
||||
builder.setNegativeButton(R.string.action_dont_terminate, this)
|
||||
|
@ -424,7 +424,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
|||
|
||||
companion object {
|
||||
|
||||
private val RESULT_SETTINGS_CHANGED = 10
|
||||
private const val RESULT_SETTINGS_CHANGED = 10
|
||||
|
||||
fun setShouldRecreate(activity: Activity) {
|
||||
if (activity !is SettingsActivity) return
|
||||
|
|
|
@ -428,23 +428,30 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
internal fun onSignInError(exception: Exception) {
|
||||
DebugLog.w(LOGTAG, "Sign in error", exception)
|
||||
var errorReason: String? = null
|
||||
if (exception is AuthenticityTokenException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
} else if (exception is WrongUserPassException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
} else if (exception is SignInTask.WrongBasicCredentialException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
} else if (exception is SignInTask.WrongAPIURLFormatException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
} else if (exception is LoginVerificationException) {
|
||||
Toast.makeText(this, R.string.message_toast_login_verification_failed, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "login_verification_failed"
|
||||
} else {
|
||||
Toast.makeText(this, exception.getErrorMessage(this), Toast.LENGTH_SHORT).show()
|
||||
when (exception) {
|
||||
is AuthenticityTokenException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
}
|
||||
is WrongUserPassException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
}
|
||||
is SignInTask.WrongBasicCredentialException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
}
|
||||
is SignInTask.WrongAPIURLFormatException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
}
|
||||
is LoginVerificationException -> {
|
||||
Toast.makeText(this, R.string.message_toast_login_verification_failed, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "login_verification_failed"
|
||||
}
|
||||
else -> {
|
||||
Toast.makeText(this, exception.getErrorMessage(this), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
Analyzer.log(SignIn(false, credentialsType = apiConfig.credentialsType,
|
||||
errorReason = errorReason, accountType = apiConfig.type))
|
||||
|
@ -573,13 +580,13 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
class SignInTypeChooserDialogFragment : BaseDialogFragment(),
|
||||
LoaderManager.LoaderCallbacks<List<CustomAPIConfig>> {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
val builder = AlertDialog.Builder(requireContext())
|
||||
builder.setView(R.layout.dialog_expandable_list)
|
||||
val dialog = builder.create()
|
||||
dialog.onShow {
|
||||
it.applyTheme()
|
||||
val listView = it.expandableList
|
||||
val adapter = LoginTypeAdapter(context!!)
|
||||
val adapter = LoginTypeAdapter(requireContext())
|
||||
listView.setAdapter(adapter)
|
||||
listView.setOnGroupClickListener { _, _, groupPosition, _ ->
|
||||
val type = adapter.getGroup(groupPosition)
|
||||
|
@ -623,7 +630,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
AccountType.MASTODON, AccountType.STATUSNET)
|
||||
val result = supportedAccountTypes.mapNotNullTo(ArrayList()) { type ->
|
||||
if (type == AccountType.MASTODON) return@mapNotNullTo LoginType(type,
|
||||
listOf(CustomAPIConfig.mastodon(context!!)))
|
||||
listOf(CustomAPIConfig.mastodon(requireContext())))
|
||||
return@mapNotNullTo configGroup[type]?.let { list ->
|
||||
LoginType(type, list.sortedBy { !it.isDefault })
|
||||
}
|
||||
|
@ -632,7 +639,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
}
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<CustomAPIConfig>> {
|
||||
return DefaultAPIConfigLoader(context!!)
|
||||
return DefaultAPIConfigLoader(requireContext())
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<CustomAPIConfig>>) {
|
||||
|
@ -694,7 +701,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
var challengeType: String? = null
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
val builder = AlertDialog.Builder(requireContext())
|
||||
builder.setTitle(R.string.login_verification)
|
||||
builder.setView(R.layout.dialog_login_verification_code)
|
||||
builder.positive(android.R.string.ok, this::performVerification)
|
||||
|
@ -753,7 +760,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
class PasswordSignInDialogFragment : BaseDialogFragment() {
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
val builder = AlertDialog.Builder(requireContext())
|
||||
builder.setView(R.layout.dialog_password_sign_in)
|
||||
builder.positive(R.string.action_sign_in, this::onPositiveButton)
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
|
@ -809,10 +816,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
val oauth = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
|
||||
accountType = apiConfig.type, cls = TwitterOAuth::class.java)
|
||||
val accessToken: OAuthToken
|
||||
if (oauthVerifier != null) {
|
||||
accessToken = oauth.getAccessToken(requestToken, oauthVerifier)
|
||||
accessToken = if (oauthVerifier != null) {
|
||||
oauth.getAccessToken(requestToken, oauthVerifier)
|
||||
} else {
|
||||
accessToken = oauth.getAccessToken(requestToken)
|
||||
oauth.getAccessToken(requestToken)
|
||||
}
|
||||
auth = apiConfig.getOAuthAuthorization(accessToken) ?:
|
||||
throw MicroBlogException("Invalid OAuth credential")
|
||||
|
@ -823,7 +830,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(context)
|
||||
|
@ -901,7 +908,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
return authOAuth()
|
||||
}
|
||||
|
||||
@Throws(OAuthPasswordAuthenticator.AuthenticationException::class, MicroBlogException::class)
|
||||
@Throws(AuthenticationException::class, MicroBlogException::class)
|
||||
private fun authOAuth(): SignInResponse {
|
||||
val activity = activityRef.get() ?: throw InterruptedException()
|
||||
val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
||||
|
@ -940,7 +947,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
return getOAuthSignInResponse(activity, accessToken, Credentials.Type.XAUTH)
|
||||
}
|
||||
|
||||
@Throws(MicroBlogException::class, OAuthPasswordAuthenticator.AuthenticationException::class)
|
||||
@Throws(MicroBlogException::class, AuthenticationException::class)
|
||||
private fun authBasic(): SignInResponse {
|
||||
val activity = activityRef.get() ?: throw InterruptedException()
|
||||
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
||||
|
@ -962,7 +969,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
}
|
||||
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
|
@ -991,7 +998,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
|
@ -1018,7 +1025,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
|
@ -1040,11 +1047,11 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
return SignInResponse(account != null, authType, credentials, user, color, type, extras)
|
||||
}
|
||||
|
||||
internal class WrongBasicCredentialException : OAuthPasswordAuthenticator.AuthenticationException()
|
||||
internal class WrongBasicCredentialException : AuthenticationException()
|
||||
|
||||
internal class WrongAPIURLFormatException : OAuthPasswordAuthenticator.AuthenticationException()
|
||||
internal class WrongAPIURLFormatException : AuthenticationException()
|
||||
|
||||
internal inner class InputLoginVerificationCallback : OAuthPasswordAuthenticator.LoginVerificationCallback {
|
||||
internal inner class InputLoginVerificationCallback : LoginVerificationCallback {
|
||||
|
||||
override fun getLoginVerification(challengeType: String): String? {
|
||||
// Dismiss current progress dialog
|
||||
|
@ -1087,10 +1094,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
protected val profileImageSize: String = activity.getString(R.string.profile_image_size)
|
||||
|
||||
final override fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
|
||||
try {
|
||||
return SingleResponse.getInstance(performLogin())
|
||||
return try {
|
||||
SingleResponse.getInstance(performLogin())
|
||||
} catch (e: Exception) {
|
||||
return SingleResponse.getInstance(e)
|
||||
SingleResponse.getInstance(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1189,8 +1196,8 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
const val REQUEST_BROWSER_TWITTER_SIGN_IN = 101
|
||||
const val REQUEST_BROWSER_MASTODON_SIGN_IN = 102
|
||||
|
||||
private val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
|
||||
private val EXTRA_API_LAST_CHANGE = "api_last_change"
|
||||
private const val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
|
||||
private const val EXTRA_API_LAST_CHANGE = "api_last_change"
|
||||
|
||||
@Throws(IOException::class)
|
||||
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {
|
||||
|
|
|
@ -41,8 +41,8 @@ class ThemedMediaPickerActivity : MediaPickerActivity() {
|
|||
|
||||
companion object {
|
||||
|
||||
fun withThemed(context: Context): MediaPickerActivity.IntentBuilder {
|
||||
val builder = MediaPickerActivity.IntentBuilder(context, ThemedMediaPickerActivity::class.java)
|
||||
fun withThemed(context: Context): IntentBuilder {
|
||||
val builder = IntentBuilder(context, ThemedMediaPickerActivity::class.java)
|
||||
builder.cropImageActivityClass(ImageCropperActivity::class.java)
|
||||
builder.streamDownloaderClass(RestFuNetworkStreamDownloader::class.java)
|
||||
return builder
|
||||
|
|
|
@ -93,7 +93,7 @@ class TrendsLocationSelectorActivity : BaseActivity() {
|
|||
private val list: Array<LocationsMap.LocationsData> get() = arguments?.getTypedArray(EXTRA_DATA) ?: emptyArray()
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val selectorBuilder = AlertDialog.Builder(context!!)
|
||||
val selectorBuilder = AlertDialog.Builder(requireContext())
|
||||
selectorBuilder.setTitle(R.string.trends_location)
|
||||
selectorBuilder.setView(R.layout.dialog_expandable_list)
|
||||
selectorBuilder.setNegativeButton(android.R.string.cancel, null)
|
||||
|
@ -101,7 +101,7 @@ class TrendsLocationSelectorActivity : BaseActivity() {
|
|||
dialog.onShow {
|
||||
it.applyTheme()
|
||||
val listView = it.expandableList
|
||||
val adapter = ExpandableTrendLocationsListAdapter(context!!)
|
||||
val adapter = ExpandableTrendLocationsListAdapter(requireContext())
|
||||
adapter.data = list
|
||||
listView.setAdapter(adapter)
|
||||
listView.setOnGroupClickListener(ExpandableListView.OnGroupClickListener { _, _, groupPosition, _ ->
|
||||
|
@ -177,23 +177,14 @@ class TrendsLocationSelectorActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||
val view: View
|
||||
if (convertView != null) {
|
||||
view = convertView
|
||||
} else {
|
||||
view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
|
||||
}
|
||||
val view: View = convertView ?: inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
|
||||
view.findViewById<TextView>(android.R.id.text1).text = getGroup(groupPosition).name
|
||||
return view
|
||||
}
|
||||
|
||||
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||
val view: View
|
||||
if (convertView != null) {
|
||||
view = convertView
|
||||
} else {
|
||||
view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
}
|
||||
val view: View =
|
||||
convertView ?: inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
val location = getChild(groupPosition, childPosition)
|
||||
val text1 = view.findViewById<TextView>(android.R.id.text1)
|
||||
if (location.parentId == WORLDWIDE) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue