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
|
- git
|
||||||
- ruby
|
- ruby
|
||||||
|
|
||||||
before_cache:
|
# before_cache:
|
||||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
# - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||||
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
# - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||||
cache:
|
# cache:
|
||||||
directories:
|
# directories:
|
||||||
- $HOME/.gradle/caches/
|
# - $HOME/.gradle/caches/
|
||||||
- $HOME/.gradle/wrapper/
|
# - $HOME/.gradle/wrapper/
|
||||||
- $HOME/.m2/
|
# - $HOME/.m2/
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- ./travis/scripts/decode_private_configs.sh
|
- ./travis/scripts/decode_private_configs.sh
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/twidere/localized.svg)](https://crowdin.com/project/twidere)
|
[![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)
|
[<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/).
|
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 {
|
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
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,13 @@ buildscript {
|
||||||
allprojects {
|
allprojects {
|
||||||
ext {
|
ext {
|
||||||
projectGroupId = 'org.mariotaku.twidere'
|
projectGroupId = 'org.mariotaku.twidere'
|
||||||
projectVersionCode = 512
|
projectVersionCode = 513
|
||||||
projectVersionName = '4.1.3'
|
projectVersionName = '4.1.4'
|
||||||
|
|
||||||
globalCompileSdkVersion = 29
|
globalCompileSdkVersion = 29
|
||||||
globalBuildToolsVersion = "29.0.3"
|
globalBuildToolsVersion = "29.0.3"
|
||||||
|
|
||||||
globalMinSdkVersion = 19
|
globalMinSdkVersion = 16
|
||||||
globalTargetSdkVersion = 29
|
globalTargetSdkVersion = 29
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,54 +39,18 @@ subprojects {
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
kotlinVersion = '1.3.72'
|
kotlinVersion = '1.3.72'
|
||||||
pluginVersions = [
|
sharedVersions = [
|
||||||
AndroidSvgDrawable: '3.0.0',
|
|
||||||
PlayServices : '4.3.3',
|
|
||||||
]
|
|
||||||
libVersions = [
|
|
||||||
Kotlin : "${kotlinVersion}",
|
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',
|
LoganSquare : '1.3.7',
|
||||||
IABv3 : '1.1.0',
|
Jackson : '2.7.4',
|
||||||
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',
|
|
||||||
ParcelablePlease : '1.0.2',
|
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',
|
ExportablePreferences: '0.9.7',
|
||||||
ACRA : '4.9.2',
|
MariotakuCommons : '0.9.20',
|
||||||
AbstractTask : '0.9.5',
|
ObjectCursor : '0.9.21',
|
||||||
Dagger : '2.11',
|
RestFu : '0.9.60',
|
||||||
StethoBeanShellREPL : '0.1',
|
|
||||||
MessageBubbleView : '3.5',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
org.gradle.jvmargs=-Xmx3584m
|
org.gradle.jvmargs=-Xmx3584m
|
||||||
#https://github.com/TwidereProject/Twidere-Android/issues/963
|
#https://github.com/TwidereProject/Twidere-Android/issues/963
|
||||||
android.enableAapt2=false
|
# android.enableAapt2=false
|
||||||
android.useAndroidX=true
|
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
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
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
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -82,6 +82,7 @@ esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
@ -129,6 +130,7 @@ fi
|
||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
# 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
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@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%
|
"%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.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
org.gradle.jvmargs=-Xmx3584m
|
org.gradle.jvmargs=-Xmx3584m
|
||||||
org.gradle.parallel=false
|
|
||||||
kotlin.incremental=false
|
|
||||||
kotlin.compiler.execution.strategy=in-process
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
android.jetifier.blacklist=android-4.1.1.4.jar
|
|
@ -38,8 +38,8 @@ buildscript {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
|
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
|
||||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
|
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,12 +58,19 @@ android {
|
||||||
versionCode projectVersionCode
|
versionCode projectVersionCode
|
||||||
versionName projectVersionName
|
versionName projectVersionName
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
encoding = 'UTF-8'
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -72,23 +79,23 @@ dependencies {
|
||||||
|
|
||||||
|
|
||||||
/** Third-party dependencies **/
|
/** Third-party dependencies **/
|
||||||
implementation "com.bluelinelabs:logansquare:${libVersions['LoganSquare']}"
|
implementation "com.bluelinelabs:logansquare:${sharedVersions['LoganSquare']}"
|
||||||
annotationProcessor "com.bluelinelabs:logansquare-compiler:${libVersions['LoganSquare']}"
|
annotationProcessor "com.bluelinelabs:logansquare-compiler:${sharedVersions['LoganSquare']}"
|
||||||
implementation "com.fasterxml.jackson.core:jackson-core:2.7.4"
|
implementation "com.fasterxml.jackson.core:jackson-core:${sharedVersions['Jackson']}"
|
||||||
implementation "com.hannesdorfmann.parcelableplease:annotation:${libVersions['ParcelablePlease']}"
|
implementation "com.hannesdorfmann.parcelableplease:annotation:${sharedVersions['ParcelablePlease']}"
|
||||||
annotationProcessor "com.hannesdorfmann.parcelableplease:processor:${libVersions['ParcelablePlease']}"
|
annotationProcessor "com.hannesdorfmann.parcelableplease:processor:${sharedVersions['ParcelablePlease']}"
|
||||||
|
|
||||||
|
|
||||||
/** Custom dependencies **/
|
/** Custom dependencies **/
|
||||||
implementation "com.github.mariotaku.RestFu:library:${libVersions['RestFu']}"
|
implementation "com.github.mariotaku.ExportablePreferences:core:${sharedVersions['ExportablePreferences']}"
|
||||||
implementation "com.github.mariotaku.RestFu:oauth:${libVersions['RestFu']}"
|
annotationProcessor "com.github.mariotaku.ExportablePreferences:processor:${sharedVersions['ExportablePreferences']}"
|
||||||
implementation "com.github.mariotaku.RestFu:oauth2:${libVersions['RestFu']}"
|
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${sharedVersions['MariotakuCommons']}"
|
||||||
implementation "com.github.mariotaku.ObjectCursor:core:${libVersions['ObjectCursor']}"
|
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${sharedVersions['MariotakuCommons']}"
|
||||||
annotationProcessor "com.github.mariotaku.ObjectCursor:processor:${libVersions['ObjectCursor']}"
|
implementation "com.github.mariotaku.ObjectCursor:core:${sharedVersions['ObjectCursor']}"
|
||||||
implementation "com.github.mariotaku.ExportablePreferences:core:${libVersions['ExportablePreferences']}"
|
annotationProcessor "com.github.mariotaku.ObjectCursor:processor:${sharedVersions['ObjectCursor']}"
|
||||||
annotationProcessor "com.github.mariotaku.ExportablePreferences:processor:${libVersions['ExportablePreferences']}"
|
implementation "com.github.mariotaku.RestFu:library:${sharedVersions['RestFu']}"
|
||||||
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${libVersions['MariotakuCommons']}"
|
implementation "com.github.mariotaku.RestFu:oauth:${sharedVersions['RestFu']}"
|
||||||
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${libVersions['MariotakuCommons']}"
|
implementation "com.github.mariotaku.RestFu:oauth2:${sharedVersions['RestFu']}"
|
||||||
}
|
}
|
||||||
|
|
||||||
install {
|
install {
|
||||||
|
|
|
@ -206,7 +206,7 @@ public class MicroBlogException extends Exception implements TwitterResponse, Ht
|
||||||
try {
|
try {
|
||||||
final String retryAfterStr = httpResponse.getHeader("Retry-After");
|
final String retryAfterStr = httpResponse.getHeader("Retry-After");
|
||||||
if (retryAfterStr != null) {
|
if (retryAfterStr != null) {
|
||||||
retryAfter = Integer.valueOf(retryAfterStr);
|
retryAfter = Integer.parseInt(retryAfterStr);
|
||||||
}
|
}
|
||||||
} catch (final NumberFormatException ignore) {
|
} catch (final NumberFormatException ignore) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,11 @@
|
||||||
|
|
||||||
package org.mariotaku.microblog.library.mastodon.model;
|
package org.mariotaku.microblog.library.mastodon.model;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
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}
|
* {@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")
|
@JsonField(name = "text_url")
|
||||||
String textUrl;
|
String textUrl;
|
||||||
|
|
||||||
|
@JsonField(name = "meta")
|
||||||
|
MetaInfo meta;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +89,51 @@ public class Attachment {
|
||||||
return textUrl;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Attachment{" +
|
return "Attachment{" +
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class CardDataMap implements ValueMap {
|
||||||
@Override
|
@Override
|
||||||
public String[] keys() {
|
public String[] keys() {
|
||||||
final Set<String> keySet = map.keySet();
|
final Set<String> keySet = map.keySet();
|
||||||
return keySet.toArray(new String[keySet.size()]);
|
return keySet.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,7 +37,6 @@ import java.util.List;
|
||||||
@Keep
|
@Keep
|
||||||
public class IDs$$JsonObjectMapper extends JsonMapper<IDs> {
|
public class IDs$$JsonObjectMapper extends JsonMapper<IDs> {
|
||||||
|
|
||||||
@SuppressWarnings("TryWithIdenticalCatches")
|
|
||||||
@Override
|
@Override
|
||||||
public IDs parse(JsonParser jsonParser) throws IOException {
|
public IDs parse(JsonParser jsonParser) throws IOException {
|
||||||
IDs instance = new IDs();
|
IDs instance = new IDs();
|
||||||
|
|
|
@ -61,11 +61,8 @@ public final class ResponseList$$JsonObjectMapper<T> extends JsonMapper<Response
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void parseField(ResponseList<T> instance, String fieldName, JsonParser jsonParser) throws IOException {
|
public void parseField(ResponseList<T> instance, String fieldName, JsonParser jsonParser) throws IOException {
|
||||||
switch (fieldName) {
|
if ("results".equals(fieldName)) {
|
||||||
case "results": {
|
instance.addAll(m84ClassJsonMapper.parseList(jsonParser));
|
||||||
instance.addAll(m84ClassJsonMapper.parseList(jsonParser));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,7 @@ public class UniversalSearchResult {
|
||||||
index.end = jsonParser.nextIntValue(-1);
|
index.end = jsonParser.nextIntValue(-1);
|
||||||
list.add(index);
|
list.add(index);
|
||||||
}
|
}
|
||||||
return list.toArray(new Index[list.size()]);
|
return list.toArray(new Index[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -52,12 +52,9 @@ public final class InternalParseUtil {
|
||||||
accessLevel = TwitterResponse.AccessLevel.READ_WRITE;
|
accessLevel = TwitterResponse.AccessLevel.READ_WRITE;
|
||||||
break;
|
break;
|
||||||
case 25:
|
case 25:
|
||||||
// “read-write-directmessages” (Read, Write, & Direct
|
|
||||||
// Message)
|
|
||||||
accessLevel = TwitterResponse.AccessLevel.READ_WRITE_DIRECTMESSAGES;
|
|
||||||
break;
|
|
||||||
case 26:
|
case 26:
|
||||||
// “read-write-privatemessages” (Read, Write, & Direct
|
// “read-write-privatemessages” (Read, Write, & Direct
|
||||||
|
// “read-write-directmessages” (Read, Write, & Direct
|
||||||
// Message)
|
// Message)
|
||||||
accessLevel = TwitterResponse.AccessLevel.READ_WRITE_DIRECTMESSAGES;
|
accessLevel = TwitterResponse.AccessLevel.READ_WRITE_DIRECTMESSAGES;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -64,8 +64,8 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
||||||
String ETAG_MASTODON_APPS_PREFERENCES_NAME = "mastodon_apps";
|
String ETAG_MASTODON_APPS_PREFERENCES_NAME = "mastodon_apps";
|
||||||
String ACCOUNT_PREFERENCES_NAME_PREFIX = "account_preferences_";
|
String ACCOUNT_PREFERENCES_NAME_PREFIX = "account_preferences_";
|
||||||
|
|
||||||
String TWITTER_CONSUMER_KEY = "wmtrtTaVOjUnH5pWQp4LDI5Qs";
|
String TWITTER_CONSUMER_KEY = "MUUBibXUognm6e9vbzrUIqPkt";
|
||||||
String TWITTER_CONSUMER_SECRET = "E9Q9u2yK0COJae2tLcNEdY75OPA3bxqJiGZQztraHaQUtoI2cu";
|
String TWITTER_CONSUMER_SECRET = "l2uWAgQkoHvDfM2PrRFx2WN4h7QIUIktmxyeTAqRo6TkGCtNKy";
|
||||||
|
|
||||||
String YANDEX_KEY = "trnsl.1.1.20200513T065609Z.8e72845b632aa04f.fe1297e42c152de9e8773e1bc71162b1e498e2a8";
|
String YANDEX_KEY = "trnsl.1.1.20200513T065609Z.8e72845b632aa04f.fe1297e42c152de9e8773e1bc71162b1e498e2a8";
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,5 @@ public @interface FilterScope {
|
||||||
|
|
||||||
// Contains all flags
|
// Contains all flags
|
||||||
int ALL = 0xFFFFFFFF;
|
int ALL = 0xFFFFFFFF;
|
||||||
@SuppressWarnings("PointlessBitwiseExpression")
|
|
||||||
int DEFAULT = ALL & ~(TARGET_NAME | TARGET_DESCRIPTION);
|
int DEFAULT = ALL & ~(TARGET_NAME | TARGET_DESCRIPTION);
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,6 +291,8 @@ public interface SharedPreferenceConstants {
|
||||||
String KEY_AUTO_HIDE_TABS = "auto_hide_tabs";
|
String KEY_AUTO_HIDE_TABS = "auto_hide_tabs";
|
||||||
@ExportablePreference(BOOLEAN)
|
@ExportablePreference(BOOLEAN)
|
||||||
String KEY_HIDE_CARD_NUMBERS = "hide_card_numbers";
|
String KEY_HIDE_CARD_NUMBERS = "hide_card_numbers";
|
||||||
|
@ExportablePreference(BOOLEAN)
|
||||||
|
String KEY_SHOW_LINK_PREVIEW = "show_link_preview";
|
||||||
|
|
||||||
// Internal preferences
|
// Internal preferences
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ import java.util.Arrays;
|
||||||
@JsonObject
|
@JsonObject
|
||||||
@ParcelablePlease
|
@ParcelablePlease
|
||||||
public class ParcelableMedia implements Parcelable {
|
public class ParcelableMedia implements Parcelable {
|
||||||
@SuppressWarnings("NullableProblems")
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@JsonField(name = "url")
|
@JsonField(name = "url")
|
||||||
@ParcelableThisPlease
|
@ParcelableThisPlease
|
||||||
|
|
|
@ -31,7 +31,6 @@ import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||||
@ParcelablePlease
|
@ParcelablePlease
|
||||||
public class ParcelableMediaUpdate implements Parcelable {
|
public class ParcelableMediaUpdate implements Parcelable {
|
||||||
|
|
||||||
@SuppressWarnings("NullableProblems")
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@JsonField(name = "uri")
|
@JsonField(name = "uri")
|
||||||
public String uri;
|
public String uri;
|
||||||
|
|
|
@ -20,11 +20,11 @@ package org.mariotaku.twidere.model;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import androidx.annotation.IntDef;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import androidx.annotation.LongDef;
|
import androidx.annotation.LongDef;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||||
|
@ -52,13 +52,7 @@ import java.util.Comparator;
|
||||||
@ParcelablePlease
|
@ParcelablePlease
|
||||||
public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus>, Cloneable {
|
public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus>, Cloneable {
|
||||||
|
|
||||||
public static final Comparator<ParcelableStatus> REVERSE_COMPARATOR = new Comparator<ParcelableStatus>() {
|
public static final Comparator<ParcelableStatus> REVERSE_COMPARATOR = (object1, object2) -> object2.compareTo(object1);
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(final ParcelableStatus object1, final ParcelableStatus object2) {
|
|
||||||
return object2.compareTo(object1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public static final Creator<ParcelableStatus> CREATOR = new Creator<ParcelableStatus>() {
|
public static final Creator<ParcelableStatus> CREATOR = new Creator<ParcelableStatus>() {
|
||||||
@Override
|
@Override
|
||||||
public ParcelableStatus createFromParcel(Parcel source) {
|
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)
|
@CursorField(value = Statuses._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
|
||||||
public long _id;
|
public long _id;
|
||||||
|
|
||||||
@SuppressWarnings("NullableProblems")
|
|
||||||
@JsonField(name = "id")
|
@JsonField(name = "id")
|
||||||
@CursorField(Statuses.ID)
|
@CursorField(Statuses.ID)
|
||||||
@NonNull
|
@NonNull
|
||||||
public String id;
|
public String id;
|
||||||
|
|
||||||
@SuppressWarnings("NullableProblems")
|
|
||||||
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
|
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
|
||||||
@CursorField(value = Statuses.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
|
@CursorField(value = Statuses.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -98,7 +90,6 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
||||||
@JsonField(name = "timestamp")
|
@JsonField(name = "timestamp")
|
||||||
@CursorField(Statuses.TIMESTAMP)
|
@CursorField(Statuses.TIMESTAMP)
|
||||||
public long timestamp;
|
public long timestamp;
|
||||||
@SuppressWarnings("NullableProblems")
|
|
||||||
|
|
||||||
@JsonField(name = "user_id", typeConverter = UserKeyConverter.class)
|
@JsonField(name = "user_id", typeConverter = UserKeyConverter.class)
|
||||||
@CursorField(value = Statuses.USER_KEY, converter = UserKeyCursorFieldConverter.class)
|
@CursorField(value = Statuses.USER_KEY, converter = UserKeyCursorFieldConverter.class)
|
||||||
|
@ -527,6 +518,9 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
||||||
@JsonField(name = "external_url")
|
@JsonField(name = "external_url")
|
||||||
public String external_url;
|
public String external_url;
|
||||||
|
|
||||||
|
@JsonField(name = "entities_url")
|
||||||
|
public String[] entities_url;
|
||||||
|
|
||||||
@JsonField(name = "quoted_external_url")
|
@JsonField(name = "quoted_external_url")
|
||||||
public String quoted_external_url;
|
public String quoted_external_url;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ import java.util.Arrays;
|
||||||
@JsonObject
|
@JsonObject
|
||||||
public class ParcelableStatusUpdate implements Parcelable {
|
public class ParcelableStatusUpdate implements Parcelable {
|
||||||
|
|
||||||
@SuppressWarnings("NullableProblems")
|
|
||||||
@JsonField(name = "accounts")
|
@JsonField(name = "accounts")
|
||||||
@NonNull
|
@NonNull
|
||||||
@ParcelableThisPlease
|
@ParcelableThisPlease
|
||||||
|
|
|
@ -45,7 +45,6 @@ public class ParcelableTrend implements Parcelable {
|
||||||
|
|
||||||
@CursorField(value = CachedTrends._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
|
@CursorField(value = CachedTrends._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
|
||||||
long _id;
|
long _id;
|
||||||
@SuppressWarnings("NullableProblems")
|
|
||||||
@ParcelableThisPlease
|
@ParcelableThisPlease
|
||||||
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
|
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
|
||||||
@CursorField(value = CachedTrends.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
|
@CursorField(value = CachedTrends.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
|
||||||
|
|
|
@ -35,10 +35,8 @@ import java.io.IOException;
|
||||||
public abstract class ConversationExtras implements Parcelable {
|
public abstract class ConversationExtras implements Parcelable {
|
||||||
public static ConversationExtras parse(@NonNull final String extrasType, @Nullable final String json) throws IOException {
|
public static ConversationExtras parse(@NonNull final String extrasType, @Nullable final String json) throws IOException {
|
||||||
if (json == null) return null;
|
if (json == null) return null;
|
||||||
switch (extrasType) {
|
if (ExtrasType.TWITTER_OFFICIAL.equals(extrasType)) {
|
||||||
case ExtrasType.TWITTER_OFFICIAL: {
|
return LoganSquare.parse(json, TwitterOfficialConversationExtras.class);
|
||||||
return LoganSquare.parse(json, TwitterOfficialConversationExtras.class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return LoganSquare.parse(json, DefaultConversationExtras.class);
|
return LoganSquare.parse(json, DefaultConversationExtras.class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class UserKeysConverter implements TypeConverter<UserKey[]> {
|
||||||
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
|
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
|
||||||
list.add(UserKey.valueOf(jsonParser.getValueAsString()));
|
list.add(UserKey.valueOf(jsonParser.getValueAsString()));
|
||||||
}
|
}
|
||||||
return list.toArray(new UserKey[list.size()]);
|
return list.toArray(new UserKey[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,6 +29,12 @@ android {
|
||||||
minSdkVersion globalMinSdkVersion
|
minSdkVersion globalMinSdkVersion
|
||||||
targetSdkVersion globalTargetSdkVersion
|
targetSdkVersion globalTargetSdkVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
encoding = 'UTF-8'
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -314,7 +314,7 @@ public class NyanDrawingHelper {
|
||||||
public void dispatchOnDraw(final Canvas canvas) {
|
public void dispatchOnDraw(final Canvas canvas) {
|
||||||
final int w = canvas.getWidth(), h = canvas.getHeight();
|
final int w = canvas.getWidth(), h = canvas.getHeight();
|
||||||
if (w <= 0 || h <= 0) return;
|
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 int col = star.nextColumn(), row = star.nextRow();
|
||||||
final float y = (row + 0.5f) * (h / mStarRows), x = (col + 0.5f) * (w / mStarCols);
|
final float y = (row + 0.5f) * (h / mStarRows), x = (col + 0.5f) * (w / mStarCols);
|
||||||
drawStar(canvas, x, y, star.nextFrame());
|
drawStar(canvas, x, y, star.nextFrame());
|
||||||
|
|
|
@ -25,7 +25,7 @@ buildscript {
|
||||||
|
|
||||||
if (enableGoogleVariant) {
|
if (enableGoogleVariant) {
|
||||||
// START Non-FOSS component
|
// 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
|
// END Non-FOSS component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,9 +91,6 @@ android {
|
||||||
signingConfig signingConfigs.twidere
|
signingConfig signingConfigs.twidere
|
||||||
}
|
}
|
||||||
|
|
||||||
multiDexEnabled true
|
|
||||||
minifyEnabled false
|
|
||||||
shrinkResources false
|
|
||||||
resValue("bool", "debug", "true")
|
resValue("bool", "debug", "true")
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
|
@ -101,7 +98,6 @@ android {
|
||||||
signingConfig signingConfigs.twidere
|
signingConfig signingConfigs.twidere
|
||||||
}
|
}
|
||||||
|
|
||||||
multiDexEnabled true
|
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
shrinkResources false
|
shrinkResources false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
@ -115,6 +111,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
encoding = 'UTF-8'
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
@ -145,7 +142,6 @@ android {
|
||||||
exclude 'sdk-version.txt'
|
exclude 'sdk-version.txt'
|
||||||
exclude 'build-data.properties'
|
exclude 'build-data.properties'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task buildTranslationArray {
|
task buildTranslationArray {
|
||||||
|
@ -153,16 +149,16 @@ task buildTranslationArray {
|
||||||
foundLocales.append("new String[]{")
|
foundLocales.append("new String[]{")
|
||||||
|
|
||||||
fileTree("src/main/res-localized").visit { FileVisitDetails details ->
|
fileTree("src/main/res-localized").visit { FileVisitDetails details ->
|
||||||
if(details.file.path.endsWith("strings.xml")){
|
if (details.file.path.endsWith("strings.xml")) {
|
||||||
def languageCode = details.file.parentFile.name.replaceAll('values-','').replaceAll('-r','-')
|
def languageCode = details.file.parentFile.name.replaceAll('values-', '').replaceAll('-r', '-')
|
||||||
languageCode = (languageCode == "values") ? "en" : languageCode;
|
languageCode = (languageCode == "values") ? "en" : languageCode
|
||||||
foundLocales.append("\"").append(languageCode).append("\"").append(",")
|
foundLocales.append("\"").append(languageCode).append("\"").append(",")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foundLocales.append("}")
|
foundLocales.append("}")
|
||||||
//Don't forget to remove the trailing comma
|
//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
|
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 {
|
dependencies {
|
||||||
implementation project(':twidere.component.common')
|
implementation project(':twidere.component.common')
|
||||||
implementation project(':twidere.component.nyan')
|
implementation project(':twidere.component.nyan')
|
||||||
|
|
||||||
/** Kotlin **/
|
/** 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:${libVersions['Kovenant']}"
|
||||||
implementation "nl.komponents.kovenant:kovenant-android:${libVersions['Kovenant']}"
|
implementation "nl.komponents.kovenant:kovenant-android:${libVersions['Kovenant']}"
|
||||||
implementation "nl.komponents.kovenant:kovenant-combine:${libVersions['Kovenant']}"
|
implementation "nl.komponents.kovenant:kovenant-combine:${libVersions['Kovenant']}"
|
||||||
|
@ -189,103 +198,104 @@ dependencies {
|
||||||
|
|
||||||
/** Android support **/
|
/** Android support **/
|
||||||
implementation 'androidx.annotation:annotation:1.1.0'
|
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.browser:browser:1.2.0'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
implementation 'androidx.core:core:1.2.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.drawerlayout:drawerlayout:1.1.0-alpha01'
|
||||||
implementation 'androidx.exifinterface:exifinterface:1.1.0'
|
implementation 'androidx.exifinterface:exifinterface:1.2.0'
|
||||||
implementation "androidx.preference:preference:1.1.1"
|
|
||||||
implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
|
implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
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 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
implementation 'com.google.android.material:material:1.1.0'
|
||||||
implementation "androidx.core:core-ktx:1.2.0"
|
|
||||||
|
|
||||||
|
|
||||||
/** Third-party dependencies **/
|
/** Third-party dependencies **/
|
||||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
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.davemorrissey.labs:subsampling-scale-image-view:3.6.0'
|
||||||
implementation 'com.squareup:otto:1.3.8'
|
implementation 'com.squareup:otto:1.3.8'
|
||||||
implementation 'dnsjava:dnsjava:2.1.8'
|
implementation 'dnsjava:dnsjava:2.1.9'
|
||||||
implementation 'com.commonsware.cwac:layouts:0.4.3'
|
implementation 'com.commonsware.cwac:layouts:0.4.5'
|
||||||
implementation 'com.rengwuxian.materialedittext:library:2.1.4'
|
implementation 'com.rengwuxian.materialedittext:library:2.1.4'
|
||||||
implementation 'com.pnikosis:materialish-progress:1.7'
|
implementation 'com.pnikosis:materialish-progress:1.7'
|
||||||
implementation 'com.github.uucky:ColorPicker-Android:0.9.7@aar'
|
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.sprylab.android.texturevideoview:texturevideoview:1.2.1'
|
||||||
implementation 'com.squareup:pollexor:2.0.4'
|
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-core:${libVersions['Mime4J']}"
|
||||||
implementation "org.apache.james:apache-mime4j-storage:${libVersions['Mime4J']}"
|
implementation "org.apache.james:apache-mime4j-storage:${libVersions['Mime4J']}"
|
||||||
implementation "com.bluelinelabs:logansquare:${libVersions['LoganSquare']}"
|
implementation "com.bluelinelabs:logansquare:${sharedVersions['LoganSquare']}"
|
||||||
kapt "com.bluelinelabs:logansquare-compiler:${libVersions['LoganSquare']}"
|
kapt "com.bluelinelabs:logansquare-compiler:${sharedVersions['LoganSquare']}"
|
||||||
implementation "com.fasterxml.jackson.core:jackson-core:2.7.4"
|
implementation "com.fasterxml.jackson.core:jackson-core:${sharedVersions['Jackson']}"
|
||||||
implementation "com.hannesdorfmann.parcelableplease:annotation:${libVersions['ParcelablePlease']}"
|
implementation "com.hannesdorfmann.parcelableplease:annotation:${sharedVersions['ParcelablePlease']}"
|
||||||
kapt "com.hannesdorfmann.parcelableplease:processor:${libVersions['ParcelablePlease']}"
|
kapt "com.hannesdorfmann.parcelableplease:processor:${sharedVersions['ParcelablePlease']}"
|
||||||
implementation "com.squareup.okhttp3:okhttp:${libVersions['OkHttp']}"
|
implementation 'com.squareup.okhttp3:okhttp:3.12.12'
|
||||||
implementation "com.squareup.okio:okio:2.4.3"
|
implementation 'com.squareup.okio:okio:2.6.0'
|
||||||
implementation 'com.lnikkila:extendedtouchview:0.1.1'
|
implementation 'com.lnikkila:extendedtouchview:0.1.1'
|
||||||
implementation "com.google.dagger:dagger:${libVersions['Dagger']}"
|
implementation "com.google.dagger:dagger:${libVersions['Dagger']}"
|
||||||
kapt "com.google.dagger:dagger-compiler:${libVersions['Dagger']}"
|
kapt "com.google.dagger:dagger-compiler:${libVersions['Dagger']}"
|
||||||
implementation 'org.attoparser:attoparser:2.0.4.RELEASE'
|
implementation 'org.attoparser:attoparser:2.0.5.RELEASE'
|
||||||
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.9.1'
|
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.0'
|
||||||
implementation 'net.ypresto.androidtranscoder:android-transcoder:0.2.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-core:${libVersions['Exoplayer']}"
|
||||||
implementation "com.google.android.exoplayer:exoplayer-ui:${libVersions['Exoplayer']}"
|
implementation "com.google.android.exoplayer:exoplayer-ui:${libVersions['Exoplayer']}"
|
||||||
implementation "com.google.android.exoplayer:extension-okhttp:${libVersions['Exoplayer']}"
|
implementation "com.google.android.exoplayer:extension-okhttp:${libVersions['Exoplayer']}"
|
||||||
implementation "com.github.bumptech.glide:glide:${libVersions['Glide']}"
|
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']}"
|
kapt "com.github.bumptech.glide:compiler:${libVersions['Glide']}"
|
||||||
implementation "jp.wasabeef:glide-transformations:${libVersions['GlideTransformations']}"
|
implementation 'jp.wasabeef:glide-transformations:4.1.0'
|
||||||
implementation "com.theartofdev.edmodo:android-image-cropper:${libVersions['AndroidImageCropper']}"
|
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
|
||||||
|
|
||||||
|
|
||||||
/** Custom dependencies **/
|
/** Custom dependencies **/
|
||||||
|
implementation 'com.github.mariotaku:AbstractTask:0.9.5'
|
||||||
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
||||||
implementation "com.github.mariotaku:MessageBubbleView:${libVersions['MessageBubbleView']}"
|
implementation "com.github.mariotaku.ExportablePreferences:core:${sharedVersions['ExportablePreferences']}"
|
||||||
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
implementation("com.github.mariotaku.CommonsLibrary:emojione-android:${sharedVersions['MariotakuCommons']}") {
|
||||||
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']}") {
|
|
||||||
exclude group: 'org.apache.commons', module: 'commons-text'
|
exclude group: 'org.apache.commons', module: 'commons-text'
|
||||||
}
|
}
|
||||||
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${libVersions['MariotakuCommons']}"
|
implementation "com.github.mariotaku.CommonsLibrary:io:${sharedVersions['MariotakuCommons']}"
|
||||||
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${libVersions['MariotakuCommons']}"
|
implementation "com.github.mariotaku.CommonsLibrary:logansquare:${sharedVersions['MariotakuCommons']}"
|
||||||
implementation "com.github.mariotaku:KPreferences:${libVersions['KPreferences']}"
|
implementation "com.github.mariotaku.CommonsLibrary:objectcursor:${sharedVersions['MariotakuCommons']}"
|
||||||
implementation "com.github.mariotaku.UniqR:android:${libVersions['UniqR']}"
|
implementation "com.github.mariotaku.CommonsLibrary:parcel:${sharedVersions['MariotakuCommons']}"
|
||||||
implementation "com.github.mariotaku:PickNCrop:${libVersions['PickNCrop']}"
|
implementation "com.github.mariotaku.CommonsLibrary:text:${sharedVersions['MariotakuCommons']}"
|
||||||
implementation "com.github.mariotaku.RestFu:library:${libVersions['RestFu']}"
|
implementation "com.github.mariotaku.CommonsLibrary:text-kotlin:${sharedVersions['MariotakuCommons']}"
|
||||||
implementation "com.github.mariotaku.RestFu:oauth:${libVersions['RestFu']}"
|
implementation 'com.github.mariotaku:KPreferences:0.9.8'
|
||||||
implementation "com.github.mariotaku.RestFu:oauth2:${libVersions['RestFu']}"
|
implementation "com.github.mariotaku.MediaViewerLibrary:base:${libVersions['MediaViewerLibrary']}"
|
||||||
implementation "com.github.mariotaku.RestFu:okhttp3:${libVersions['RestFu']}"
|
implementation "com.github.mariotaku.MediaViewerLibrary:subsample-image-view:${libVersions['MediaViewerLibrary']}"
|
||||||
implementation "com.github.mariotaku.RestFu:logansquare:${libVersions['RestFu']}"
|
implementation 'com.github.mariotaku:MessageBubbleView:3.5'
|
||||||
implementation "com.github.Tlaster:Chameleon:${libVersions['Chameleon']}"
|
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 **/
|
/** Flavor dependencies **/
|
||||||
fdroidImplementation "org.osmdroid:osmdroid-android:${libVersions['OSMDroid']}"
|
fdroidImplementation 'org.osmdroid:osmdroid-android:5.6.5'
|
||||||
fdroidImplementation "ch.acra:acra:${libVersions['ACRA']}"
|
fdroidImplementation 'ch.acra:acra:4.11'
|
||||||
|
|
||||||
if (enableGoogleVariant) {
|
if (enableGoogleVariant) {
|
||||||
// START Non-FOSS component
|
// START Non-FOSS component
|
||||||
googleImplementation "com.google.android.gms:play-services-ads:${libVersions['PlayServices']}"
|
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-auth:${libVersions['PlayServices']}"
|
||||||
googleImplementation "com.google.android.gms:play-services-maps:${libVersions['PlayServices']}"
|
googleImplementation "com.google.android.gms:play-services-maps:${libVersions['PlayServices']}"
|
||||||
googleImplementation "com.google.maps.android:android-maps-utils:${libVersions['MapsUtils']}"
|
googleImplementation 'com.google.maps.android:android-maps-utils:0.6.2'
|
||||||
googleImplementation "com.anjlab.android.iab.v3:library:${libVersions['IABv3']}"
|
googleImplementation 'com.anjlab.android.iab.v3:library:1.1.0'
|
||||||
googleImplementation "com.dropbox.core:dropbox-core-sdk:${libVersions['DropboxCoreSdk']}"
|
googleImplementation 'com.dropbox.core:dropbox-core-sdk:3.1.3'
|
||||||
googleImplementation("com.google.apis:google-api-services-drive:${libVersions['GoogleDriveApi']}") {
|
googleImplementation('com.google.apis:google-api-services-drive:v3-rev195-1.25.0') {
|
||||||
exclude group: 'org.apache.httpcomponents'
|
exclude group: 'org.apache.httpcomponents'
|
||||||
}
|
}
|
||||||
implementation 'com.google.guava:guava:28.2-android'
|
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:${libVersions['Stetho']}"
|
||||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:${libVersions['Stetho']}"
|
debugImplementation "com.facebook.stetho:stetho-okhttp3:${libVersions['Stetho']}"
|
||||||
debugImplementation "com.github.mariotaku:StethoBeanShellREPL:${libVersions['StethoBeanShellREPL']}"
|
debugImplementation 'com.github.mariotaku:StethoBeanShellREPL:0.5'
|
||||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:${libVersions['LeakCanary']}"
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
|
||||||
debugImplementation('com.jayway.jsonpath:json-path:2.2.0') {
|
debugImplementation('com.jayway.jsonpath:json-path:2.4.0') {
|
||||||
exclude group: 'net.minidev', module: 'json-smart'
|
exclude group: 'net.minidev', module: 'json-smart'
|
||||||
}
|
}
|
||||||
// Stetho dependency, see https://g.co/androidstudio/app-test-app-conflict
|
// 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)
|
return JsonPath.parse(JsonSerializer.serialize(details), configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Any.prettyPrint() = when {
|
private fun Any.prettyPrint() = when (this) {
|
||||||
this is JSONObject -> toString(4)
|
is JSONObject -> toString(4)
|
||||||
this is JSONArray -> toString(4)
|
is JSONArray -> toString(4)
|
||||||
else -> toString()
|
else -> toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
"auth_type": "oauth",
|
"auth_type": "oauth",
|
||||||
"same_oauth_url": true,
|
"same_oauth_url": true,
|
||||||
"no_version_suffix": false,
|
"no_version_suffix": false,
|
||||||
"consumer_key": "wmtrtTaVOjUnH5pWQp4LDI5Qs",
|
"consumer_key": "MUUBibXUognm6e9vbzrUIqPkt",
|
||||||
"consumer_secret": "E9Q9u2yK0COJae2tLcNEdY75OPA3bxqJiGZQztraHaQUtoI2cu",
|
"consumer_secret": "l2uWAgQkoHvDfM2PrRFx2WN4h7QIUIktmxyeTAqRo6TkGCtNKy",
|
||||||
"sign_up_url": "https://twitter.com/signup"
|
"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_NAME = "Twidere Project";
|
||||||
String TWIDERE_PREVIEW_SCREEN_NAME = "TwidereProject";
|
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_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_TEXT_UNESCAPED = "Twidere is an open source twitter client for Android, see github.com/mariotak…";
|
||||||
String TWIDERE_PREVIEW_SOURCE = "Twidere for Android";
|
String TWIDERE_PREVIEW_SOURCE = "Twidere for Android";
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
|
||||||
* instantiating views.
|
* instantiating views.
|
||||||
*/
|
*/
|
||||||
public ArrayAdapter(Context context, int resource) {
|
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) {
|
public void setPadding(final int left, final int top, final int right, final int bottom) {
|
||||||
mPadding = new Padding() {
|
mPadding = (position, rect) -> {
|
||||||
@Override
|
rect.set(left, top, right, bottom);
|
||||||
public boolean get(int position, Rect rect) {
|
return true;
|
||||||
rect.set(left, top, right, bottom);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,12 +66,9 @@ public final class DataExportImportTypeSelectorDialogFragment extends BaseDialog
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onClick(final DialogInterface dialog, final int which) {
|
public final void onClick(final DialogInterface dialog, final int which) {
|
||||||
switch (which) {
|
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||||
case DialogInterface.BUTTON_POSITIVE: {
|
final int flags = getCheckedFlags();
|
||||||
final int flags = getCheckedFlags();
|
onPositiveButtonClicked(flags);
|
||||||
onPositiveButtonClicked(flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,14 +118,11 @@ public class FileSelectorDialogFragment extends BaseDialogFragment implements Lo
|
||||||
builder.setPositiveButton(android.R.string.ok, this);
|
builder.setPositiveButton(android.R.string.ok, this);
|
||||||
}
|
}
|
||||||
final AlertDialog dialog = builder.create();
|
final AlertDialog dialog = builder.create();
|
||||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
dialog.setOnShowListener(dialog1 -> {
|
||||||
@Override
|
final AlertDialog alertDialog = (AlertDialog) dialog1;
|
||||||
public void onShow(final DialogInterface dialog) {
|
DialogExtensionsKt.applyTheme(alertDialog);
|
||||||
final AlertDialog alertDialog = (AlertDialog) dialog;
|
final ListView listView = alertDialog.getListView();
|
||||||
DialogExtensionsKt.applyTheme(alertDialog);
|
listView.setOnItemClickListener(FileSelectorDialogFragment.this);
|
||||||
final ListView listView = alertDialog.getListView();
|
|
||||||
listView.setOnItemClickListener(FileSelectorDialogFragment.this);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
@ -268,12 +265,9 @@ public class FileSelectorDialogFragment extends BaseDialogFragment implements Lo
|
||||||
private final String[] extensions;
|
private final String[] extensions;
|
||||||
private final Pattern extensions_regex;
|
private final Pattern extensions_regex;
|
||||||
|
|
||||||
private static final Comparator<File> NAME_COMPARATOR = new Comparator<File>() {
|
private static final Comparator<File> NAME_COMPARATOR = (file1, file2) -> {
|
||||||
@Override
|
final Locale loc = Locale.getDefault();
|
||||||
public int compare(final File file1, final File file2) {
|
return file1.getName().toLowerCase(loc).compareTo(file2.getName().toLowerCase(loc));
|
||||||
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) {
|
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;
|
||||||
import android.content.DialogInterface.OnClickListener;
|
import android.content.DialogInterface.OnClickListener;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -66,12 +65,10 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
if (item.getItemId() == R.id.reset) {
|
||||||
case R.id.reset: {
|
final DialogFragment f = new ResetKeyboardShortcutConfirmDialogFragment();
|
||||||
final DialogFragment f = new ResetKeyboardShortcutConfirmDialogFragment();
|
f.show(getFragmentManager(), "reset_keyboard_shortcut_confirm");
|
||||||
f.show(getFragmentManager(), "reset_keyboard_shortcut_confirm");
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
@ -90,12 +87,7 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
||||||
mAction = action;
|
mAction = action;
|
||||||
setPersistent(false);
|
setPersistent(false);
|
||||||
setTitle(KeyboardShortcutsHandler.getActionLabel(context, action));
|
setTitle(KeyboardShortcutsHandler.getActionLabel(context, action));
|
||||||
mPreferencesChangeListener = new OnSharedPreferenceChangeListener() {
|
mPreferencesChangeListener = (preferences, key) -> updateSummary();
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
|
||||||
updateSummary();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
updateSummary();
|
updateSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,8 +95,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
||||||
protected void onClick() {
|
protected void onClick() {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
|
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
|
||||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_CONTEXT_TAG(), mContextTag);
|
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_CONTEXT_TAG, mContextTag);
|
||||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_KEY_ACTION(), mAction);
|
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_KEY_ACTION, mAction);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,11 +124,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
||||||
implements OnClickListener {
|
implements OnClickListener {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
switch (which) {
|
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||||
case DialogInterface.BUTTON_POSITIVE: {
|
keyboardShortcutsHandler.reset();
|
||||||
keyboardShortcutsHandler.reset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,12 +137,7 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
||||||
builder.setPositiveButton(android.R.string.ok, this);
|
builder.setPositiveButton(android.R.string.ok, this);
|
||||||
builder.setNegativeButton(android.R.string.cancel, this);
|
builder.setNegativeButton(android.R.string.cancel, this);
|
||||||
final AlertDialog dialog = builder.create();
|
final AlertDialog dialog = builder.create();
|
||||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
dialog.setOnShowListener(dialog1 -> DialogExtensionsKt.applyTheme((AlertDialog) dialog1));
|
||||||
@Override
|
|
||||||
public void onShow(final DialogInterface dialog) {
|
|
||||||
DialogExtensionsKt.applyTheme((AlertDialog) dialog);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,24 +47,21 @@ public class ThemedListPreferenceDialogFragmentCompat extends ThemedPreferenceDi
|
||||||
}
|
}
|
||||||
mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
|
mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
|
||||||
builder.setSingleChoiceItems(entries, mClickedDialogEntryIndex,
|
builder.setSingleChoiceItems(entries, mClickedDialogEntryIndex,
|
||||||
new DialogInterface.OnClickListener() {
|
(dialog, which) -> {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
mClickedDialogEntryIndex = which;
|
||||||
mClickedDialogEntryIndex = which;
|
/*
|
||||||
/*
|
* Clicking on an item simulates the positive button
|
||||||
* Clicking on an item simulates the positive button
|
* click, and dismisses the dialog.
|
||||||
* click, and dismisses the dialog.
|
*/
|
||||||
*/
|
ThemedListPreferenceDialogFragmentCompat.this.onClick(dialog,
|
||||||
ThemedListPreferenceDialogFragmentCompat.this.onClick(dialog,
|
DialogInterface.BUTTON_POSITIVE);
|
||||||
DialogInterface.BUTTON_POSITIVE);
|
dialog.dismiss();
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
/*
|
/*
|
||||||
* The typical interaction for list-based dialogs is to have
|
* The typical interaction for list-based dialogs is to have
|
||||||
* click-on-an-item dismiss the dialog instead of the user having to
|
* click-on-an-item dismiss the dialog instead of the user having to
|
||||||
* press 'Ok'.
|
* press 'Ok'.
|
||||||
*/
|
*/
|
||||||
//noinspection ConstantConditions
|
|
||||||
builder.setPositiveButton(null, null);
|
builder.setPositiveButton(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,6 @@ public class ObjectCursorLoader<T> extends FixedAsyncTaskLoader<List<T>> {
|
||||||
return new ObjectCursor<>(cursor, indices, mUseCache);
|
return new ObjectCursor<>(cursor, indices, mUseCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("TryWithIdenticalCatches")
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private ObjectCursor.CursorIndices<T> createIndices(final Cursor cursor) {
|
private ObjectCursor.CursorIndices<T> createIndices(final Cursor cursor) {
|
||||||
return ObjectCursor.indicesFrom(cursor, mObjectClass);
|
return ObjectCursor.indicesFrom(cursor, mObjectClass);
|
||||||
|
|
|
@ -447,7 +447,7 @@ public class CronExpression {
|
||||||
if (match) {
|
if (match) {
|
||||||
list.add(str.substring(start, i));
|
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) {
|
public static DrawableHolder parse(String str) {
|
||||||
DrawableHolder icon = builtin(str);
|
return builtin(str);
|
||||||
if (icon != null) {
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<DrawableHolder> builtins() {
|
public static List<DrawableHolder> builtins() {
|
||||||
|
|
|
@ -100,12 +100,7 @@ abstract class MultiSelectListPreference extends DialogPreference implements IDi
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
builder.setNegativeButton(android.R.string.cancel, null);
|
||||||
builder.setMultiChoiceItems(mNames, mValues, this);
|
builder.setMultiChoiceItems(mNames, mValues, this);
|
||||||
final AlertDialog dialog = builder.create();
|
final AlertDialog dialog = builder.create();
|
||||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
dialog.setOnShowListener(dialog1 -> DialogExtensionsKt.applyTheme((AlertDialog) dialog1));
|
||||||
@Override
|
|
||||||
public void onShow(final DialogInterface dialog) {
|
|
||||||
DialogExtensionsKt.applyTheme((AlertDialog) dialog);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ package org.mariotaku.twidere.preference;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -78,19 +77,9 @@ public class SettingsImportExportPreference extends DialogPreference implements
|
||||||
entries[1] = context.getString(R.string.export_settings);
|
entries[1] = context.getString(R.string.export_settings);
|
||||||
values[0] = new Intent(context, DataImportActivity.class);
|
values[0] = new Intent(context, DataImportActivity.class);
|
||||||
values[1] = new Intent(context, DataExportActivity.class);
|
values[1] = new Intent(context, DataExportActivity.class);
|
||||||
builder.setItems(entries, new DialogInterface.OnClickListener() {
|
builder.setItems(entries, (dialog, which) -> startActivity(values[which]));
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
startActivity(values[which]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
final AlertDialog dialog = builder.create();
|
final AlertDialog dialog = builder.create();
|
||||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
dialog.setOnShowListener(dialog1 -> DialogExtensionsKt.applyTheme((AlertDialog) dialog1));
|
||||||
@Override
|
|
||||||
public void onShow(final DialogInterface dialog) {
|
|
||||||
DialogExtensionsKt.applyTheme((AlertDialog) dialog);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ package org.mariotaku.twidere.preference;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.DialogInterface.OnClickListener;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -17,7 +15,6 @@ import android.util.AttributeSet;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
|
|
||||||
|
@ -160,42 +157,33 @@ public class ThemeBackgroundPreference extends DialogPreference implements Const
|
||||||
final SharedPreferences preferences = preference.getSharedPreferences();
|
final SharedPreferences preferences = preference.getSharedPreferences();
|
||||||
preference.setValue(preference.getPersistedString(null));
|
preference.setValue(preference.getPersistedString(null));
|
||||||
builder.setTitle(preference.getDialogTitle());
|
builder.setTitle(preference.getDialogTitle());
|
||||||
builder.setSingleChoiceItems(preference.mBackgroundEntries, preference.getValueIndex(), new OnClickListener() {
|
builder.setSingleChoiceItems(preference.mBackgroundEntries, preference.getValueIndex(), (dialog, which) -> {
|
||||||
@Override
|
preference.setSelectedOption(which);
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
updateAlphaVisibility();
|
||||||
preference.setSelectedOption(which);
|
|
||||||
updateAlphaVisibility();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
builder.setPositiveButton(android.R.string.ok, this);
|
builder.setPositiveButton(android.R.string.ok, this);
|
||||||
builder.setNegativeButton(android.R.string.cancel, this);
|
builder.setNegativeButton(android.R.string.cancel, this);
|
||||||
final Dialog dialog = builder.create();
|
final Dialog dialog = builder.create();
|
||||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
dialog.setOnShowListener(dialog1 -> {
|
||||||
@Override
|
final AlertDialog alertDialog = (AlertDialog) dialog1;
|
||||||
public void onShow(DialogInterface dialog) {
|
DialogExtensionsKt.applyTheme(alertDialog);
|
||||||
final AlertDialog alertDialog = (AlertDialog) dialog;
|
if (preferences != null) {
|
||||||
DialogExtensionsKt.applyTheme(alertDialog);
|
final LayoutInflater inflater = alertDialog.getLayoutInflater();
|
||||||
if (preferences != null) {
|
final ListView listView = alertDialog.getListView();
|
||||||
final LayoutInflater inflater = alertDialog.getLayoutInflater();
|
assert listView != null;
|
||||||
final ListView listView = alertDialog.getListView();
|
final ViewGroup listViewParent = (ViewGroup) listView.getParent();
|
||||||
assert listView != null;
|
listViewParent.removeView(listView);
|
||||||
final ViewGroup listViewParent = (ViewGroup) listView.getParent();
|
final View view = inflater.inflate(R.layout.dialog_theme_background_preference, listViewParent);
|
||||||
listViewParent.removeView(listView);
|
((ViewGroup) view.findViewById(R.id.list_container)).addView(listView);
|
||||||
final View view = inflater.inflate(R.layout.dialog_theme_background_preference, listViewParent);
|
mAlphaContainer = view.findViewById(R.id.alpha_container);
|
||||||
((ViewGroup) view.findViewById(R.id.list_container)).addView(listView);
|
mAlphaSlider = view.findViewById(R.id.alpha_slider);
|
||||||
mAlphaContainer = view.findViewById(R.id.alpha_container);
|
mAlphaSlider.setMax(MAX_ALPHA - MIN_ALPHA);
|
||||||
mAlphaSlider = view.findViewById(R.id.alpha_slider);
|
mAlphaSlider.setProgress(preferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA) - MIN_ALPHA);
|
||||||
mAlphaSlider.setMax(MAX_ALPHA - MIN_ALPHA);
|
listView.setOnItemClickListener((parent, view1, position, id) -> {
|
||||||
mAlphaSlider.setProgress(preferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA) - MIN_ALPHA);
|
preference.setSelectedOption(position);
|
||||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
preference.setSelectedOption(position);
|
|
||||||
updateAlphaVisibility();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
updateAlphaVisibility();
|
updateAlphaVisibility();
|
||||||
}
|
});
|
||||||
|
updateAlphaVisibility();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return dialog;
|
return dialog;
|
||||||
|
|
|
@ -31,7 +31,6 @@ import androidx.annotation.Nullable;
|
||||||
import org.mariotaku.twidere.constant.IntentConstants;
|
import org.mariotaku.twidere.constant.IntentConstants;
|
||||||
import org.mariotaku.twidere.util.ServiceUtils.ServiceToken;
|
import org.mariotaku.twidere.util.ServiceUtils.ServiceToken;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.FutureTask;
|
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 Intent intent = new Intent(IntentConstants.INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
||||||
final ComponentName component = ComponentName.unflattenFromString(mShortenerName);
|
final ComponentName component = ComponentName.unflattenFromString(mShortenerName);
|
||||||
intent.setComponent(component);
|
intent.setComponent(component);
|
||||||
final FutureTask<Boolean> futureTask = new FutureTask<>(new Callable<Boolean>() {
|
final FutureTask<Boolean> futureTask = new FutureTask<>(() -> mIInterface != null);
|
||||||
@Override
|
|
||||||
public Boolean call() throws Exception {
|
|
||||||
return mIInterface != null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mToken = ServiceUtils.bindToService(mContext, intent, new ServiceConnection() {
|
mToken = ServiceUtils.bindToService(mContext, intent, new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(final ComponentName name, final IBinder obj) {
|
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 {
|
public interface CheckServiceAction {
|
||||||
@SuppressWarnings("RedundantThrows")
|
|
||||||
void check(@Nullable Bundle metaData) throws CheckServiceException;
|
void check(@Nullable Bundle metaData) throws CheckServiceException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
@ -169,7 +170,7 @@ public class DataImportExportUtils implements Constants {
|
||||||
ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
|
ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
List<String> entryNames = new ArrayList<>();
|
List<String> entryNames = new ArrayList<>();
|
||||||
ZipEntry entry = null;
|
ZipEntry entry;
|
||||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||||
entryNames.add(entry.getName());
|
entryNames.add(entry.getName());
|
||||||
}
|
}
|
||||||
|
@ -203,11 +204,11 @@ public class DataImportExportUtils implements Constants {
|
||||||
try (InputStream inputStream = context.getContentResolver().openInputStream(src.getUri());
|
try (InputStream inputStream = context.getContentResolver().openInputStream(src.getUri());
|
||||||
ZipInputStream zipInputStream = new ZipInputStream(inputStream)
|
ZipInputStream zipInputStream = new ZipInputStream(inputStream)
|
||||||
) {
|
) {
|
||||||
ZipEntry entry = null;
|
ZipEntry entry;
|
||||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int read = 0;
|
int read;
|
||||||
while ((read = zipInputStream.read(buffer, 0, 1024)) >= 0) {
|
while ((read = zipInputStream.read(buffer, 0, 1024)) >= 0) {
|
||||||
stringBuilder.append(new String(buffer, 0, read));
|
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 String preferencesName, @NonNull final String entryName,
|
||||||
@NonNull final SharedPreferencesProcessStrategy strategy,
|
@NonNull final SharedPreferencesProcessStrategy strategy,
|
||||||
@NonNull final String data) throws IOException {
|
@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);
|
final JsonParser jsonParser = LoganSquare.JSON_FACTORY.createParser(data);
|
||||||
if (jsonParser.getCurrentToken() == null) {
|
if (jsonParser.getCurrentToken() == null) {
|
||||||
jsonParser.nextToken();
|
jsonParser.nextToken();
|
||||||
|
@ -327,7 +336,15 @@ public class DataImportExportUtils implements Constants {
|
||||||
@NonNull final String data,
|
@NonNull final String data,
|
||||||
@NonNull final ContentResolverProcessStrategy<List<T>> strategy)
|
@NonNull final ContentResolverProcessStrategy<List<T>> strategy)
|
||||||
throws IOException {
|
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);
|
List<T> itemsList = JsonSerializer.parseList(data, itemCls);
|
||||||
strategy.importItem(context.getContentResolver(), itemsList);
|
strategy.importItem(context.getContentResolver(), itemsList);
|
||||||
}
|
}
|
||||||
|
@ -352,7 +369,15 @@ public class DataImportExportUtils implements Constants {
|
||||||
@NonNull final String data,
|
@NonNull final String data,
|
||||||
@NonNull final ContentResolverProcessStrategy<T> strategy)
|
@NonNull final ContentResolverProcessStrategy<T> strategy)
|
||||||
throws IOException {
|
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);
|
T item = JsonSerializer.parse(data, itemCls);
|
||||||
strategy.importItem(context.getContentResolver(), item);
|
strategy.importItem(context.getContentResolver(), item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class MouseScrollDirectionDecider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ViewConstructor")
|
@SuppressLint("ViewConstructor")
|
||||||
private class InternalHorizontalScrollView extends HorizontalScrollView {
|
private static class InternalHorizontalScrollView extends HorizontalScrollView {
|
||||||
|
|
||||||
private final int factor;
|
private final int factor;
|
||||||
private final MouseScrollDirectionDecider decider;
|
private final MouseScrollDirectionDecider decider;
|
||||||
|
|
|
@ -133,7 +133,7 @@ public class MultiSelectManager {
|
||||||
userKeys.add(((ParcelableStatus) item).user_key);
|
userKeys.add(((ParcelableStatus) item).user_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return userKeys.toArray(new UserKey[userKeys.size()]);
|
return userKeys.toArray(new UserKey[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class NotificationManagerWrapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PostedNotification {
|
private static class PostedNotification {
|
||||||
private final String tag;
|
private final String tag;
|
||||||
private final int id;
|
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) {
|
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
|
||||||
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
|
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
|
||||||
if (action == null) return false;
|
if (action == null) return false;
|
||||||
switch (action) {
|
if (ACTION_NAVIGATION_TOP.equals(action)) {
|
||||||
case ACTION_NAVIGATION_TOP: {
|
if (iface != null) {
|
||||||
if (iface != null) {
|
iface.scrollToStart();
|
||||||
iface.scrollToStart();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -325,7 +325,7 @@ public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PendingDismissData implements Comparable<PendingDismissData> {
|
static class PendingDismissData implements Comparable<PendingDismissData> {
|
||||||
public int position;
|
public int position;
|
||||||
public View view;
|
public View view;
|
||||||
|
|
||||||
|
@ -391,12 +391,9 @@ public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
animator.addUpdateListener(valueAnimator -> {
|
||||||
@Override
|
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
dismissView.setLayoutParams(lp);
|
||||||
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
|
||||||
dismissView.setLayoutParams(lp);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
mPendingDismisses.add(new PendingDismissData(dismissPosition, dismissView));
|
mPendingDismisses.add(new PendingDismissData(dismissPosition, dismissView));
|
||||||
|
|
|
@ -25,6 +25,7 @@ package org.mariotaku.twidere.util.collection;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -253,8 +254,7 @@ public class CompactHashSet<E> extends java.util.AbstractSet<E> {
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
elements = 0;
|
elements = 0;
|
||||||
for (int ix = 0; ix < objects.length; ix++)
|
Arrays.fill(objects, null);
|
||||||
objects[ix] = null;
|
|
||||||
freecells = objects.length;
|
freecells = objects.length;
|
||||||
modCount++;
|
modCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class ContentResolverUtils {
|
||||||
|
|
||||||
public static int bulkInsert(@NonNull final ContentResolver resolver, @NonNull final Uri uri,
|
public static int bulkInsert(@NonNull final ContentResolver resolver, @NonNull final Uri uri,
|
||||||
@NonNull final Collection<ContentValues> values) {
|
@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,
|
public static int bulkInsert(@NonNull final ContentResolver resolver, @NonNull final Uri uri,
|
||||||
|
|
|
@ -107,7 +107,7 @@ public final class DatabaseUpgradeHelper {
|
||||||
newInsertColsList.add(newCol);
|
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;
|
if (!TwidereArrayUtils.contains(newInsertCols, notNullCols)) return null;
|
||||||
qb.columns(newInsertCols);
|
qb.columns(newInsertCols);
|
||||||
final Columns.Column[] oldDataCols = new Columns.Column[newInsertCols.length];
|
final Columns.Column[] oldDataCols = new Columns.Column[newInsertCols.length];
|
||||||
|
|
|
@ -15,12 +15,7 @@ public class ImgurProvider implements Provider {
|
||||||
public boolean supports(@NonNull String link) {
|
public boolean supports(@NonNull String link) {
|
||||||
final String authority = UriUtils.getAuthority(link);
|
final String authority = UriUtils.getAuthority(link);
|
||||||
if (authority == null) return false;
|
if (authority == null) return false;
|
||||||
switch (authority) {
|
return "i.imgur.com".equals(authority);
|
||||||
case "i.imgur.com":
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -28,13 +23,11 @@ public class ImgurProvider implements Provider {
|
||||||
public ParcelableMedia from(@NonNull String url) {
|
public ParcelableMedia from(@NonNull String url) {
|
||||||
final String authority = UriUtils.getAuthority(url);
|
final String authority = UriUtils.getAuthority(url);
|
||||||
if (authority == null) return null;
|
if (authority == null) return null;
|
||||||
switch (authority) {
|
if ("i.imgur.com".equals(authority)) {
|
||||||
case "i.imgur.com": {
|
final String path = UriUtils.getPath(url);
|
||||||
final String path = UriUtils.getPath(url);
|
if (path == null) return null;
|
||||||
if (path == null) return null;
|
ParcelableMedia media = new ParcelableMedia();
|
||||||
ParcelableMedia media = new ParcelableMedia();
|
media.url = url;
|
||||||
media.url = url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,8 @@ public final class ViewSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static void setBackground(final View view, final Drawable background) {
|
public static void setBackground(final View view, final Drawable background) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
|
ViewAccessorJB.setBackground(view, background);
|
||||||
view.setBackgroundDrawable(background);
|
|
||||||
} else {
|
|
||||||
ViewAccessorJB.setBackground(view, background);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setButtonTintList(CompoundButton view, ColorStateList list) {
|
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 (cls.isAssignableFrom(view.getClass())) return (T) view;
|
||||||
if (view instanceof ViewGroup) {
|
if (view instanceof ViewGroup) {
|
||||||
for (int i = 0, j = ((ViewGroup) view).getChildCount(); i < j; i++) {
|
for (int i = 0, j = ((ViewGroup) view).getChildCount(); i < j; i++) {
|
||||||
final View found = findViewByType(((ViewGroup) view).getChildAt(i), cls);
|
final T found = findViewByType(((ViewGroup) view).getChildAt(i), cls);
|
||||||
if (found != null) return (T) found;
|
if (found != null) return found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -130,7 +125,6 @@ public final class ViewSupport {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setBackground(final View view, final Drawable background) {
|
static void setBackground(final View view, final Drawable background) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
|
|
||||||
view.setBackground(background);
|
view.setBackground(background);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,10 +136,8 @@ public final class ViewSupport {
|
||||||
|
|
||||||
static void setForeground(final View view, final Drawable foreground) {
|
static void setForeground(final View view, final Drawable foreground) {
|
||||||
if (view instanceof FrameLayout) {
|
if (view instanceof FrameLayout) {
|
||||||
//noinspection RedundantCast
|
|
||||||
((FrameLayout) view).setForeground(foreground);
|
((FrameLayout) view).setForeground(foreground);
|
||||||
} else if (view instanceof IForegroundView) {
|
} else if (view instanceof IForegroundView) {
|
||||||
//noinspection RedundantCast
|
|
||||||
((IForegroundView) view).setForeground(foreground);
|
((IForegroundView) view).setForeground(foreground);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,14 +29,12 @@ public class WebSettingsSupport {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setAllowUniversalAccessFromFileURLs(final WebSettings settings, final boolean flag) {
|
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);
|
WebSettingsAccessorSDK16.setAllowUniversalAccessFromFileURLs(settings, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||||
private static class WebSettingsAccessorSDK16 {
|
private static class WebSettingsAccessorSDK16 {
|
||||||
private static void setAllowUniversalAccessFromFileURLs(final WebSettings settings, final boolean flag) {
|
private static void setAllowUniversalAccessFromFileURLs(final WebSettings settings, final boolean flag) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
|
|
||||||
settings.setAllowUniversalAccessFromFileURLs(flag);
|
settings.setAllowUniversalAccessFromFileURLs(flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,6 @@ public final class BirthdayView extends LayeredCanvasView {
|
||||||
((AnimatedBitmapLayer) layers[2]).setScale(Math.max(1, w / 160));
|
((AnimatedBitmapLayer) layers[2]).setScale(Math.max(1, w / 160));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
||||||
final int stripTop = Utils.INSTANCE.getInsetsTopWithoutActionBarHeight(getContext(), insets.top);
|
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 (dy > 0 && mDrawer.canScrollCallback(-dy) && mDrawer.isTouchingScrollableContent()) {
|
||||||
if (!mDrawer.isUsingDragHelper()) {
|
if (!mDrawer.isUsingDragHelper()) {
|
||||||
// Scrolling up while list still has space to scroll, so make header still
|
// Scrolling up while list still has space to scroll, so make header still
|
||||||
mScrollingHeaderByHelper = false;
|
|
||||||
return current;
|
|
||||||
} else {
|
} else {
|
||||||
mDrawer.scrollByCallback(-dy);
|
mDrawer.scrollByCallback(-dy);
|
||||||
mScrollingHeaderByHelper = false;
|
|
||||||
return current;
|
|
||||||
}
|
}
|
||||||
|
mScrollingHeaderByHelper = false;
|
||||||
|
return current;
|
||||||
}
|
}
|
||||||
final int min = mDrawer.getHeaderTopMinimum(), max = mDrawer.getHeaderTopMaximum();
|
final int min = mDrawer.getHeaderTopMinimum(), max = mDrawer.getHeaderTopMaximum();
|
||||||
if (top < min && mDrawer.isTouchingScrollableContent() && mDrawer.isUsingDragHelper()) {
|
if (top < min && mDrawer.isTouchingScrollableContent() && mDrawer.isUsingDragHelper()) {
|
||||||
|
|
|
@ -196,17 +196,14 @@ public class ShapedImageView extends AppCompatImageView {
|
||||||
contentHeight = contentBottom - contentTop;
|
contentHeight = contentBottom - contentTop;
|
||||||
final int size = Math.min(contentWidth, contentHeight);
|
final int size = Math.min(contentWidth, contentHeight);
|
||||||
|
|
||||||
if (OUTLINE_DRAW) {
|
if (!OUTLINE_DRAW) {
|
||||||
drawShape(canvas, mDestination, 0, mBackgroundPaint);
|
|
||||||
super.onDraw(canvas);
|
|
||||||
} else {
|
|
||||||
if (mShadowBitmap != null && mDrawShadow) {
|
if (mShadowBitmap != null && mDrawShadow) {
|
||||||
canvas.drawBitmap(mShadowBitmap, contentLeft + (contentWidth - size) / 2 - mShadowRadius,
|
canvas.drawBitmap(mShadowBitmap, contentLeft + (contentWidth - size) / 2 - mShadowRadius,
|
||||||
contentTop + (contentHeight - size) / 2 - mShadowRadius, null);
|
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.
|
// Then draw the border.
|
||||||
if (mBorderEnabled) {
|
if (mBorderEnabled) {
|
||||||
drawBorder(canvas, mDestination);
|
drawBorder(canvas, mDestination);
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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;
|
package org.oshkimaadziig.george.androidutils;
|
||||||
|
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
|
@ -33,7 +35,6 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
* @author George T. Steel
|
* @author George T. Steel
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("IfCanBeSwitch")
|
|
||||||
public class SpanFormatter {
|
public class SpanFormatter {
|
||||||
public static final Pattern FORMAT_SEQUENCE = Pattern.compile("%([0-9]+\\$|<?)([^a-zA-z%]*)([[a-zA-Z%]&&[^tT]]|[tT][a-zA-Z])");
|
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("%")) {
|
if (typeTerm.equals("%")) {
|
||||||
cookedArg = "%";
|
cookedArg = "%";
|
||||||
} else if (typeTerm.equals("%")) {
|
} else if (typeTerm.equals("n")) {
|
||||||
cookedArg = "\n";
|
cookedArg = "\n";
|
||||||
} else {
|
} else {
|
||||||
int argIdx = 0;
|
int argIdx;
|
||||||
if (argTerm.equals("")) argIdx = ++argAt;
|
if (argTerm.equals("")) argIdx = ++argAt;
|
||||||
else if (argTerm.equals("<")) argIdx = argAt;
|
else if (argTerm.equals("<")) argIdx = argAt;
|
||||||
else argIdx = Integer.parseInt(argTerm.substring(0, argTerm.length() - 1)) - 1;
|
else argIdx = Integer.parseInt(argTerm.substring(0, argTerm.length() - 1)) - 1;
|
||||||
|
|
|
@ -25,26 +25,38 @@ import java.util.*
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
object LocaleHelperAccessor {
|
object LocaleHelperAccessor {
|
||||||
fun forLanguageTag(str: String): Locale {
|
fun forLanguageTag(str: String): Locale {
|
||||||
if (str.contains("-")) {
|
when {
|
||||||
val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray()
|
str.contains("-") -> {
|
||||||
if (args.size > 2) {
|
val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
return Locale(args[0], args[1], args[2])
|
when {
|
||||||
} else if (args.size > 1) {
|
args.size > 2 -> {
|
||||||
return Locale(args[0], args[1])
|
return Locale(args[0], args[1], args[2])
|
||||||
} else if (args.size == 1) {
|
}
|
||||||
return Locale(args[0])
|
args.size > 1 -> {
|
||||||
|
return Locale(args[0], args[1])
|
||||||
|
}
|
||||||
|
args.size == 1 -> {
|
||||||
|
return Locale(args[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (str.contains("_")) {
|
str.contains("_") -> {
|
||||||
val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray()
|
val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
if (args.size > 2) {
|
when {
|
||||||
return Locale(args[0], args[1], args[2])
|
args.size > 2 -> {
|
||||||
} else if (args.size > 1) {
|
return Locale(args[0], args[1], args[2])
|
||||||
return Locale(args[0], args[1])
|
}
|
||||||
} else if (args.size == 1) {
|
args.size > 1 -> {
|
||||||
return Locale(args[0])
|
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]")
|
throw IllegalArgumentException("Can not parse language tag: [$str]")
|
||||||
|
|
|
@ -19,8 +19,12 @@
|
||||||
|
|
||||||
package androidx.core.view
|
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?
|
val WindowInsetsCompat.unwrapped: Any?
|
||||||
@Suppress("RestrictedApi")
|
|
||||||
get() = this.toWindowInsets()
|
get() = this.toWindowInsets()
|
|
@ -1,8 +1,5 @@
|
||||||
package androidx.loader.app
|
package androidx.loader.app
|
||||||
|
|
||||||
import androidx.loader.app.LoaderManager
|
|
||||||
import androidx.loader.app.LoaderManagerImpl
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 2016/11/26.
|
* Created by mariotaku on 2016/11/26.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,7 +2,6 @@ package androidx.loader.content
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.AsyncTask
|
import android.os.AsyncTask
|
||||||
import androidx.loader.content.AsyncTaskLoader
|
|
||||||
import org.mariotaku.twidere.extension.set
|
import org.mariotaku.twidere.extension.set
|
||||||
import org.mariotaku.twidere.util.Analyzer
|
import org.mariotaku.twidere.util.Analyzer
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,4 @@
|
||||||
|
|
||||||
package androidx.recyclerview.widget
|
package androidx.recyclerview.widget
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
|
|
||||||
val RecyclerView.LayoutManager.recyclerView: RecyclerView? get() = mRecyclerView
|
val RecyclerView.LayoutManager.recyclerView: RecyclerView? get() = mRecyclerView
|
||||||
|
|
|
@ -10,23 +10,23 @@ import android.os.Handler
|
||||||
|
|
||||||
fun AccountManager.addOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener,
|
fun AccountManager.addOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener,
|
||||||
handler: Handler? = null, updateImmediately: Boolean = false): Boolean {
|
handler: Handler? = null, updateImmediately: Boolean = false): Boolean {
|
||||||
try {
|
return try {
|
||||||
this.addOnAccountsUpdatedListener(listener, handler, updateImmediately)
|
this.addOnAccountsUpdatedListener(listener, handler, updateImmediately)
|
||||||
return true
|
true
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
return false
|
false
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AccountManager.removeOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener): Boolean {
|
fun AccountManager.removeOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener): Boolean {
|
||||||
try {
|
return try {
|
||||||
this.removeOnAccountsUpdatedListener(listener)
|
this.removeOnAccountsUpdatedListener(listener)
|
||||||
return true
|
true
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
return false
|
false
|
||||||
} catch (e: IllegalArgumentException) {
|
} 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 {
|
fun <T> MutableCollection<T>.addAllEnhanced(collection: Collection<T>, ignoreDuplicates: Boolean): Boolean {
|
||||||
if (ignoreDuplicates) {
|
return if (ignoreDuplicates) {
|
||||||
return addAll(collection.filter { it !in this })
|
addAll(collection.filter { it !in this })
|
||||||
} else {
|
} 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> {
|
inline fun <reified T> List<T>.subArray(range: IntRange): Array<T> {
|
||||||
return Array(range.count()) {
|
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 {
|
fun Context.unregisterReceiverSafe(receiver: BroadcastReceiver?): Boolean {
|
||||||
if (receiver == null) return false
|
if (receiver == null) return false
|
||||||
try {
|
return try {
|
||||||
unregisterReceiver(receiver)
|
unregisterReceiver(receiver)
|
||||||
return true
|
true
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ fun Cursor.safeGetInt(columnIndex: Int, def: Int = -1) = try {
|
||||||
def
|
def
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Cursor.safeGetString(columnIndex: Int, def: String = "") = try {
|
fun Cursor.safeGetString(columnIndex: Int, def: String = ""): String = try {
|
||||||
getString(columnIndex)
|
getString(columnIndex)
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
def
|
def
|
||||||
|
|
|
@ -58,10 +58,10 @@ val Locale.bcp47Tag: String
|
||||||
}
|
}
|
||||||
|
|
||||||
val bcp47Tag = StringBuilder(language)
|
val bcp47Tag = StringBuilder(language)
|
||||||
if (!country.isEmpty()) {
|
if (country.isNotEmpty()) {
|
||||||
bcp47Tag.append(SEP).append(country)
|
bcp47Tag.append(SEP).append(country)
|
||||||
}
|
}
|
||||||
if (!variant.isEmpty()) {
|
if (variant.isNotEmpty()) {
|
||||||
bcp47Tag.append(SEP).append(variant)
|
bcp47Tag.append(SEP).append(variant)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ fun Number.toLocalizedString(locale: Locale = Locale.getDefault()): String {
|
||||||
val Int.nextPowerOf2: Int
|
val Int.nextPowerOf2: Int
|
||||||
get() {
|
get() {
|
||||||
var n = this
|
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 -= 1
|
||||||
n = n or (n shr 16)
|
n = n or (n shr 16)
|
||||||
n = n or (n shr 8)
|
n = n or (n shr 8)
|
||||||
|
|
|
@ -6,5 +6,5 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
* Created by mariotaku on 16/8/21.
|
* Created by mariotaku on 16/8/21.
|
||||||
*/
|
*/
|
||||||
fun RecyclerView.Adapter<*>.findPositionByItemId(itemId: Long): Int {
|
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 {
|
fun InputStream.expectBytes(bytes: ByteArray): Boolean {
|
||||||
val readBytes = ByteArray(bytes.size)
|
val readBytes = ByteArray(bytes.size)
|
||||||
read(readBytes)
|
read(readBytes)
|
||||||
return Arrays.equals(readBytes, bytes)
|
return readBytes.contentEquals(bytes)
|
||||||
}
|
}
|
|
@ -35,20 +35,24 @@ object InternalActivityCreator {
|
||||||
activity.maxSortPosition = activity.minSortPosition
|
activity.maxSortPosition = activity.minSortPosition
|
||||||
activity.createdAt = status.getCreatedAt()
|
activity.createdAt = status.getCreatedAt()
|
||||||
|
|
||||||
if (status.getInReplyToUserId() == accountId) {
|
when {
|
||||||
activity.action = Activity.Action.REPLY
|
status.getInReplyToUserId() == accountId -> {
|
||||||
activity.targetStatuses = arrayOf(status)
|
activity.action = Activity.Action.REPLY
|
||||||
|
activity.targetStatuses = arrayOf(status)
|
||||||
|
|
||||||
//TODO set target statuses (in reply to status)
|
//TODO set target statuses (in reply to status)
|
||||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||||
} else if (status.quotedStatus?.user?.id == accountId) {
|
}
|
||||||
activity.action = Activity.Action.QUOTE
|
status.quotedStatus?.user?.id == accountId -> {
|
||||||
activity.targetStatuses = arrayOf(status)
|
activity.action = Activity.Action.QUOTE
|
||||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
activity.targetStatuses = arrayOf(status)
|
||||||
} else {
|
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||||
activity.action = Activity.Action.MENTION
|
}
|
||||||
activity.targetUsers = arrayOfNulls<User>(0)
|
else -> {
|
||||||
activity.targetObjectStatuses = arrayOf(status)
|
activity.action = Activity.Action.MENTION
|
||||||
|
activity.targetUsers = arrayOfNulls<User>(0)
|
||||||
|
activity.targetObjectStatuses = arrayOf(status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activity.sourcesSize = 1
|
activity.sourcesSize = 1
|
||||||
activity.sources = arrayOf(status.getUser())
|
activity.sources = arrayOf(status.getUser())
|
||||||
|
|
|
@ -34,7 +34,6 @@ import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.TwidereConstants.*
|
import org.mariotaku.twidere.TwidereConstants.*
|
||||||
import org.mariotaku.twidere.adapter.AccountDetailsAdapter
|
import org.mariotaku.twidere.adapter.AccountDetailsAdapter
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.app.TwidereApplication
|
|
||||||
import org.mariotaku.twidere.extension.model.isOAuth
|
import org.mariotaku.twidere.extension.model.isOAuth
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
|
|
|
@ -13,8 +13,7 @@ class AssistLauncherActivity : Activity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val prefs = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
|
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 (prefs.getString(KEY_COMPOSE_NOW_ACTION, VALUE_COMPOSE_NOW_ACTION_COMPOSE)) {
|
||||||
val action = when (composeNowAction) {
|
|
||||||
VALUE_COMPOSE_NOW_ACTION_TAKE_PHOTO -> INTENT_ACTION_COMPOSE_TAKE_PHOTO
|
VALUE_COMPOSE_NOW_ACTION_TAKE_PHOTO -> INTENT_ACTION_COMPOSE_TAKE_PHOTO
|
||||||
VALUE_COMPOSE_NOW_ACTION_PICK_IMAGE -> INTENT_ACTION_COMPOSE_PICK_IMAGE
|
VALUE_COMPOSE_NOW_ACTION_PICK_IMAGE -> INTENT_ACTION_COMPOSE_PICK_IMAGE
|
||||||
else -> INTENT_ACTION_COMPOSE
|
else -> INTENT_ACTION_COMPOSE
|
||||||
|
|
|
@ -27,22 +27,22 @@ import android.graphics.Rect
|
||||||
import android.nfc.NfcAdapter
|
import android.nfc.NfcAdapter
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
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.util.AttributeSet
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
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.Glide
|
||||||
import com.bumptech.glide.RequestManager
|
import com.bumptech.glide.RequestManager
|
||||||
import com.squareup.otto.Bus
|
import com.squareup.otto.Bus
|
||||||
|
@ -300,7 +300,7 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
|
||||||
for (i in 0 until handlerFilter.countDataAuthorities()) {
|
for (i in 0 until handlerFilter.countDataAuthorities()) {
|
||||||
val authorityEntry = handlerFilter.getDataAuthority(i)
|
val authorityEntry = handlerFilter.getDataAuthority(i)
|
||||||
val port = authorityEntry.port
|
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 {
|
try {
|
||||||
adapter.enableForegroundDispatch(this, intent, arrayOf(intentFilter), null)
|
adapter.enableForegroundDispatch(this, intent, arrayOf(intentFilter), null)
|
||||||
|
@ -363,7 +363,11 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
|
||||||
super.attachBaseContext(newBase)
|
super.attachBaseContext(newBase)
|
||||||
return
|
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> {
|
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? {
|
private fun newInstance(name: String, context: Context, attrs: AttributeSet): View? {
|
||||||
try {
|
return try {
|
||||||
val cls = findClass(name) ?: throw ClassNotFoundException(name)
|
val cls = findClass(name) ?: throw ClassNotFoundException(name)
|
||||||
val constructor = cls.getConstructor(Context::class.java, AttributeSet::class.java)
|
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) {
|
} catch (e: InstantiationException) {
|
||||||
return null
|
null
|
||||||
} catch (e: IllegalAccessException) {
|
} catch (e: IllegalAccessException) {
|
||||||
return null
|
null
|
||||||
} catch (e: InvocationTargetException) {
|
} catch (e: InvocationTargetException) {
|
||||||
return null
|
null
|
||||||
} catch (e: NoSuchMethodException) {
|
} catch (e: NoSuchMethodException) {
|
||||||
return null
|
null
|
||||||
} catch (e: ClassNotFoundException) {
|
} catch (e: ClassNotFoundException) {
|
||||||
return null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ class ColorPickerDialogActivity : BaseActivity(), Callback {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val RESULT_CLEARED = -2
|
const val RESULT_CLEARED = -2
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,7 @@ import java.text.Normalizer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.math.abs
|
||||||
import android.Manifest.permission as AndroidPermission
|
import android.Manifest.permission as AndroidPermission
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
|
@ -389,11 +390,15 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> {
|
REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
val src = MediaPickerActivity.getMediaUris(data)
|
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)
|
val extras = data.getBundleExtra(MediaPickerActivity.EXTRA_EXTRAS)
|
||||||
if (extras?.getBoolean(EXTRA_IS_POSSIBLY_SENSITIVE) == true) {
|
if (extras?.getBoolean(EXTRA_IS_POSSIBLY_SENSITIVE) == true) {
|
||||||
possiblySensitive = true
|
possiblySensitive = true
|
||||||
|
@ -430,7 +435,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
val src = MediaPickerActivity.getMediaUris(data)?.takeIf(Array<Uri>::isNotEmpty) ?:
|
val src = MediaPickerActivity.getMediaUris(data)?.takeIf(Array<Uri>::isNotEmpty) ?:
|
||||||
data.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)?.let { arrayOf(it) }
|
data.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)?.let { arrayOf(it) }
|
||||||
if (src != null) {
|
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 -> {
|
replyLabel -> {
|
||||||
if (replyLabel.visibility != View.VISIBLE) return
|
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) {
|
private fun extensionIntentItemSelected(item: MenuItem) {
|
||||||
val intent = item.intent ?: return
|
val intent = item.intent ?: return
|
||||||
try {
|
try {
|
||||||
val action = intent.action
|
when (intent.action) {
|
||||||
when (action) {
|
|
||||||
INTENT_ACTION_EXTENSION_COMPOSE -> {
|
INTENT_ACTION_EXTENSION_COMPOSE -> {
|
||||||
val accountKeys = accountsAdapter.selectedAccountKeys
|
val accountKeys = accountsAdapter.selectedAccountKeys
|
||||||
intent.putExtra(EXTRA_TEXT, ParseUtils.parseString(editText.text))
|
intent.putExtra(EXTRA_TEXT, ParseUtils.parseString(editText.text))
|
||||||
|
@ -1083,16 +1090,20 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
val action = intent.action
|
val action = intent.action
|
||||||
val hasVisibility = intent.hasExtra(EXTRA_VISIBILITY)
|
val hasVisibility = intent.hasExtra(EXTRA_VISIBILITY)
|
||||||
val hasAccountKeys: Boolean
|
val hasAccountKeys: Boolean
|
||||||
if (intent.hasExtra(EXTRA_ACCOUNT_KEYS)) {
|
when {
|
||||||
val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS)
|
intent.hasExtra(EXTRA_ACCOUNT_KEYS) -> {
|
||||||
accountsAdapter.selectedAccountKeys = accountKeys
|
val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS)
|
||||||
hasAccountKeys = true
|
accountsAdapter.selectedAccountKeys = accountKeys
|
||||||
} else if (intent.hasExtra(EXTRA_ACCOUNT_KEY)) {
|
hasAccountKeys = true
|
||||||
val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
}
|
||||||
accountsAdapter.selectedAccountKeys = arrayOf(accountKey)
|
intent.hasExtra(EXTRA_ACCOUNT_KEY) -> {
|
||||||
hasAccountKeys = true
|
val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||||
} else {
|
accountsAdapter.selectedAccountKeys = arrayOf(accountKey)
|
||||||
hasAccountKeys = false
|
hasAccountKeys = true
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
hasAccountKeys = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
when (action) {
|
when (action) {
|
||||||
Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE -> {
|
Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE -> {
|
||||||
|
@ -1101,7 +1112,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
val stream = intent.getStreamExtra()
|
val stream = intent.getStreamExtra()
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
val src = stream.toTypedArray()
|
val src = stream.toTypedArray()
|
||||||
TaskStarter.execute(AddMediaTask(this, src, null, true, false))
|
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||||
|
copySrc = true,
|
||||||
|
deleteSrc = false
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -1110,7 +1124,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
val data = intent.data
|
val data = intent.data
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
val src = arrayOf(data)
|
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 -> {
|
INTENT_ACTION_EDIT_DRAFT -> {
|
||||||
val draft: Draft? = intent.getParcelableExtra(EXTRA_DRAFT)
|
val draft: Draft? = intent.getParcelableExtra(EXTRA_DRAFT)
|
||||||
when (draft?.action_type) {
|
return when (draft?.action_type) {
|
||||||
Draft.Action.REPLY -> {
|
Draft.Action.REPLY -> {
|
||||||
return showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||||
}
|
}
|
||||||
Draft.Action.QUOTE -> {
|
Draft.Action.QUOTE -> {
|
||||||
return showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
showDefaultLabelAndHint()
|
showDefaultLabelAndHint()
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1785,7 +1802,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
s.setSpan(MarkForDeleteSpan(), start, start + count,
|
s.setSpan(MarkForDeleteSpan(), start, start + count,
|
||||||
Spanned.SPAN_INCLUSIVE_INCLUSIVE)
|
Spanned.SPAN_INCLUSIVE_INCLUSIVE)
|
||||||
}
|
}
|
||||||
if (!imageSources.isEmpty()) {
|
if (imageSources.isNotEmpty()) {
|
||||||
val intent = ThemedMediaPickerActivity.withThemed(this@ComposeActivity)
|
val intent = ThemedMediaPickerActivity.withThemed(this@ComposeActivity)
|
||||||
.getMedia(Uri.parse(imageSources[0]))
|
.getMedia(Uri.parse(imageSources[0]))
|
||||||
.build()
|
.build()
|
||||||
|
@ -1816,7 +1833,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
})
|
})
|
||||||
editText.customSelectionActionModeCallback = this
|
editText.customSelectionActionModeCallback = this
|
||||||
editText.imageInputListener = { contentInfo ->
|
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 = {
|
task.callback = {
|
||||||
contentInfo.releasePermission()
|
contentInfo.releasePermission()
|
||||||
}
|
}
|
||||||
|
@ -1839,8 +1859,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val context = activity!!
|
val context = requireActivity()
|
||||||
val builder = AlertDialog.Builder(context!!)
|
val builder = AlertDialog.Builder(requireContext())
|
||||||
builder.setMessage(R.string.quote_protected_status_warning_message)
|
builder.setMessage(R.string.quote_protected_status_warning_message)
|
||||||
builder.setPositiveButton(R.string.send_anyway, this)
|
builder.setPositiveButton(R.string.send_anyway, this)
|
||||||
builder.setNegativeButton(android.R.string.cancel, null)
|
builder.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
@ -1873,8 +1893,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val context = activity!!
|
val context = requireActivity()
|
||||||
val builder = AlertDialog.Builder(context!!)
|
val builder = AlertDialog.Builder(requireContext())
|
||||||
builder.setMessage(getString(R.string.message_format_compose_message_convert_to_status,
|
builder.setMessage(getString(R.string.message_format_compose_message_convert_to_status,
|
||||||
"@$screenName"))
|
"@$screenName"))
|
||||||
builder.setPositiveButton(R.string.action_send, this)
|
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 {
|
override fun isLongPressDragEnabled(): Boolean {
|
||||||
return true
|
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) {
|
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
|
||||||
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
|
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
|
||||||
// Fade out the view as it is swiped out of the parent's bounds
|
// 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
|
viewHolder.itemView.alpha = alpha
|
||||||
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1924,7 +1944,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ALPHA_FULL = 1.0f
|
const val ALPHA_FULL = 1.0f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1996,7 +2016,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
set(value) {
|
set(value) {
|
||||||
selection.clear()
|
selection.clear()
|
||||||
for (accountKey in value) {
|
for (accountKey in value) {
|
||||||
selection.put(accountKey, true)
|
selection[accountKey] = true
|
||||||
}
|
}
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
@ -2034,7 +2054,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
fun toggleSelection(position: Int) {
|
fun toggleSelection(position: Int) {
|
||||||
if (accounts == null || position < 0) return
|
if (accounts == null || position < 0) return
|
||||||
val account = accounts!![position]
|
val account = accounts!![position]
|
||||||
selection.put(account.key, true != selection[account.key])
|
selection[account.key] = true != selection[account.key]
|
||||||
activity.updateAccountSelectionState()
|
activity.updateAccountSelectionState()
|
||||||
activity.updateVisibilityState()
|
activity.updateVisibilityState()
|
||||||
activity.updateSummaryTextState()
|
activity.updateSummaryTextState()
|
||||||
|
@ -2046,7 +2066,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
if (accounts == null || position < 0) return
|
if (accounts == null || position < 0) return
|
||||||
val account = accounts!![position]
|
val account = accounts!![position]
|
||||||
selection.clear()
|
selection.clear()
|
||||||
selection.put(account.key, true != selection[account.key])
|
selection[account.key] = true != selection[account.key]
|
||||||
activity.updateAccountSelectionState()
|
activity.updateAccountSelectionState()
|
||||||
activity.updateVisibilityState()
|
activity.updateVisibilityState()
|
||||||
activity.updateSummaryTextState()
|
activity.updateSummaryTextState()
|
||||||
|
@ -2096,12 +2116,12 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
private class DisplayPlaceNameTask : AbstractTask<ParcelableLocation, List<Address>, ComposeActivity>() {
|
private class DisplayPlaceNameTask : AbstractTask<ParcelableLocation, List<Address>, ComposeActivity>() {
|
||||||
|
|
||||||
override fun doLongOperation(location: ParcelableLocation): List<Address>? {
|
override fun doLongOperation(location: ParcelableLocation): List<Address>? {
|
||||||
try {
|
return try {
|
||||||
val activity = callback ?: throw IOException("Interrupted")
|
val activity = callback ?: throw IOException("Interrupted")
|
||||||
val gcd = Geocoder(activity, Locale.getDefault())
|
val gcd = Geocoder(activity, Locale.getDefault())
|
||||||
return gcd.getFromLocation(location.latitude, location.longitude, 1)
|
gcd.getFromLocation(location.latitude, location.longitude, 1)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
return null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2119,13 +2139,16 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
textView.spannable = ParcelableLocationUtils.getHumanReadableString(location, 3)
|
textView.spannable = ParcelableLocationUtils.getHumanReadableString(location, 3)
|
||||||
textView.tag = location
|
textView.tag = location
|
||||||
} else {
|
} else {
|
||||||
val tag = textView.tag
|
when (val tag = textView.tag) {
|
||||||
if (tag is Address) {
|
is Address -> {
|
||||||
textView.spannable = tag.locality
|
textView.spannable = tag.locality
|
||||||
} else if (tag is NoAddress) {
|
}
|
||||||
textView.setText(R.string.label_location_your_coarse_location)
|
is NoAddress -> {
|
||||||
} else {
|
textView.setText(R.string.label_location_your_coarse_location)
|
||||||
textView.setText(R.string.getting_location)
|
}
|
||||||
|
else -> {
|
||||||
|
textView.setText(R.string.getting_location)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -105,12 +105,12 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||||
?: return false
|
?: return false
|
||||||
// val file = File(folder, fileName)
|
// val file = File(folder, fileName)
|
||||||
// file.delete()
|
// file.delete()
|
||||||
try {
|
return try {
|
||||||
DataImportExportUtils.exportData(activity, file, flags)
|
DataImportExportUtils.exportData(activity, file, flags)
|
||||||
return true
|
true
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Log.w(LOGTAG, e)
|
Log.w(LOGTAG, e)
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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
|
return false
|
||||||
}
|
}
|
||||||
if (!file.isFile) return false
|
if (!file.isFile) return false
|
||||||
try {
|
return try {
|
||||||
DataImportExportUtils.importData(activity, file, flags)
|
DataImportExportUtils.importData(activity, file, flags)
|
||||||
return true
|
true
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Log.w(LOGTAG, e)
|
Log.w(LOGTAG, e)
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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
|
return 0
|
||||||
}
|
}
|
||||||
if (!file.isFile) return 0
|
if (!file.isFile) return 0
|
||||||
try {
|
return try {
|
||||||
return DataImportExportUtils.getImportedSettingsFlags(activity, file)
|
DataImportExportUtils.getImportedSettingsFlags(activity, file)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
return 0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||||
|
|
||||||
companion object {
|
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()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
|
when {
|
||||||
showPickFileDialog()
|
checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE) -> {
|
||||||
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
|
showPickFileDialog()
|
||||||
val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
}
|
||||||
ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS)
|
Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN -> {
|
||||||
} else {
|
val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||||
finishWithDeniedMessage()
|
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.HomeDrawerLayout
|
||||||
import org.mariotaku.twidere.view.TabPagerIndicator
|
import org.mariotaku.twidere.view.TabPagerIndicator
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, SupportFragmentCallback,
|
class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, SupportFragmentCallback,
|
||||||
OnLongClickListener, DrawerLayout.DrawerListener {
|
OnLongClickListener, DrawerLayout.DrawerListener {
|
||||||
|
@ -422,12 +423,18 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
||||||
if (!ViewCompat.getFitsSystemWindows(homeMenu)) {
|
if (!ViewCompat.getFitsSystemWindows(homeMenu)) {
|
||||||
homeContent.setPadding(0, insets.systemWindowInsetTop, 0, 0)
|
homeContent.setPadding(0, insets.systemWindowInsetTop, 0, 0)
|
||||||
}
|
}
|
||||||
|
(toolbar.layoutParams as? MarginLayoutParams)?.bottomMargin = insets.systemWindowInsetBottom
|
||||||
(actionsButton.layoutParams as? MarginLayoutParams)?.bottomMargin =
|
(actionsButton.layoutParams as? MarginLayoutParams)?.bottomMargin =
|
||||||
actionsButtonBottomMargin + insets.systemWindowInsetBottom
|
actionsButtonBottomMargin + if (preferences[tabPositionKey] == SharedPreferenceConstants.VALUE_TAB_POSITION_TOP) {
|
||||||
|
insets.systemWindowInsetBottom
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
return insets
|
return insets
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
val tabPosition = handleIntent(intent, false)
|
val tabPosition = handleIntent(intent, false)
|
||||||
if (tabPosition >= 0) {
|
if (tabPosition >= 0) {
|
||||||
mainPager.currentItem = tabPosition.coerceInOr(0 until pagerAdapter.count, 0)
|
mainPager.currentItem = tabPosition.coerceInOr(0 until pagerAdapter.count, 0)
|
||||||
|
@ -623,16 +630,22 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
||||||
}
|
}
|
||||||
notifyControlBarOffsetChanged()
|
notifyControlBarOffsetChanged()
|
||||||
} else {
|
} else {
|
||||||
|
val layoutparams = toolbar.layoutParams
|
||||||
|
val toolbarMarginBottom = if (layoutparams is MarginLayoutParams) {
|
||||||
|
layoutparams.bottomMargin
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
val translationY = if (mainTabs.columns > 1 || !toolbar.isVisible) {
|
val translationY = if (mainTabs.columns > 1 || !toolbar.isVisible) {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
(toolbar.height * (offset - 1)).toInt()
|
((toolbar.height + toolbarMarginBottom) * (offset - 1)).toInt()
|
||||||
}
|
}
|
||||||
toolbar.translationY = -translationY.toFloat()
|
toolbar.translationY = -translationY.toFloat()
|
||||||
windowOverlay.translationY = -translationY.toFloat()
|
windowOverlay.translationY = -translationY.toFloat()
|
||||||
val lp = actionsButton.layoutParams
|
val lp = actionsButton.layoutParams
|
||||||
if (lp is MarginLayoutParams) {
|
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 {
|
} else {
|
||||||
actionsButton.translationY = actionsButton.height * (1 - offset)
|
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)
|
"wide" -> resources.getDimension(R.dimen.preferred_tab_column_width_wide)
|
||||||
else -> resources.getDimension(R.dimen.preferred_tab_column_width_normal)
|
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 {
|
} else {
|
||||||
mainPager.pageMargin = 0
|
mainPager.pageMargin = 0
|
||||||
mainPager.setPageMarginDrawable(null)
|
mainPager.setPageMarginDrawable(null)
|
||||||
|
@ -1059,7 +1072,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
||||||
|
|
||||||
class AutoRefreshConfirmDialogFragment : BaseDialogFragment() {
|
class AutoRefreshConfirmDialogFragment : BaseDialogFragment() {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val builder = AlertDialog.Builder(context!!)
|
val builder = AlertDialog.Builder(requireContext())
|
||||||
builder.setTitle(R.string.auto_refresh)
|
builder.setTitle(R.string.auto_refresh)
|
||||||
builder.setMessage(R.string.message_auto_refresh_confirm)
|
builder.setMessage(R.string.message_auto_refresh_confirm)
|
||||||
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
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 {
|
private fun getResultIntent(uri: Uri?, error: Exception?, sampleSize: Int): Intent {
|
||||||
val result = CropImage.ActivityResult(cropImageView.imageUri, uri, error,
|
val result = CropImage.ActivityResult(cropImageView.imageUri, uri, error,
|
||||||
cropImageView.cropPoints, cropImageView.cropRect, cropImageView.rotatedDegrees,
|
cropImageView.cropPoints, cropImageView.cropRect, cropImageView.rotatedDegrees,
|
||||||
sampleSize)
|
cropImageView.wholeImageRect, sampleSize)
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.putExtra(CropImage.CROP_IMAGE_EXTRA_RESULT, result)
|
intent.putExtra(CropImage.CROP_IMAGE_EXTRA_RESULT, result)
|
||||||
return intent
|
return intent
|
||||||
|
|
|
@ -30,7 +30,7 @@ class InvalidAccountAlertActivity : FragmentActivity() {
|
||||||
|
|
||||||
class InvalidAccountAlertDialogFragment : BaseDialogFragment() {
|
class InvalidAccountAlertDialogFragment : BaseDialogFragment() {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
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.setTitle(R.string.title_error_invalid_account)
|
||||||
builder.setMessage(R.string.message_error_invalid_account)
|
builder.setMessage(R.string.message_error_invalid_account)
|
||||||
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
|
|
@ -119,7 +119,7 @@ class KeyboardShortcutPreferenceCompatActivity : BaseActivity(), OnClickListener
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val EXTRA_CONTEXT_TAG = "context_tag"
|
const val EXTRA_CONTEXT_TAG = "context_tag"
|
||||||
val EXTRA_KEY_ACTION = "key_action"
|
const val EXTRA_KEY_ACTION = "key_action"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.provider.MediaStore
|
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
@ -75,6 +74,8 @@ import org.mariotaku.twidere.view.viewer.MediaSwipeCloseContainer
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import android.Manifest.permission as AndroidPermissions
|
import android.Manifest.permission as AndroidPermissions
|
||||||
|
|
||||||
class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeCloseContainer.Listener,
|
class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeCloseContainer.Listener,
|
||||||
|
@ -146,7 +147,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
activityLayout.statusBarAlpha = offset
|
activityLayout.statusBarAlpha = offset
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
actionBar.hideOffset = Math.round(controlBarHeight * (1f - offset))
|
actionBar.hideOffset = (controlBarHeight * (1f - offset)).roundToInt()
|
||||||
} catch (e: UnsupportedOperationException) {
|
} catch (e: UnsupportedOperationException) {
|
||||||
// Some device will throw this exception
|
// Some device will throw this exception
|
||||||
hideOffsetNotSupported = true
|
hideOffsetNotSupported = true
|
||||||
|
@ -181,6 +182,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
REQUEST_SHARE_MEDIA -> {
|
REQUEST_SHARE_MEDIA -> {
|
||||||
ShareProvider.clearTempFiles(this)
|
ShareProvider.clearTempFiles(this)
|
||||||
|
@ -367,10 +369,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
ParcelableMedia.Type.IMAGE -> {
|
ParcelableMedia.Type.IMAGE -> {
|
||||||
val mediaUrl = media.media_url ?: return Fragment.instantiate(this, ExternalBrowserPageFragment::class.java.name, args) as MediaViewerFragment
|
val mediaUrl = media.media_url ?: return Fragment.instantiate(this, ExternalBrowserPageFragment::class.java.name, args) as MediaViewerFragment
|
||||||
args.putParcelable(EXTRA_MEDIA_URI, Uri.parse(mediaUrl))
|
args.putParcelable(EXTRA_MEDIA_URI, Uri.parse(mediaUrl))
|
||||||
if (mediaUrl.endsWith(".gif")) {
|
return if (mediaUrl.endsWith(".gif")) {
|
||||||
return Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment
|
Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment
|
||||||
} else {
|
} 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 -> {
|
ParcelableMedia.Type.ANIMATED_GIF, ParcelableMedia.Type.CARD_ANIMATED_GIF -> {
|
||||||
|
@ -408,10 +410,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSwipeOffsetChanged(offset: Int) {
|
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
|
swipeContainer.backgroundAlpha = offsetFactor
|
||||||
val colorToolbar = overrideTheme.colorToolbar
|
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
|
activityLayout.statusBarAlpha = alpha / 255f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,11 +452,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun instantiateMediaViewerFragment(args: Bundle): MediaViewerFragment {
|
private fun instantiateMediaViewerFragment(args: Bundle): MediaViewerFragment {
|
||||||
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
|
return Fragment.instantiate(this, ExoPlayerPageFragment::class.java.name, args) as MediaViewerFragment
|
||||||
Fragment.instantiate(this, VideoPageFragment::class.java.name, args) as MediaViewerFragment
|
|
||||||
} else {
|
|
||||||
Fragment.instantiate(this, ExoPlayerPageFragment::class.java.name, args) as MediaViewerFragment
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processShareIntent(intent: Intent) {
|
private fun processShareIntent(intent: Intent) {
|
||||||
|
@ -468,11 +466,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
if (checkAllSelfPermissionsGranted(AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
|
if (checkAllSelfPermissionsGranted(AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
|
||||||
saveToStorage()
|
saveToStorage()
|
||||||
} else {
|
} else {
|
||||||
val permissions: Array<String>
|
val permissions: Array<String> = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
|
||||||
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
|
|
||||||
} else {
|
} else {
|
||||||
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||||
}
|
}
|
||||||
PermissionRequestDialog.show(supportFragmentManager, getString(R.string.message_permission_request_save_media),
|
PermissionRequestDialog.show(supportFragmentManager, getString(R.string.message_permission_request_save_media),
|
||||||
permissions, REQUEST_PERMISSION_SAVE_MEDIA)
|
permissions, REQUEST_PERMISSION_SAVE_MEDIA)
|
||||||
|
@ -503,8 +500,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
|
|
||||||
private fun saveToStorage() {
|
private fun saveToStorage() {
|
||||||
val fileInfo = getCurrentCacheFileInfo(saveToStoragePosition) ?: return
|
val fileInfo = getCurrentCacheFileInfo(saveToStoragePosition) ?: return
|
||||||
val type = (fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType
|
val pubDir = when ((fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType) {
|
||||||
val pubDir = when (type) {
|
|
||||||
CacheFileType.VIDEO -> {
|
CacheFileType.VIDEO -> {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
||||||
|
@ -640,10 +636,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val REQUEST_SHARE_MEDIA = 201
|
private const val REQUEST_SHARE_MEDIA = 201
|
||||||
private val REQUEST_PERMISSION_SAVE_MEDIA = 202
|
private const val REQUEST_PERMISSION_SAVE_MEDIA = 202
|
||||||
private val REQUEST_PERMISSION_SHARE_MEDIA = 203
|
private const val REQUEST_PERMISSION_SHARE_MEDIA = 203
|
||||||
private val REQUEST_SELECT_SAVE_MEDIA = 204
|
private const val REQUEST_SELECT_SAVE_MEDIA = 204
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
|
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||||
const val FLAG_SYSTEM_UI_HIDE_BARS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
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?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
when (resultCode) {
|
when (resultCode) {
|
||||||
REQUEST_PURCHASE_EXTRA_FEATURES -> {
|
REQUEST_PURCHASE_EXTRA_FEATURES -> {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
|
|
@ -171,7 +171,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
||||||
override fun onDismiss(listView: ListView, reverseSortedPositions: IntArray) {
|
override fun onDismiss(listView: ListView, reverseSortedPositions: IntArray) {
|
||||||
val adapter = suggestionsList.adapter as SuggestionsAdapter
|
val adapter = suggestionsList.adapter as SuggestionsAdapter
|
||||||
val ids = LongArray(reverseSortedPositions.size)
|
val ids = LongArray(reverseSortedPositions.size)
|
||||||
for (i in 0 until reverseSortedPositions.size) {
|
for (i in reverseSortedPositions.indices) {
|
||||||
val position = reverseSortedPositions[i]
|
val position = reverseSortedPositions[i]
|
||||||
val item = adapter.getSuggestionItem(position) ?: return
|
val item = adapter.getSuggestionItem(position) ?: return
|
||||||
ids[i] = item._id
|
ids[i] = item._id
|
||||||
|
@ -215,6 +215,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
REQUEST_SCAN_QR -> {
|
REQUEST_SCAN_QR -> {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
|
@ -504,7 +505,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
||||||
private fun getActualPosition(position: Int): Int {
|
private fun getActualPosition(position: Int): Int {
|
||||||
var skipped = 0
|
var skipped = 0
|
||||||
for (i in 0 until removedPositions.size) {
|
for (i in 0 until removedPositions.size) {
|
||||||
if (position + skipped >= removedPositions.get(i)) {
|
if (position + skipped >= removedPositions[i]) {
|
||||||
skipped++
|
skipped++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,10 +538,10 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
internal val VIEW_TYPE_SEARCH_HISTORY = 0
|
internal const val VIEW_TYPE_SEARCH_HISTORY = 0
|
||||||
internal val VIEW_TYPE_SAVED_SEARCH = 1
|
internal const val VIEW_TYPE_SAVED_SEARCH = 1
|
||||||
internal val VIEW_TYPE_USER_SUGGESTION_ITEM = 2
|
internal const val VIEW_TYPE_USER_SUGGESTION_ITEM = 2
|
||||||
internal val VIEW_TYPE_USER_SCREEN_NAME = 3
|
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.KeyboardShortcutsHandler
|
||||||
import org.mariotaku.twidere.util.ThemeUtils
|
import org.mariotaku.twidere.util.ThemeUtils
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartFragmentCallback {
|
class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartFragmentCallback {
|
||||||
|
|
||||||
|
@ -74,8 +75,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
||||||
shouldTerminate = savedInstanceState.getBoolean(EXTRA_SHOULD_TERMINATE, shouldTerminate)
|
shouldTerminate = savedInstanceState.getBoolean(EXTRA_SHOULD_TERMINATE, shouldTerminate)
|
||||||
} else if (intent.getBooleanExtra(EXTRA_SHOULD_TERMINATE, false)) {
|
} else if (intent.getBooleanExtra(EXTRA_SHOULD_TERMINATE, false)) {
|
||||||
finishNoRestart()
|
finishNoRestart()
|
||||||
System.exit(0)
|
exitProcess(0)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val backgroundOption = currentThemeBackgroundOption
|
val backgroundOption = currentThemeBackgroundOption
|
||||||
|
@ -349,8 +349,8 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val VIEW_TYPE_PREFERENCE_ENTRY = 0
|
const val VIEW_TYPE_PREFERENCE_ENTRY = 0
|
||||||
val VIEW_TYPE_HEADER_ENTRY = 1
|
const val VIEW_TYPE_HEADER_ENTRY = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
||||||
|
|
||||||
class RestartConfirmDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
|
class RestartConfirmDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val builder = AlertDialog.Builder(activity!!)
|
val builder = AlertDialog.Builder(requireActivity())
|
||||||
if (arguments?.getBoolean(EXTRA_SHOULD_TERMINATE) == true) {
|
if (arguments?.getBoolean(EXTRA_SHOULD_TERMINATE) == true) {
|
||||||
builder.setMessage(R.string.app_terminate_confirm)
|
builder.setMessage(R.string.app_terminate_confirm)
|
||||||
builder.setNegativeButton(R.string.action_dont_terminate, this)
|
builder.setNegativeButton(R.string.action_dont_terminate, this)
|
||||||
|
@ -424,7 +424,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val RESULT_SETTINGS_CHANGED = 10
|
private const val RESULT_SETTINGS_CHANGED = 10
|
||||||
|
|
||||||
fun setShouldRecreate(activity: Activity) {
|
fun setShouldRecreate(activity: Activity) {
|
||||||
if (activity !is SettingsActivity) return
|
if (activity !is SettingsActivity) return
|
||||||
|
|
|
@ -428,23 +428,30 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
internal fun onSignInError(exception: Exception) {
|
internal fun onSignInError(exception: Exception) {
|
||||||
DebugLog.w(LOGTAG, "Sign in error", exception)
|
DebugLog.w(LOGTAG, "Sign in error", exception)
|
||||||
var errorReason: String? = null
|
var errorReason: String? = null
|
||||||
if (exception is AuthenticityTokenException) {
|
when (exception) {
|
||||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
is AuthenticityTokenException -> {
|
||||||
errorReason = "wrong_api_key"
|
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||||
} else if (exception is WrongUserPassException) {
|
errorReason = "wrong_api_key"
|
||||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
}
|
||||||
errorReason = "wrong_username_password"
|
is WrongUserPassException -> {
|
||||||
} else if (exception is SignInTask.WrongBasicCredentialException) {
|
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
errorReason = "wrong_username_password"
|
||||||
errorReason = "wrong_username_password"
|
}
|
||||||
} else if (exception is SignInTask.WrongAPIURLFormatException) {
|
is SignInTask.WrongBasicCredentialException -> {
|
||||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||||
errorReason = "wrong_api_key"
|
errorReason = "wrong_username_password"
|
||||||
} else if (exception is LoginVerificationException) {
|
}
|
||||||
Toast.makeText(this, R.string.message_toast_login_verification_failed, Toast.LENGTH_SHORT).show()
|
is SignInTask.WrongAPIURLFormatException -> {
|
||||||
errorReason = "login_verification_failed"
|
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
errorReason = "wrong_api_key"
|
||||||
Toast.makeText(this, exception.getErrorMessage(this), Toast.LENGTH_SHORT).show()
|
}
|
||||||
|
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,
|
Analyzer.log(SignIn(false, credentialsType = apiConfig.credentialsType,
|
||||||
errorReason = errorReason, accountType = apiConfig.type))
|
errorReason = errorReason, accountType = apiConfig.type))
|
||||||
|
@ -573,13 +580,13 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
class SignInTypeChooserDialogFragment : BaseDialogFragment(),
|
class SignInTypeChooserDialogFragment : BaseDialogFragment(),
|
||||||
LoaderManager.LoaderCallbacks<List<CustomAPIConfig>> {
|
LoaderManager.LoaderCallbacks<List<CustomAPIConfig>> {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val builder = AlertDialog.Builder(context!!)
|
val builder = AlertDialog.Builder(requireContext())
|
||||||
builder.setView(R.layout.dialog_expandable_list)
|
builder.setView(R.layout.dialog_expandable_list)
|
||||||
val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
dialog.onShow {
|
dialog.onShow {
|
||||||
it.applyTheme()
|
it.applyTheme()
|
||||||
val listView = it.expandableList
|
val listView = it.expandableList
|
||||||
val adapter = LoginTypeAdapter(context!!)
|
val adapter = LoginTypeAdapter(requireContext())
|
||||||
listView.setAdapter(adapter)
|
listView.setAdapter(adapter)
|
||||||
listView.setOnGroupClickListener { _, _, groupPosition, _ ->
|
listView.setOnGroupClickListener { _, _, groupPosition, _ ->
|
||||||
val type = adapter.getGroup(groupPosition)
|
val type = adapter.getGroup(groupPosition)
|
||||||
|
@ -623,7 +630,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
AccountType.MASTODON, AccountType.STATUSNET)
|
AccountType.MASTODON, AccountType.STATUSNET)
|
||||||
val result = supportedAccountTypes.mapNotNullTo(ArrayList()) { type ->
|
val result = supportedAccountTypes.mapNotNullTo(ArrayList()) { type ->
|
||||||
if (type == AccountType.MASTODON) return@mapNotNullTo LoginType(type,
|
if (type == AccountType.MASTODON) return@mapNotNullTo LoginType(type,
|
||||||
listOf(CustomAPIConfig.mastodon(context!!)))
|
listOf(CustomAPIConfig.mastodon(requireContext())))
|
||||||
return@mapNotNullTo configGroup[type]?.let { list ->
|
return@mapNotNullTo configGroup[type]?.let { list ->
|
||||||
LoginType(type, list.sortedBy { !it.isDefault })
|
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>> {
|
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<CustomAPIConfig>> {
|
||||||
return DefaultAPIConfigLoader(context!!)
|
return DefaultAPIConfigLoader(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoaderReset(loader: Loader<List<CustomAPIConfig>>) {
|
override fun onLoaderReset(loader: Loader<List<CustomAPIConfig>>) {
|
||||||
|
@ -694,7 +701,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
var challengeType: String? = null
|
var challengeType: String? = null
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val builder = AlertDialog.Builder(context!!)
|
val builder = AlertDialog.Builder(requireContext())
|
||||||
builder.setTitle(R.string.login_verification)
|
builder.setTitle(R.string.login_verification)
|
||||||
builder.setView(R.layout.dialog_login_verification_code)
|
builder.setView(R.layout.dialog_login_verification_code)
|
||||||
builder.positive(android.R.string.ok, this::performVerification)
|
builder.positive(android.R.string.ok, this::performVerification)
|
||||||
|
@ -753,7 +760,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
class PasswordSignInDialogFragment : BaseDialogFragment() {
|
class PasswordSignInDialogFragment : BaseDialogFragment() {
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
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.setView(R.layout.dialog_password_sign_in)
|
||||||
builder.positive(R.string.action_sign_in, this::onPositiveButton)
|
builder.positive(R.string.action_sign_in, this::onPositiveButton)
|
||||||
builder.setNegativeButton(android.R.string.cancel, null)
|
builder.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
@ -809,10 +816,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
val oauth = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
|
val oauth = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
|
||||||
accountType = apiConfig.type, cls = TwitterOAuth::class.java)
|
accountType = apiConfig.type, cls = TwitterOAuth::class.java)
|
||||||
val accessToken: OAuthToken
|
val accessToken: OAuthToken
|
||||||
if (oauthVerifier != null) {
|
accessToken = if (oauthVerifier != null) {
|
||||||
accessToken = oauth.getAccessToken(requestToken, oauthVerifier)
|
oauth.getAccessToken(requestToken, oauthVerifier)
|
||||||
} else {
|
} else {
|
||||||
accessToken = oauth.getAccessToken(requestToken)
|
oauth.getAccessToken(requestToken)
|
||||||
}
|
}
|
||||||
auth = apiConfig.getOAuthAuthorization(accessToken) ?:
|
auth = apiConfig.getOAuthAuthorization(accessToken) ?:
|
||||||
throw MicroBlogException("Invalid OAuth credential")
|
throw MicroBlogException("Invalid OAuth credential")
|
||||||
|
@ -823,7 +830,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||||
val apiUser = twitter.verifyCredentials()
|
val apiUser = twitter.verifyCredentials()
|
||||||
var color = analyseUserProfileColor(apiUser)
|
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 accountKey = apiUser.key
|
||||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||||
val am = AccountManager.get(context)
|
val am = AccountManager.get(context)
|
||||||
|
@ -901,7 +908,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
return authOAuth()
|
return authOAuth()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(OAuthPasswordAuthenticator.AuthenticationException::class, MicroBlogException::class)
|
@Throws(AuthenticationException::class, MicroBlogException::class)
|
||||||
private fun authOAuth(): SignInResponse {
|
private fun authOAuth(): SignInResponse {
|
||||||
val activity = activityRef.get() ?: throw InterruptedException()
|
val activity = activityRef.get() ?: throw InterruptedException()
|
||||||
val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
||||||
|
@ -940,7 +947,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
return getOAuthSignInResponse(activity, accessToken, Credentials.Type.XAUTH)
|
return getOAuthSignInResponse(activity, accessToken, Credentials.Type.XAUTH)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(MicroBlogException::class, OAuthPasswordAuthenticator.AuthenticationException::class)
|
@Throws(MicroBlogException::class, AuthenticationException::class)
|
||||||
private fun authBasic(): SignInResponse {
|
private fun authBasic(): SignInResponse {
|
||||||
val activity = activityRef.get() ?: throw InterruptedException()
|
val activity = activityRef.get() ?: throw InterruptedException()
|
||||||
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
||||||
|
@ -962,7 +969,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
var color = analyseUserProfileColor(apiUser)
|
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 accountKey = apiUser.key
|
||||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||||
val am = AccountManager.get(activity)
|
val am = AccountManager.get(activity)
|
||||||
|
@ -991,7 +998,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||||
val apiUser = twitter.verifyCredentials()
|
val apiUser = twitter.verifyCredentials()
|
||||||
var color = analyseUserProfileColor(apiUser)
|
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 accountKey = apiUser.key
|
||||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||||
val am = AccountManager.get(activity)
|
val am = AccountManager.get(activity)
|
||||||
|
@ -1018,7 +1025,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||||
val apiUser = twitter.verifyCredentials()
|
val apiUser = twitter.verifyCredentials()
|
||||||
var color = analyseUserProfileColor(apiUser)
|
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 accountKey = apiUser.key
|
||||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||||
val am = AccountManager.get(activity)
|
val am = AccountManager.get(activity)
|
||||||
|
@ -1040,11 +1047,11 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
return SignInResponse(account != null, authType, credentials, user, color, type, extras)
|
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? {
|
override fun getLoginVerification(challengeType: String): String? {
|
||||||
// Dismiss current progress dialog
|
// Dismiss current progress dialog
|
||||||
|
@ -1087,10 +1094,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
protected val profileImageSize: String = activity.getString(R.string.profile_image_size)
|
protected val profileImageSize: String = activity.getString(R.string.profile_image_size)
|
||||||
|
|
||||||
final override fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
|
final override fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
|
||||||
try {
|
return try {
|
||||||
return SingleResponse.getInstance(performLogin())
|
SingleResponse.getInstance(performLogin())
|
||||||
} catch (e: Exception) {
|
} 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_TWITTER_SIGN_IN = 101
|
||||||
const val REQUEST_BROWSER_MASTODON_SIGN_IN = 102
|
const val REQUEST_BROWSER_MASTODON_SIGN_IN = 102
|
||||||
|
|
||||||
private val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
|
private const val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
|
||||||
private val EXTRA_API_LAST_CHANGE = "api_last_change"
|
private const val EXTRA_API_LAST_CHANGE = "api_last_change"
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {
|
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {
|
||||||
|
|
|
@ -41,8 +41,8 @@ class ThemedMediaPickerActivity : MediaPickerActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun withThemed(context: Context): MediaPickerActivity.IntentBuilder {
|
fun withThemed(context: Context): IntentBuilder {
|
||||||
val builder = MediaPickerActivity.IntentBuilder(context, ThemedMediaPickerActivity::class.java)
|
val builder = IntentBuilder(context, ThemedMediaPickerActivity::class.java)
|
||||||
builder.cropImageActivityClass(ImageCropperActivity::class.java)
|
builder.cropImageActivityClass(ImageCropperActivity::class.java)
|
||||||
builder.streamDownloaderClass(RestFuNetworkStreamDownloader::class.java)
|
builder.streamDownloaderClass(RestFuNetworkStreamDownloader::class.java)
|
||||||
return builder
|
return builder
|
||||||
|
|
|
@ -93,7 +93,7 @@ class TrendsLocationSelectorActivity : BaseActivity() {
|
||||||
private val list: Array<LocationsMap.LocationsData> get() = arguments?.getTypedArray(EXTRA_DATA) ?: emptyArray()
|
private val list: Array<LocationsMap.LocationsData> get() = arguments?.getTypedArray(EXTRA_DATA) ?: emptyArray()
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val selectorBuilder = AlertDialog.Builder(context!!)
|
val selectorBuilder = AlertDialog.Builder(requireContext())
|
||||||
selectorBuilder.setTitle(R.string.trends_location)
|
selectorBuilder.setTitle(R.string.trends_location)
|
||||||
selectorBuilder.setView(R.layout.dialog_expandable_list)
|
selectorBuilder.setView(R.layout.dialog_expandable_list)
|
||||||
selectorBuilder.setNegativeButton(android.R.string.cancel, null)
|
selectorBuilder.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
@ -101,7 +101,7 @@ class TrendsLocationSelectorActivity : BaseActivity() {
|
||||||
dialog.onShow {
|
dialog.onShow {
|
||||||
it.applyTheme()
|
it.applyTheme()
|
||||||
val listView = it.expandableList
|
val listView = it.expandableList
|
||||||
val adapter = ExpandableTrendLocationsListAdapter(context!!)
|
val adapter = ExpandableTrendLocationsListAdapter(requireContext())
|
||||||
adapter.data = list
|
adapter.data = list
|
||||||
listView.setAdapter(adapter)
|
listView.setAdapter(adapter)
|
||||||
listView.setOnGroupClickListener(ExpandableListView.OnGroupClickListener { _, _, groupPosition, _ ->
|
listView.setOnGroupClickListener(ExpandableListView.OnGroupClickListener { _, _, groupPosition, _ ->
|
||||||
|
@ -177,23 +177,14 @@ class TrendsLocationSelectorActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
|
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||||
val view: View
|
val view: View = convertView ?: inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
|
||||||
if (convertView != null) {
|
|
||||||
view = convertView
|
|
||||||
} else {
|
|
||||||
view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
|
|
||||||
}
|
|
||||||
view.findViewById<TextView>(android.R.id.text1).text = getGroup(groupPosition).name
|
view.findViewById<TextView>(android.R.id.text1).text = getGroup(groupPosition).name
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
|
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||||
val view: View
|
val view: View =
|
||||||
if (convertView != null) {
|
convertView ?: inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||||
view = convertView
|
|
||||||
} else {
|
|
||||||
view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
|
|
||||||
}
|
|
||||||
val location = getChild(groupPosition, childPosition)
|
val location = getChild(groupPosition, childPosition)
|
||||||
val text1 = view.findViewById<TextView>(android.R.id.text1)
|
val text1 = view.findViewById<TextView>(android.R.id.text1)
|
||||||
if (location.parentId == WORLDWIDE) {
|
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