commit
4c884673ee
|
@ -226,6 +226,7 @@ dependencies {
|
|||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
|
||||
implementation 'com.sprylab.android.texturevideoview:texturevideoview:1.2.1'
|
||||
implementation 'com.squareup:pollexor:2.0.4'
|
||||
implementation 'org.apache.commons:commons-text:1.8'
|
||||
implementation "org.apache.james:apache-mime4j-core:${libVersions['Mime4J']}"
|
||||
implementation "org.apache.james:apache-mime4j-storage:${libVersions['Mime4J']}"
|
||||
implementation "com.bluelinelabs:logansquare:${sharedVersions['LoganSquare']}"
|
||||
|
|
|
@ -316,9 +316,9 @@ class AccountsDumperPlugin(val context: Context) : DumperPlugin {
|
|||
return JsonPath.parse(JsonSerializer.serialize(details), configuration)
|
||||
}
|
||||
|
||||
private fun Any.prettyPrint() = when {
|
||||
this is JSONObject -> toString(4)
|
||||
this is JSONArray -> toString(4)
|
||||
private fun Any.prettyPrint() = when (this) {
|
||||
is JSONObject -> toString(4)
|
||||
is JSONArray -> toString(4)
|
||||
else -> toString()
|
||||
}
|
||||
|
||||
|
|
|
@ -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,101 +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.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;
|
||||
|
||||
for (Map.Entry<CharSequence, CharSequence> pair : lookupMap.entrySet()) {
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -95,8 +95,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
|||
protected void onClick() {
|
||||
final Context context = getContext();
|
||||
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_CONTEXT_TAG(), mContextTag);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_KEY_ACTION(), mAction);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_CONTEXT_TAG, mContextTag);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_KEY_ACTION, mAction);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Uses https://github.com/george-steel/android-utils/commit/289aff11e53593a55d780f9f5986e49343a79e55
|
||||
|
||||
package org.oshkimaadziig.george.androidutils;
|
||||
|
||||
import android.text.Spannable;
|
||||
|
@ -87,7 +89,7 @@ public class SpanFormatter {
|
|||
|
||||
if (typeTerm.equals("%")) {
|
||||
cookedArg = "%";
|
||||
} else if (typeTerm.equals("%")) {
|
||||
} else if (typeTerm.equals("n")) {
|
||||
cookedArg = "\n";
|
||||
} else {
|
||||
int argIdx;
|
||||
|
|
|
@ -25,26 +25,38 @@ import java.util.*
|
|||
@SuppressLint("RestrictedApi")
|
||||
object LocaleHelperAccessor {
|
||||
fun forLanguageTag(str: String): Locale {
|
||||
if (str.contains("-")) {
|
||||
val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (args.size > 2) {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
} else if (args.size > 1) {
|
||||
return Locale(args[0], args[1])
|
||||
} else if (args.size == 1) {
|
||||
return Locale(args[0])
|
||||
when {
|
||||
str.contains("-") -> {
|
||||
val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
when {
|
||||
args.size > 2 -> {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
}
|
||||
args.size > 1 -> {
|
||||
return Locale(args[0], args[1])
|
||||
}
|
||||
args.size == 1 -> {
|
||||
return Locale(args[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (str.contains("_")) {
|
||||
val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (args.size > 2) {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
} else if (args.size > 1) {
|
||||
return Locale(args[0], args[1])
|
||||
} else if (args.size == 1) {
|
||||
return Locale(args[0])
|
||||
str.contains("_") -> {
|
||||
val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
when {
|
||||
args.size > 2 -> {
|
||||
return Locale(args[0], args[1], args[2])
|
||||
}
|
||||
args.size > 1 -> {
|
||||
return Locale(args[0], args[1])
|
||||
}
|
||||
args.size == 1 -> {
|
||||
return Locale(args[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
return Locale(str)
|
||||
}
|
||||
} else {
|
||||
return Locale(str)
|
||||
}
|
||||
|
||||
throw IllegalArgumentException("Can not parse language tag: [$str]")
|
||||
|
|
|
@ -10,23 +10,23 @@ import android.os.Handler
|
|||
|
||||
fun AccountManager.addOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener,
|
||||
handler: Handler? = null, updateImmediately: Boolean = false): Boolean {
|
||||
try {
|
||||
return try {
|
||||
this.addOnAccountsUpdatedListener(listener, handler, updateImmediately)
|
||||
return true
|
||||
true
|
||||
} catch (e: IllegalStateException) {
|
||||
return false
|
||||
false
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun AccountManager.removeOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener): Boolean {
|
||||
try {
|
||||
return try {
|
||||
this.removeOnAccountsUpdatedListener(listener)
|
||||
return true
|
||||
true
|
||||
} catch (e: IllegalStateException) {
|
||||
return false
|
||||
false
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ fun Collection<*>?.isNullOrEmpty(): Boolean {
|
|||
}
|
||||
|
||||
fun <T> MutableCollection<T>.addAllEnhanced(collection: Collection<T>, ignoreDuplicates: Boolean): Boolean {
|
||||
if (ignoreDuplicates) {
|
||||
return addAll(collection.filter { it !in this })
|
||||
return if (ignoreDuplicates) {
|
||||
addAll(collection.filter { it !in this })
|
||||
} else {
|
||||
return addAll(collection)
|
||||
addAll(collection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ fun <E> Collection<E>.contentEquals(other: Collection<E>): Boolean {
|
|||
|
||||
inline fun <reified T> List<T>.subArray(range: IntRange): Array<T> {
|
||||
return Array(range.count()) {
|
||||
this[range.start + it]
|
||||
this[range.first + it]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ fun Context.checkAnySelfPermissionsGranted(vararg permissions: String): Boolean
|
|||
|
||||
fun Context.unregisterReceiverSafe(receiver: BroadcastReceiver?): Boolean {
|
||||
if (receiver == null) return false
|
||||
try {
|
||||
return try {
|
||||
unregisterReceiver(receiver)
|
||||
return true
|
||||
true
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ fun Cursor.safeGetInt(columnIndex: Int, def: Int = -1) = try {
|
|||
def
|
||||
}
|
||||
|
||||
fun Cursor.safeGetString(columnIndex: Int, def: String = "") = try {
|
||||
fun Cursor.safeGetString(columnIndex: Int, def: String = ""): String = try {
|
||||
getString(columnIndex)
|
||||
} catch (e: IllegalStateException) {
|
||||
def
|
||||
|
|
|
@ -58,10 +58,10 @@ val Locale.bcp47Tag: String
|
|||
}
|
||||
|
||||
val bcp47Tag = StringBuilder(language)
|
||||
if (!country.isEmpty()) {
|
||||
if (country.isNotEmpty()) {
|
||||
bcp47Tag.append(SEP).append(country)
|
||||
}
|
||||
if (!variant.isEmpty()) {
|
||||
if (variant.isNotEmpty()) {
|
||||
bcp47Tag.append(SEP).append(variant)
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ fun Number.toLocalizedString(locale: Locale = Locale.getDefault()): String {
|
|||
val Int.nextPowerOf2: Int
|
||||
get() {
|
||||
var n = this
|
||||
if (n <= 0 || n > 1 shl 30) throw IllegalArgumentException("n is invalid: " + n)
|
||||
if (n <= 0 || n > 1 shl 30) throw IllegalArgumentException("n is invalid: $n")
|
||||
n -= 1
|
||||
n = n or (n shr 16)
|
||||
n = n or (n shr 8)
|
||||
|
|
|
@ -6,5 +6,5 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
* Created by mariotaku on 16/8/21.
|
||||
*/
|
||||
fun RecyclerView.Adapter<*>.findPositionByItemId(itemId: Long): Int {
|
||||
return (0 until itemCount).firstOrNull { getItemId(it) == itemId } ?: androidx.recyclerview.widget.RecyclerView.NO_POSITION
|
||||
return (0 until itemCount).firstOrNull { getItemId(it) == itemId } ?: RecyclerView.NO_POSITION
|
||||
}
|
||||
|
|
|
@ -40,5 +40,5 @@ fun InputStream.expectLine(string: String = "", charset: Charset = Charset.defau
|
|||
fun InputStream.expectBytes(bytes: ByteArray): Boolean {
|
||||
val readBytes = ByteArray(bytes.size)
|
||||
read(readBytes)
|
||||
return Arrays.equals(readBytes, bytes)
|
||||
return readBytes.contentEquals(bytes)
|
||||
}
|
|
@ -35,20 +35,24 @@ object InternalActivityCreator {
|
|||
activity.maxSortPosition = activity.minSortPosition
|
||||
activity.createdAt = status.getCreatedAt()
|
||||
|
||||
if (status.getInReplyToUserId() == accountId) {
|
||||
activity.action = Activity.Action.REPLY
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
when {
|
||||
status.getInReplyToUserId() == accountId -> {
|
||||
activity.action = Activity.Action.REPLY
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
|
||||
//TODO set target statuses (in reply to status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
} else if (status.quotedStatus?.user?.id == accountId) {
|
||||
activity.action = Activity.Action.QUOTE
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
} else {
|
||||
activity.action = Activity.Action.MENTION
|
||||
activity.targetUsers = arrayOfNulls<User>(0)
|
||||
activity.targetObjectStatuses = arrayOf(status)
|
||||
//TODO set target statuses (in reply to status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
}
|
||||
status.quotedStatus?.user?.id == accountId -> {
|
||||
activity.action = Activity.Action.QUOTE
|
||||
activity.targetStatuses = arrayOf(status)
|
||||
activity.targetObjectStatuses = arrayOfNulls<Status>(0)
|
||||
}
|
||||
else -> {
|
||||
activity.action = Activity.Action.MENTION
|
||||
activity.targetUsers = arrayOfNulls<User>(0)
|
||||
activity.targetObjectStatuses = arrayOf(status)
|
||||
}
|
||||
}
|
||||
activity.sourcesSize = 1
|
||||
activity.sources = arrayOf(status.getUser())
|
||||
|
|
|
@ -13,8 +13,7 @@ class AssistLauncherActivity : Activity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val prefs = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
|
||||
val composeNowAction = prefs.getString(KEY_COMPOSE_NOW_ACTION, VALUE_COMPOSE_NOW_ACTION_COMPOSE)
|
||||
val action = when (composeNowAction) {
|
||||
val action = when (prefs.getString(KEY_COMPOSE_NOW_ACTION, VALUE_COMPOSE_NOW_ACTION_COMPOSE)) {
|
||||
VALUE_COMPOSE_NOW_ACTION_TAKE_PHOTO -> INTENT_ACTION_COMPOSE_TAKE_PHOTO
|
||||
VALUE_COMPOSE_NOW_ACTION_PICK_IMAGE -> INTENT_ACTION_COMPOSE_PICK_IMAGE
|
||||
else -> INTENT_ACTION_COMPOSE
|
||||
|
|
|
@ -300,7 +300,7 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
|
|||
for (i in 0 until handlerFilter.countDataAuthorities()) {
|
||||
val authorityEntry = handlerFilter.getDataAuthority(i)
|
||||
val port = authorityEntry.port
|
||||
intentFilter.addDataAuthority(authorityEntry.host, if (port < 0) null else Integer.toString(port))
|
||||
intentFilter.addDataAuthority(authorityEntry.host, if (port < 0) null else port.toString())
|
||||
}
|
||||
try {
|
||||
adapter.enableForegroundDispatch(this, intent, arrayOf(intentFilter), null)
|
||||
|
@ -469,20 +469,20 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
|
|||
}
|
||||
|
||||
private fun newInstance(name: String, context: Context, attrs: AttributeSet): View? {
|
||||
try {
|
||||
return try {
|
||||
val cls = findClass(name) ?: throw ClassNotFoundException(name)
|
||||
val constructor = cls.getConstructor(Context::class.java, AttributeSet::class.java)
|
||||
return constructor.newInstance(context, attrs) as View
|
||||
constructor.newInstance(context, attrs) as View
|
||||
} catch (e: InstantiationException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: IllegalAccessException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: InvocationTargetException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: NoSuchMethodException) {
|
||||
return null
|
||||
null
|
||||
} catch (e: ClassNotFoundException) {
|
||||
return null
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ class ColorPickerDialogActivity : BaseActivity(), Callback {
|
|||
|
||||
companion object {
|
||||
|
||||
val RESULT_CLEARED = -2
|
||||
const val RESULT_CLEARED = -2
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ import java.text.Normalizer
|
|||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.math.abs
|
||||
import android.Manifest.permission as AndroidPermission
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
|
@ -394,7 +395,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val src = MediaPickerActivity.getMediaUris(data)
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, false, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = false,
|
||||
deleteSrc = false
|
||||
))
|
||||
val extras = data.getBundleExtra(MediaPickerActivity.EXTRA_EXTRAS)
|
||||
if (extras?.getBoolean(EXTRA_IS_POSSIBLY_SENSITIVE) == true) {
|
||||
possiblySensitive = true
|
||||
|
@ -431,7 +435,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val src = MediaPickerActivity.getMediaUris(data)?.takeIf(Array<Uri>::isNotEmpty) ?:
|
||||
data.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)?.let { arrayOf(it) }
|
||||
if (src != null) {
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, false, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = false,
|
||||
deleteSrc = false
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +516,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
replyLabel -> {
|
||||
if (replyLabel.visibility != View.VISIBLE) return
|
||||
replyLabel.setSingleLine(replyLabel.lineCount > 1)
|
||||
replyLabel.isSingleLine = replyLabel.lineCount > 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -807,8 +814,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
private fun extensionIntentItemSelected(item: MenuItem) {
|
||||
val intent = item.intent ?: return
|
||||
try {
|
||||
val action = intent.action
|
||||
when (action) {
|
||||
when (intent.action) {
|
||||
INTENT_ACTION_EXTENSION_COMPOSE -> {
|
||||
val accountKeys = accountsAdapter.selectedAccountKeys
|
||||
intent.putExtra(EXTRA_TEXT, ParseUtils.parseString(editText.text))
|
||||
|
@ -1084,16 +1090,20 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val action = intent.action
|
||||
val hasVisibility = intent.hasExtra(EXTRA_VISIBILITY)
|
||||
val hasAccountKeys: Boolean
|
||||
if (intent.hasExtra(EXTRA_ACCOUNT_KEYS)) {
|
||||
val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS)
|
||||
accountsAdapter.selectedAccountKeys = accountKeys
|
||||
hasAccountKeys = true
|
||||
} else if (intent.hasExtra(EXTRA_ACCOUNT_KEY)) {
|
||||
val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
accountsAdapter.selectedAccountKeys = arrayOf(accountKey)
|
||||
hasAccountKeys = true
|
||||
} else {
|
||||
hasAccountKeys = false
|
||||
when {
|
||||
intent.hasExtra(EXTRA_ACCOUNT_KEYS) -> {
|
||||
val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS)
|
||||
accountsAdapter.selectedAccountKeys = accountKeys
|
||||
hasAccountKeys = true
|
||||
}
|
||||
intent.hasExtra(EXTRA_ACCOUNT_KEY) -> {
|
||||
val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
accountsAdapter.selectedAccountKeys = arrayOf(accountKey)
|
||||
hasAccountKeys = true
|
||||
}
|
||||
else -> {
|
||||
hasAccountKeys = false
|
||||
}
|
||||
}
|
||||
when (action) {
|
||||
Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE -> {
|
||||
|
@ -1102,7 +1112,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val stream = intent.getStreamExtra()
|
||||
if (stream != null) {
|
||||
val src = stream.toTypedArray()
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, true, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = true,
|
||||
deleteSrc = false
|
||||
))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
@ -1111,7 +1124,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val data = intent.data
|
||||
if (data != null) {
|
||||
val src = arrayOf(data)
|
||||
TaskStarter.execute(AddMediaTask(this, src, null, true, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, null,
|
||||
copySrc = true,
|
||||
deleteSrc = false
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1147,16 +1163,16 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
INTENT_ACTION_EDIT_DRAFT -> {
|
||||
val draft: Draft? = intent.getParcelableExtra(EXTRA_DRAFT)
|
||||
when (draft?.action_type) {
|
||||
return when (draft?.action_type) {
|
||||
Draft.Action.REPLY -> {
|
||||
return showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
}
|
||||
Draft.Action.QUOTE -> {
|
||||
return showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
|
||||
}
|
||||
else -> {
|
||||
showDefaultLabelAndHint()
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1786,7 +1802,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
s.setSpan(MarkForDeleteSpan(), start, start + count,
|
||||
Spanned.SPAN_INCLUSIVE_INCLUSIVE)
|
||||
}
|
||||
if (!imageSources.isEmpty()) {
|
||||
if (imageSources.isNotEmpty()) {
|
||||
val intent = ThemedMediaPickerActivity.withThemed(this@ComposeActivity)
|
||||
.getMedia(Uri.parse(imageSources[0]))
|
||||
.build()
|
||||
|
@ -1817,7 +1833,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
})
|
||||
editText.customSelectionActionModeCallback = this
|
||||
editText.imageInputListener = { contentInfo ->
|
||||
val task = AddMediaTask(this, arrayOf(contentInfo.contentUri), null, true, false)
|
||||
val task = AddMediaTask(this, arrayOf(contentInfo.contentUri), null,
|
||||
copySrc = true,
|
||||
deleteSrc = false
|
||||
)
|
||||
task.callback = {
|
||||
contentInfo.releasePermission()
|
||||
}
|
||||
|
@ -1887,7 +1906,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
}
|
||||
|
||||
class AttachedMediaItemTouchHelperCallback(adapter: SimpleItemTouchHelperCallback.ItemTouchHelperAdapter) : SimpleItemTouchHelperCallback(adapter) {
|
||||
class AttachedMediaItemTouchHelperCallback(adapter: ItemTouchHelperAdapter) : SimpleItemTouchHelperCallback(adapter) {
|
||||
|
||||
override fun isLongPressDragEnabled(): Boolean {
|
||||
return true
|
||||
|
@ -1907,7 +1926,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
|
||||
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
|
||||
// Fade out the view as it is swiped out of the parent's bounds
|
||||
val alpha = ALPHA_FULL - Math.abs(dY) / viewHolder.itemView.height.toFloat()
|
||||
val alpha = ALPHA_FULL - abs(dY) / viewHolder.itemView.height.toFloat()
|
||||
viewHolder.itemView.alpha = alpha
|
||||
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
|
||||
} else {
|
||||
|
@ -1925,7 +1944,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
}
|
||||
|
||||
companion object {
|
||||
val ALPHA_FULL = 1.0f
|
||||
const val ALPHA_FULL = 1.0f
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1997,7 +2016,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
set(value) {
|
||||
selection.clear()
|
||||
for (accountKey in value) {
|
||||
selection.put(accountKey, true)
|
||||
selection[accountKey] = true
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
@ -2035,7 +2054,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
fun toggleSelection(position: Int) {
|
||||
if (accounts == null || position < 0) return
|
||||
val account = accounts!![position]
|
||||
selection.put(account.key, true != selection[account.key])
|
||||
selection[account.key] = true != selection[account.key]
|
||||
activity.updateAccountSelectionState()
|
||||
activity.updateVisibilityState()
|
||||
activity.updateSummaryTextState()
|
||||
|
@ -2047,7 +2066,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
if (accounts == null || position < 0) return
|
||||
val account = accounts!![position]
|
||||
selection.clear()
|
||||
selection.put(account.key, true != selection[account.key])
|
||||
selection[account.key] = true != selection[account.key]
|
||||
activity.updateAccountSelectionState()
|
||||
activity.updateVisibilityState()
|
||||
activity.updateSummaryTextState()
|
||||
|
@ -2097,12 +2116,12 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
private class DisplayPlaceNameTask : AbstractTask<ParcelableLocation, List<Address>, ComposeActivity>() {
|
||||
|
||||
override fun doLongOperation(location: ParcelableLocation): List<Address>? {
|
||||
try {
|
||||
return try {
|
||||
val activity = callback ?: throw IOException("Interrupted")
|
||||
val gcd = Geocoder(activity, Locale.getDefault())
|
||||
return gcd.getFromLocation(location.latitude, location.longitude, 1)
|
||||
gcd.getFromLocation(location.latitude, location.longitude, 1)
|
||||
} catch (e: IOException) {
|
||||
return null
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2120,13 +2139,16 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
textView.spannable = ParcelableLocationUtils.getHumanReadableString(location, 3)
|
||||
textView.tag = location
|
||||
} else {
|
||||
val tag = textView.tag
|
||||
if (tag is Address) {
|
||||
textView.spannable = tag.locality
|
||||
} else if (tag is NoAddress) {
|
||||
textView.setText(R.string.label_location_your_coarse_location)
|
||||
} else {
|
||||
textView.setText(R.string.getting_location)
|
||||
when (val tag = textView.tag) {
|
||||
is Address -> {
|
||||
textView.spannable = tag.locality
|
||||
}
|
||||
is NoAddress -> {
|
||||
textView.setText(R.string.label_location_your_coarse_location)
|
||||
}
|
||||
else -> {
|
||||
textView.setText(R.string.getting_location)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -105,12 +105,12 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
?: return false
|
||||
// val file = File(folder, fileName)
|
||||
// file.delete()
|
||||
try {
|
||||
return try {
|
||||
DataImportExportUtils.exportData(activity, file, flags)
|
||||
return true
|
||||
true
|
||||
} catch (e: IOException) {
|
||||
Log.w(LOGTAG, e)
|
||||
return false
|
||||
false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val FRAGMENT_TAG = "import_settings_dialog"
|
||||
private const val FRAGMENT_TAG = "import_settings_dialog"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -111,12 +111,12 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
return false
|
||||
}
|
||||
if (!file.isFile) return false
|
||||
try {
|
||||
return try {
|
||||
DataImportExportUtils.importData(activity, file, flags)
|
||||
return true
|
||||
true
|
||||
} catch (e: IOException) {
|
||||
Log.w(LOGTAG, e)
|
||||
return false
|
||||
false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val FRAGMENT_TAG = "import_settings_dialog"
|
||||
private const val FRAGMENT_TAG = "import_settings_dialog"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -152,10 +152,10 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
return 0
|
||||
}
|
||||
if (!file.isFile) return 0
|
||||
try {
|
||||
return DataImportExportUtils.getImportedSettingsFlags(activity, file)
|
||||
return try {
|
||||
DataImportExportUtils.getImportedSettingsFlags(activity, file)
|
||||
} catch (e: IOException) {
|
||||
return 0
|
||||
0
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
|||
|
||||
companion object {
|
||||
|
||||
private val FRAGMENT_TAG = "read_settings_data_dialog"
|
||||
private const val FRAGMENT_TAG = "read_settings_data_dialog"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -87,13 +87,17 @@ class FileSelectorActivity : BaseActivity(), FileSelectorDialogFragment.Callback
|
|||
finish()
|
||||
return
|
||||
}
|
||||
if (checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
|
||||
showPickFileDialog()
|
||||
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
|
||||
val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS)
|
||||
} else {
|
||||
finishWithDeniedMessage()
|
||||
when {
|
||||
checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE) -> {
|
||||
showPickFileDialog()
|
||||
}
|
||||
Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN -> {
|
||||
val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS)
|
||||
}
|
||||
else -> {
|
||||
finishWithDeniedMessage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ import org.mariotaku.twidere.util.premium.ExtraFeaturesService
|
|||
import org.mariotaku.twidere.view.HomeDrawerLayout
|
||||
import org.mariotaku.twidere.view.TabPagerIndicator
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.math.floor
|
||||
|
||||
class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, SupportFragmentCallback,
|
||||
OnLongClickListener, DrawerLayout.DrawerListener {
|
||||
|
@ -860,7 +861,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
|||
"wide" -> resources.getDimension(R.dimen.preferred_tab_column_width_wide)
|
||||
else -> resources.getDimension(R.dimen.preferred_tab_column_width_normal)
|
||||
}
|
||||
mainTabs.columns = Math.floor(1.0 / pagerAdapter.getPageWidth(0)).toInt()
|
||||
mainTabs.columns = floor(1.0 / pagerAdapter.getPageWidth(0)).toInt()
|
||||
} else {
|
||||
mainPager.pageMargin = 0
|
||||
mainPager.setPageMarginDrawable(null)
|
||||
|
|
|
@ -119,7 +119,7 @@ class KeyboardShortcutPreferenceCompatActivity : BaseActivity(), OnClickListener
|
|||
|
||||
companion object {
|
||||
|
||||
val EXTRA_CONTEXT_TAG = "context_tag"
|
||||
val EXTRA_KEY_ACTION = "key_action"
|
||||
const val EXTRA_CONTEXT_TAG = "context_tag"
|
||||
const val EXTRA_KEY_ACTION = "key_action"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,8 @@ import org.mariotaku.twidere.view.viewer.MediaSwipeCloseContainer
|
|||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
import android.Manifest.permission as AndroidPermissions
|
||||
|
||||
class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeCloseContainer.Listener,
|
||||
|
@ -145,7 +147,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
activityLayout.statusBarAlpha = offset
|
||||
}
|
||||
try {
|
||||
actionBar.hideOffset = Math.round(controlBarHeight * (1f - offset))
|
||||
actionBar.hideOffset = (controlBarHeight * (1f - offset)).roundToInt()
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
// Some device will throw this exception
|
||||
hideOffsetNotSupported = true
|
||||
|
@ -367,10 +369,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
ParcelableMedia.Type.IMAGE -> {
|
||||
val mediaUrl = media.media_url ?: return Fragment.instantiate(this, ExternalBrowserPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
args.putParcelable(EXTRA_MEDIA_URI, Uri.parse(mediaUrl))
|
||||
if (mediaUrl.endsWith(".gif")) {
|
||||
return Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
return if (mediaUrl.endsWith(".gif")) {
|
||||
Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment
|
||||
} else {
|
||||
return Fragment.instantiate(this, ImagePageFragment::class.java.name, args) as MediaViewerFragment
|
||||
Fragment.instantiate(this, ImagePageFragment::class.java.name, args) as MediaViewerFragment
|
||||
}
|
||||
}
|
||||
ParcelableMedia.Type.ANIMATED_GIF, ParcelableMedia.Type.CARD_ANIMATED_GIF -> {
|
||||
|
@ -408,10 +410,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
}
|
||||
|
||||
override fun onSwipeOffsetChanged(offset: Int) {
|
||||
val offsetFactor = 1 - (Math.abs(offset).toFloat() / swipeContainer.height)
|
||||
val offsetFactor = 1 - (abs(offset).toFloat() / swipeContainer.height)
|
||||
swipeContainer.backgroundAlpha = offsetFactor
|
||||
val colorToolbar = overrideTheme.colorToolbar
|
||||
val alpha = Math.round(Color.alpha(colorToolbar) * offsetFactor).coerceIn(0..255)
|
||||
val alpha = (Color.alpha(colorToolbar) * offsetFactor).roundToInt().coerceIn(0..255)
|
||||
activityLayout.statusBarAlpha = alpha / 255f
|
||||
}
|
||||
|
||||
|
@ -464,11 +466,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
if (checkAllSelfPermissionsGranted(AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
|
||||
saveToStorage()
|
||||
} else {
|
||||
val permissions: Array<String>
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
|
||||
val permissions: Array<String> = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
|
||||
} else {
|
||||
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
PermissionRequestDialog.show(supportFragmentManager, getString(R.string.message_permission_request_save_media),
|
||||
permissions, REQUEST_PERMISSION_SAVE_MEDIA)
|
||||
|
@ -499,8 +500,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
|
||||
private fun saveToStorage() {
|
||||
val fileInfo = getCurrentCacheFileInfo(saveToStoragePosition) ?: return
|
||||
val type = (fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType
|
||||
val pubDir = when (type) {
|
||||
val pubDir = when ((fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType) {
|
||||
CacheFileType.VIDEO -> {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
||||
|
@ -636,10 +636,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
|
||||
companion object {
|
||||
|
||||
private val REQUEST_SHARE_MEDIA = 201
|
||||
private val REQUEST_PERMISSION_SAVE_MEDIA = 202
|
||||
private val REQUEST_PERMISSION_SHARE_MEDIA = 203
|
||||
private val REQUEST_SELECT_SAVE_MEDIA = 204
|
||||
private const val REQUEST_SHARE_MEDIA = 201
|
||||
private const val REQUEST_PERMISSION_SAVE_MEDIA = 202
|
||||
private const val REQUEST_PERMISSION_SHARE_MEDIA = 203
|
||||
private const val REQUEST_SELECT_SAVE_MEDIA = 204
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
const val FLAG_SYSTEM_UI_HIDE_BARS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||
|
|
|
@ -171,7 +171,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
|||
override fun onDismiss(listView: ListView, reverseSortedPositions: IntArray) {
|
||||
val adapter = suggestionsList.adapter as SuggestionsAdapter
|
||||
val ids = LongArray(reverseSortedPositions.size)
|
||||
for (i in 0 until reverseSortedPositions.size) {
|
||||
for (i in reverseSortedPositions.indices) {
|
||||
val position = reverseSortedPositions[i]
|
||||
val item = adapter.getSuggestionItem(position) ?: return
|
||||
ids[i] = item._id
|
||||
|
@ -505,7 +505,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
|||
private fun getActualPosition(position: Int): Int {
|
||||
var skipped = 0
|
||||
for (i in 0 until removedPositions.size) {
|
||||
if (position + skipped >= removedPositions.get(i)) {
|
||||
if (position + skipped >= removedPositions[i]) {
|
||||
skipped++
|
||||
}
|
||||
}
|
||||
|
@ -538,10 +538,10 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
|
|||
|
||||
companion object {
|
||||
|
||||
internal val VIEW_TYPE_SEARCH_HISTORY = 0
|
||||
internal val VIEW_TYPE_SAVED_SEARCH = 1
|
||||
internal val VIEW_TYPE_USER_SUGGESTION_ITEM = 2
|
||||
internal val VIEW_TYPE_USER_SCREEN_NAME = 3
|
||||
internal const val VIEW_TYPE_SEARCH_HISTORY = 0
|
||||
internal const val VIEW_TYPE_SAVED_SEARCH = 1
|
||||
internal const val VIEW_TYPE_USER_SUGGESTION_ITEM = 2
|
||||
internal const val VIEW_TYPE_USER_SCREEN_NAME = 3
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.mariotaku.twidere.util.DeviceUtils
|
|||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler
|
||||
import org.mariotaku.twidere.util.ThemeUtils
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartFragmentCallback {
|
||||
|
||||
|
@ -74,8 +75,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
|||
shouldTerminate = savedInstanceState.getBoolean(EXTRA_SHOULD_TERMINATE, shouldTerminate)
|
||||
} else if (intent.getBooleanExtra(EXTRA_SHOULD_TERMINATE, false)) {
|
||||
finishNoRestart()
|
||||
System.exit(0)
|
||||
return
|
||||
exitProcess(0)
|
||||
}
|
||||
|
||||
val backgroundOption = currentThemeBackgroundOption
|
||||
|
@ -349,8 +349,8 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
|||
|
||||
companion object {
|
||||
|
||||
val VIEW_TYPE_PREFERENCE_ENTRY = 0
|
||||
val VIEW_TYPE_HEADER_ENTRY = 1
|
||||
const val VIEW_TYPE_PREFERENCE_ENTRY = 0
|
||||
const val VIEW_TYPE_HEADER_ENTRY = 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,7 +424,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
|
|||
|
||||
companion object {
|
||||
|
||||
private val RESULT_SETTINGS_CHANGED = 10
|
||||
private const val RESULT_SETTINGS_CHANGED = 10
|
||||
|
||||
fun setShouldRecreate(activity: Activity) {
|
||||
if (activity !is SettingsActivity) return
|
||||
|
|
|
@ -428,23 +428,30 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
internal fun onSignInError(exception: Exception) {
|
||||
DebugLog.w(LOGTAG, "Sign in error", exception)
|
||||
var errorReason: String? = null
|
||||
if (exception is AuthenticityTokenException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
} else if (exception is WrongUserPassException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
} else if (exception is SignInTask.WrongBasicCredentialException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
} else if (exception is SignInTask.WrongAPIURLFormatException) {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
} else if (exception is LoginVerificationException) {
|
||||
Toast.makeText(this, R.string.message_toast_login_verification_failed, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "login_verification_failed"
|
||||
} else {
|
||||
Toast.makeText(this, exception.getErrorMessage(this), Toast.LENGTH_SHORT).show()
|
||||
when (exception) {
|
||||
is AuthenticityTokenException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
}
|
||||
is WrongUserPassException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
}
|
||||
is SignInTask.WrongBasicCredentialException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_username_password"
|
||||
}
|
||||
is SignInTask.WrongAPIURLFormatException -> {
|
||||
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "wrong_api_key"
|
||||
}
|
||||
is LoginVerificationException -> {
|
||||
Toast.makeText(this, R.string.message_toast_login_verification_failed, Toast.LENGTH_SHORT).show()
|
||||
errorReason = "login_verification_failed"
|
||||
}
|
||||
else -> {
|
||||
Toast.makeText(this, exception.getErrorMessage(this), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
Analyzer.log(SignIn(false, credentialsType = apiConfig.credentialsType,
|
||||
errorReason = errorReason, accountType = apiConfig.type))
|
||||
|
@ -809,10 +816,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
val oauth = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
|
||||
accountType = apiConfig.type, cls = TwitterOAuth::class.java)
|
||||
val accessToken: OAuthToken
|
||||
if (oauthVerifier != null) {
|
||||
accessToken = oauth.getAccessToken(requestToken, oauthVerifier)
|
||||
accessToken = if (oauthVerifier != null) {
|
||||
oauth.getAccessToken(requestToken, oauthVerifier)
|
||||
} else {
|
||||
accessToken = oauth.getAccessToken(requestToken)
|
||||
oauth.getAccessToken(requestToken)
|
||||
}
|
||||
auth = apiConfig.getOAuthAuthorization(accessToken) ?:
|
||||
throw MicroBlogException("Invalid OAuth credential")
|
||||
|
@ -823,7 +830,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(context)
|
||||
|
@ -901,7 +908,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
return authOAuth()
|
||||
}
|
||||
|
||||
@Throws(OAuthPasswordAuthenticator.AuthenticationException::class, MicroBlogException::class)
|
||||
@Throws(AuthenticationException::class, MicroBlogException::class)
|
||||
private fun authOAuth(): SignInResponse {
|
||||
val activity = activityRef.get() ?: throw InterruptedException()
|
||||
val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
||||
|
@ -940,7 +947,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
return getOAuthSignInResponse(activity, accessToken, Credentials.Type.XAUTH)
|
||||
}
|
||||
|
||||
@Throws(MicroBlogException::class, OAuthPasswordAuthenticator.AuthenticationException::class)
|
||||
@Throws(MicroBlogException::class, AuthenticationException::class)
|
||||
private fun authBasic(): SignInResponse {
|
||||
val activity = activityRef.get() ?: throw InterruptedException()
|
||||
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
||||
|
@ -962,7 +969,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
}
|
||||
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
|
@ -991,7 +998,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
|
@ -1018,7 +1025,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = apiUser.key
|
||||
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
|
@ -1040,11 +1047,11 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
return SignInResponse(account != null, authType, credentials, user, color, type, extras)
|
||||
}
|
||||
|
||||
internal class WrongBasicCredentialException : OAuthPasswordAuthenticator.AuthenticationException()
|
||||
internal class WrongBasicCredentialException : AuthenticationException()
|
||||
|
||||
internal class WrongAPIURLFormatException : OAuthPasswordAuthenticator.AuthenticationException()
|
||||
internal class WrongAPIURLFormatException : AuthenticationException()
|
||||
|
||||
internal inner class InputLoginVerificationCallback : OAuthPasswordAuthenticator.LoginVerificationCallback {
|
||||
internal inner class InputLoginVerificationCallback : LoginVerificationCallback {
|
||||
|
||||
override fun getLoginVerification(challengeType: String): String? {
|
||||
// Dismiss current progress dialog
|
||||
|
@ -1087,10 +1094,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
protected val profileImageSize: String = activity.getString(R.string.profile_image_size)
|
||||
|
||||
final override fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
|
||||
try {
|
||||
return SingleResponse.getInstance(performLogin())
|
||||
return try {
|
||||
SingleResponse.getInstance(performLogin())
|
||||
} catch (e: Exception) {
|
||||
return SingleResponse.getInstance(e)
|
||||
SingleResponse.getInstance(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1189,8 +1196,8 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
const val REQUEST_BROWSER_TWITTER_SIGN_IN = 101
|
||||
const val REQUEST_BROWSER_MASTODON_SIGN_IN = 102
|
||||
|
||||
private val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
|
||||
private val EXTRA_API_LAST_CHANGE = "api_last_change"
|
||||
private const val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
|
||||
private const val EXTRA_API_LAST_CHANGE = "api_last_change"
|
||||
|
||||
@Throws(IOException::class)
|
||||
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {
|
||||
|
|
|
@ -41,8 +41,8 @@ class ThemedMediaPickerActivity : MediaPickerActivity() {
|
|||
|
||||
companion object {
|
||||
|
||||
fun withThemed(context: Context): MediaPickerActivity.IntentBuilder {
|
||||
val builder = MediaPickerActivity.IntentBuilder(context, ThemedMediaPickerActivity::class.java)
|
||||
fun withThemed(context: Context): IntentBuilder {
|
||||
val builder = IntentBuilder(context, ThemedMediaPickerActivity::class.java)
|
||||
builder.cropImageActivityClass(ImageCropperActivity::class.java)
|
||||
builder.streamDownloaderClass(RestFuNetworkStreamDownloader::class.java)
|
||||
return builder
|
||||
|
|
|
@ -177,23 +177,14 @@ class TrendsLocationSelectorActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||
val view: View
|
||||
if (convertView != null) {
|
||||
view = convertView
|
||||
} else {
|
||||
view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
|
||||
}
|
||||
val view: View = convertView ?: inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
|
||||
view.findViewById<TextView>(android.R.id.text1).text = getGroup(groupPosition).name
|
||||
return view
|
||||
}
|
||||
|
||||
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||
val view: View
|
||||
if (convertView != null) {
|
||||
view = convertView
|
||||
} else {
|
||||
view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
}
|
||||
val view: View =
|
||||
convertView ?: inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
val location = getChild(groupPosition, childPosition)
|
||||
val text1 = view.findViewById<TextView>(android.R.id.text1)
|
||||
if (location.parentId == WORLDWIDE) {
|
||||
|
|
|
@ -95,8 +95,7 @@ class UserListSelectorActivity : BaseActivity(),
|
|||
listView.setOnScrollListener(handler)
|
||||
listView.setOnTouchListener(handler.touchListener)
|
||||
listView.onItemClickListener = OnItemClickListener { view, _, position, _ ->
|
||||
val item = view.getItemAtPosition(position)
|
||||
when (item) {
|
||||
when (val item = view.getItemAtPosition(position)) {
|
||||
is ParcelableUserList -> {
|
||||
val data = Intent()
|
||||
data.putExtra(EXTRA_USER_LIST, item)
|
||||
|
|
|
@ -114,7 +114,10 @@ class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.
|
|||
if (!fromCache) {
|
||||
showProgress()
|
||||
}
|
||||
return CacheUserSearchLoader(this, accountKey, query, !fromCache, true, true)
|
||||
return CacheUserSearchLoader(this, accountKey, query, !fromCache,
|
||||
fromCache = true,
|
||||
fromUser = true
|
||||
)
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<ParcelableUser>>) {
|
||||
|
@ -126,12 +129,16 @@ class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.
|
|||
listContainer.visibility = View.VISIBLE
|
||||
adapter.setData(data, true)
|
||||
loader as CacheUserSearchLoader
|
||||
if (data.isNotNullOrEmpty()) {
|
||||
showList()
|
||||
} else if (loader.query.isEmpty()) {
|
||||
showSearchHint()
|
||||
} else {
|
||||
showNotFound()
|
||||
when {
|
||||
data.isNotNullOrEmpty() -> {
|
||||
showList()
|
||||
}
|
||||
loader.query.isEmpty() -> {
|
||||
showSearchHint()
|
||||
}
|
||||
else -> {
|
||||
showNotFound()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ class WebLinkHandlerActivity : Activity() {
|
|||
startActivity(handledIntent)
|
||||
} else {
|
||||
if (!handledSuccessfully) {
|
||||
Analyzer.logException(TwitterLinkException("Unable to handle twitter uri " + uri))
|
||||
Analyzer.logException(TwitterLinkException("Unable to handle twitter uri $uri"))
|
||||
}
|
||||
val fallbackIntent = Intent(Intent.ACTION_VIEW, uri)
|
||||
fallbackIntent.addCategory(Intent.CATEGORY_BROWSABLE)
|
||||
|
@ -277,7 +277,7 @@ class WebLinkHandlerActivity : Activity() {
|
|||
sb.append(text)
|
||||
}
|
||||
if (!url.isNullOrEmpty()) {
|
||||
if (!sb.isEmpty()) {
|
||||
if (sb.isNotEmpty()) {
|
||||
sb.append(" ")
|
||||
}
|
||||
sb.append(url)
|
||||
|
@ -366,7 +366,7 @@ class WebLinkHandlerActivity : Activity() {
|
|||
"photo", "album", "paipai", "q", "userview", "dialogue")
|
||||
|
||||
|
||||
private val AUTHORITY_TWITTER_COM = "twitter.com"
|
||||
private const val AUTHORITY_TWITTER_COM = "twitter.com"
|
||||
|
||||
|
||||
private fun regulateTwitterUri(data: Uri): Uri {
|
||||
|
|
|
@ -63,12 +63,12 @@ interface IControlBarActivity {
|
|||
}
|
||||
val animator: ObjectAnimator
|
||||
val offset = activity.controlBarOffset
|
||||
if (visible) {
|
||||
animator = if (visible) {
|
||||
if (offset >= 1) return
|
||||
animator = ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 1f)
|
||||
ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 1f)
|
||||
} else {
|
||||
if (offset <= 0) return
|
||||
animator = ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 0f)
|
||||
ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 0f)
|
||||
}
|
||||
animator.interpolator = DecelerateInterpolator()
|
||||
animator.addListener(object : AnimatorListener {
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.mariotaku.twidere.model.AccountDetails
|
|||
import org.mariotaku.twidere.view.holder.AccountProfileImageViewHolder
|
||||
import org.mariotaku.twidere.view.transformer.AccountsSelectorTransformer
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
|
||||
class AccountSelectorAdapter(
|
||||
private val inflater: LayoutInflater,
|
||||
|
@ -46,7 +47,7 @@ class AccountSelectorAdapter(
|
|||
set(value) {
|
||||
if (value != null) {
|
||||
val previousAccounts = accounts
|
||||
if (previousAccounts != null) {
|
||||
field = if (previousAccounts != null) {
|
||||
val tmpList = arrayListOf(*value)
|
||||
val tmpResult = ArrayList<AccountDetails>()
|
||||
previousAccounts.forEach { previousAccount ->
|
||||
|
@ -56,9 +57,9 @@ class AccountSelectorAdapter(
|
|||
}
|
||||
}
|
||||
tmpResult.addAll(tmpList)
|
||||
field = tmpResult.toTypedArray()
|
||||
tmpResult.toTypedArray()
|
||||
} else {
|
||||
field = value
|
||||
value
|
||||
}
|
||||
} else {
|
||||
field = null
|
||||
|
@ -115,16 +116,16 @@ class AccountSelectorAdapter(
|
|||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return Math.max(3, accountsCount)
|
||||
return max(3, accountsCount)
|
||||
}
|
||||
|
||||
val accountStart: Int
|
||||
get() = Math.max(0, 3 - accountsCount)
|
||||
get() = max(0, 3 - accountsCount)
|
||||
|
||||
val accountsCount: Int
|
||||
get() {
|
||||
val accounts = this.accounts ?: return 0
|
||||
return Math.max(0, accounts.size - 1)
|
||||
return max(0, accounts.size - 1)
|
||||
}
|
||||
|
||||
override fun getPageWidth(position: Int): Float {
|
||||
|
|
|
@ -80,14 +80,18 @@ class DummyItemAdapter(
|
|||
}
|
||||
|
||||
override fun getStatus(position: Int, raw: Boolean): ParcelableStatus {
|
||||
if (adapter is ParcelableStatusesAdapter) {
|
||||
return adapter.getStatus(position, raw)
|
||||
} else if (adapter is VariousItemsAdapter) {
|
||||
return adapter.getItem(position) as ParcelableStatus
|
||||
} else if (adapter is ParcelableActivitiesAdapter) {
|
||||
return adapter.getActivity(position).activityStatus!!
|
||||
return when (adapter) {
|
||||
is ParcelableStatusesAdapter -> {
|
||||
adapter.getStatus(position, raw)
|
||||
}
|
||||
is VariousItemsAdapter -> {
|
||||
adapter.getItem(position) as ParcelableStatus
|
||||
}
|
||||
is ParcelableActivitiesAdapter -> {
|
||||
adapter.getActivity(position).activityStatus!!
|
||||
}
|
||||
else -> throw IndexOutOfBoundsException()
|
||||
}
|
||||
throw IndexOutOfBoundsException()
|
||||
}
|
||||
|
||||
override fun getStatusCount(raw: Boolean) = 0
|
||||
|
|
|
@ -150,20 +150,19 @@ class MessagesConversationAdapter(
|
|||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val countIndex = itemCounts.getItemCountIndex(position)
|
||||
when (countIndex) {
|
||||
return when (val countIndex = itemCounts.getItemCountIndex(position)) {
|
||||
ITEM_START_MESSAGE -> when (getMessage(position, reuse = true).message_type) {
|
||||
MessageType.STICKER -> {
|
||||
return ITEM_TYPE_STICKER_MESSAGE
|
||||
ITEM_TYPE_STICKER_MESSAGE
|
||||
}
|
||||
MessageType.CONVERSATION_CREATE, MessageType.JOIN_CONVERSATION,
|
||||
MessageType.PARTICIPANTS_LEAVE, MessageType.PARTICIPANTS_JOIN,
|
||||
MessageType.CONVERSATION_NAME_UPDATE, MessageType.CONVERSATION_AVATAR_UPDATE -> {
|
||||
return ITEM_TYPE_NOTICE_MESSAGE
|
||||
ITEM_TYPE_NOTICE_MESSAGE
|
||||
}
|
||||
else -> return ITEM_TYPE_TEXT_MESSAGE
|
||||
else -> ITEM_TYPE_TEXT_MESSAGE
|
||||
}
|
||||
ITEM_START_LOAD_OLDER -> return ITEM_LOAD_OLDER_INDICATOR
|
||||
ITEM_START_LOAD_OLDER -> ITEM_LOAD_OLDER_INDICATOR
|
||||
else -> throw UnsupportedCountIndexException(countIndex, position)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,10 +77,9 @@ class MessagesEntriesAdapter(
|
|||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val countIndex = itemCounts.getItemCountIndex(position)
|
||||
when (countIndex) {
|
||||
0 -> return ITEM_TYPE_MESSAGE_ENTRY
|
||||
1 -> return ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
return when (val countIndex = itemCounts.getItemCountIndex(position)) {
|
||||
0 -> ITEM_TYPE_MESSAGE_ENTRY
|
||||
1 -> ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
else -> throw UnsupportedCountIndexException(countIndex, position)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,13 +152,12 @@ class ParcelableActivitiesAdapter(
|
|||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
val countIndex = itemCounts.getItemCountIndex(position)
|
||||
when (countIndex) {
|
||||
return when (val countIndex = itemCounts.getItemCountIndex(position)) {
|
||||
ITEM_INDEX_ACTIVITY -> {
|
||||
return getRowId(position, false)
|
||||
getRowId(position, false)
|
||||
}
|
||||
else -> {
|
||||
return (countIndex.toLong() shl 32) or getItemViewType(position).toLong()
|
||||
(countIndex.toLong() shl 32) or getItemViewType(position).toLong()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +215,7 @@ class ParcelableActivitiesAdapter(
|
|||
return EmptyViewHolder(Space(context))
|
||||
}
|
||||
}
|
||||
throw UnsupportedOperationException("Unsupported viewType " + viewType)
|
||||
throw UnsupportedOperationException("Unsupported viewType $viewType")
|
||||
}
|
||||
|
||||
|
||||
|
@ -245,14 +244,12 @@ class ParcelableActivitiesAdapter(
|
|||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val countIndex = getItemCountIndex(position)
|
||||
when (countIndex) {
|
||||
when (val countIndex = getItemCountIndex(position)) {
|
||||
ITEM_INDEX_ACTIVITY -> {
|
||||
if (isGapItem(position)) {
|
||||
return ITEM_VIEW_TYPE_GAP
|
||||
}
|
||||
val action = getAction(position)
|
||||
when (action) {
|
||||
when (getAction(position)) {
|
||||
Activity.Action.MENTION, Activity.Action.QUOTE, Activity.Action.REPLY -> {
|
||||
return ITEM_VIEW_TYPE_STATUS
|
||||
}
|
||||
|
@ -350,12 +347,12 @@ class ParcelableActivitiesAdapter(
|
|||
throw IndexOutOfBoundsException("index: $position, valid range is $validRange")
|
||||
}
|
||||
val data = this.data!!
|
||||
if (reuse && data is ObjectCursor) {
|
||||
return if (reuse && data is ObjectCursor) {
|
||||
val activity = data.setInto(dataPosition, reuseActivity)
|
||||
activity.after_filtered_sources = null
|
||||
return activity
|
||||
activity
|
||||
} else {
|
||||
return data[dataPosition]
|
||||
data[dataPosition]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,7 +425,7 @@ class ParcelableActivitiesAdapter(
|
|||
internal val text2 = itemView.findViewById<TextView>(android.R.id.text2)
|
||||
|
||||
init {
|
||||
text2.setSingleLine(false)
|
||||
text2.isSingleLine = false
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
|
@ -529,7 +526,7 @@ class ParcelableActivitiesAdapter(
|
|||
result = 31 * result + timestamp.hashCode()
|
||||
result = 31 * result + gap.hashCode()
|
||||
result = 31 * result + action.hashCode()
|
||||
result = 31 * result + (filteredSources?.let { Arrays.hashCode(it) } ?: 0)
|
||||
result = 31 * result + (filteredSources?.contentHashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ class ParcelableGroupsAdapter(
|
|||
return LoadIndicatorViewHolder(view)
|
||||
}
|
||||
}
|
||||
throw IllegalStateException("Unknown view type " + viewType)
|
||||
throw IllegalStateException("Unknown view type $viewType")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
|
@ -142,6 +142,6 @@ class ParcelableGroupsAdapter(
|
|||
|
||||
companion object {
|
||||
|
||||
val ITEM_VIEW_TYPE_USER_LIST = 2
|
||||
const val ITEM_VIEW_TYPE_USER_LIST = 2
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,25 +171,29 @@ abstract class ParcelableStatusesAdapter(
|
|||
|
||||
override fun setData(data: List<ParcelableStatus>?): Boolean {
|
||||
var changed = true
|
||||
if (data == null) {
|
||||
displayPositions = null
|
||||
displayDataCount = 0
|
||||
} else if (data is ObjectCursor) {
|
||||
displayPositions = null
|
||||
displayDataCount = data.size
|
||||
} else {
|
||||
var filteredCount = 0
|
||||
displayPositions = IntArray(data.size).apply {
|
||||
data.forEachIndexed { i, item ->
|
||||
if (!item.is_gap && item.is_filtered) {
|
||||
filteredCount++
|
||||
} else {
|
||||
this[i - filteredCount] = i
|
||||
when (data) {
|
||||
null -> {
|
||||
displayPositions = null
|
||||
displayDataCount = 0
|
||||
}
|
||||
is ObjectCursor -> {
|
||||
displayPositions = null
|
||||
displayDataCount = data.size
|
||||
}
|
||||
else -> {
|
||||
var filteredCount = 0
|
||||
displayPositions = IntArray(data.size).apply {
|
||||
data.forEachIndexed { i, item ->
|
||||
if (!item.is_gap && item.is_filtered) {
|
||||
filteredCount++
|
||||
} else {
|
||||
this[i - filteredCount] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
displayDataCount = data.size - filteredCount
|
||||
changed = this.data != data
|
||||
}
|
||||
displayDataCount = data.size - filteredCount
|
||||
changed = this.data != data
|
||||
}
|
||||
this.data = data
|
||||
this.infoCache = if (data != null) arrayOfNulls(data.size) else null
|
||||
|
@ -324,7 +328,7 @@ abstract class ParcelableStatusesAdapter(
|
|||
return TimelineFilterHeaderViewHolder(this, view)
|
||||
}
|
||||
}
|
||||
throw IllegalStateException("Unknown view type " + viewType)
|
||||
throw IllegalStateException("Unknown view type $viewType")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
|
@ -350,8 +354,7 @@ abstract class ParcelableStatusesAdapter(
|
|||
if (position == 0 && ILoadMoreSupportAdapter.START in loadMoreIndicatorPosition) {
|
||||
return ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
}
|
||||
val countIndex = getItemCountIndex(position)
|
||||
when (countIndex) {
|
||||
when (val countIndex = getItemCountIndex(position)) {
|
||||
ITEM_INDEX_LOAD_START_INDICATOR, ITEM_INDEX_LOAD_END_INDICATOR -> {
|
||||
return ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
}
|
||||
|
@ -410,7 +413,7 @@ abstract class ParcelableStatusesAdapter(
|
|||
// lesser equals than read position
|
||||
if (positionKey <= 0) return RecyclerView.NO_POSITION
|
||||
val range = rangeOfSize(statusStartIndex, getStatusCount(raw))
|
||||
if (range.isEmpty() || range.start < 0) return RecyclerView.NO_POSITION
|
||||
if (range.isEmpty() || range.first < 0) return RecyclerView.NO_POSITION
|
||||
if (positionKey < getStatusPositionKey(range.last, raw)) {
|
||||
return range.last
|
||||
}
|
||||
|
@ -422,7 +425,7 @@ abstract class ParcelableStatusesAdapter(
|
|||
// lesser equals than read position
|
||||
if (sortId <= 0) return RecyclerView.NO_POSITION
|
||||
val range = rangeOfSize(statusStartIndex, getStatusCount(raw))
|
||||
if (range.isEmpty() || range.start < 0) return RecyclerView.NO_POSITION
|
||||
if (range.isEmpty() || range.first < 0) return RecyclerView.NO_POSITION
|
||||
if (sortId < getStatusSortId(range.last, raw)) {
|
||||
return range.last
|
||||
}
|
||||
|
@ -489,11 +492,11 @@ abstract class ParcelableStatusesAdapter(
|
|||
} else {
|
||||
dataPosition
|
||||
}
|
||||
if (reuse && data is ObjectCursor) {
|
||||
return if (reuse && data is ObjectCursor) {
|
||||
reuseStatus.is_filtered = false
|
||||
return data.setInto(listPosition, reuseStatus)
|
||||
data.setInto(listPosition, reuseStatus)
|
||||
} else {
|
||||
return data[listPosition]
|
||||
data[listPosition]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ class ParcelableUserListsAdapter(
|
|||
return LoadIndicatorViewHolder(view)
|
||||
}
|
||||
}
|
||||
throw IllegalStateException("Unknown view type " + viewType)
|
||||
throw IllegalStateException("Unknown view type $viewType")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
|
@ -122,7 +122,7 @@ class ParcelableUserListsAdapter(
|
|||
|
||||
companion object {
|
||||
|
||||
val ITEM_VIEW_TYPE_USER_LIST = 2
|
||||
const val ITEM_VIEW_TYPE_USER_LIST = 2
|
||||
|
||||
fun createUserListViewHolder(adapter: IUserListsAdapter<*>,
|
||||
inflater: LayoutInflater,
|
||||
|
|
|
@ -140,7 +140,7 @@ class ParcelableUsersAdapter(
|
|||
return LoadIndicatorViewHolder(view)
|
||||
}
|
||||
}
|
||||
throw IllegalStateException("Unknown view type " + viewType)
|
||||
throw IllegalStateException("Unknown view type $viewType")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
|
|
|
@ -77,7 +77,7 @@ class SelectableUsersAdapter(
|
|||
return LoadIndicatorViewHolder(view)
|
||||
}
|
||||
}
|
||||
throw IllegalStateException("Unknown view type " + viewType)
|
||||
throw IllegalStateException("Unknown view type $viewType")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
|
@ -89,18 +89,16 @@ class SelectableUsersAdapter(
|
|||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val countIndex = itemCounts.getItemCountIndex(position)
|
||||
when (countIndex) {
|
||||
ITEM_TYPE_START_INDICATOR, ITEM_TYPE_END_INDICATOR -> return ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
ITEM_TYPE_USER -> return ITEM_VIEW_TYPE_USER
|
||||
return when (val countIndex = itemCounts.getItemCountIndex(position)) {
|
||||
ITEM_TYPE_START_INDICATOR, ITEM_TYPE_END_INDICATOR -> ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
ITEM_TYPE_USER -> ITEM_VIEW_TYPE_USER
|
||||
else -> throw UnsupportedCountIndexException(countIndex, position)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
val countIndex = itemCounts.getItemCountIndex(position)
|
||||
return when (countIndex) {
|
||||
return when (val countIndex = itemCounts.getItemCountIndex(position)) {
|
||||
ITEM_TYPE_START_INDICATOR, ITEM_TYPE_END_INDICATOR -> (countIndex.toLong() shl 32)
|
||||
ITEM_TYPE_USER -> (countIndex.toLong() shl 32) or getUser(position).hashCode().toLong()
|
||||
else -> throw UnsupportedCountIndexException(countIndex, position)
|
||||
|
|
|
@ -36,11 +36,7 @@ class SimpleParcelableUsersAdapter(
|
|||
|
||||
override fun getItemId(position: Int): Long {
|
||||
val item = getItem(position)
|
||||
if (item != null) {
|
||||
return item.hashCode().toLong()
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
return item?.hashCode()?.toLong() ?: -1
|
||||
}
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
|
|
|
@ -80,10 +80,10 @@ class StatusDetailsAdapter(
|
|||
internal set
|
||||
var translationResult: TranslationResult? = null
|
||||
internal set(translation) {
|
||||
if (translation == null || status?.originalId != translation.id) {
|
||||
field = null
|
||||
field = if (translation == null || status?.originalId != translation.id) {
|
||||
null
|
||||
} else {
|
||||
field = translation
|
||||
translation
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ class StatusDetailsAdapter(
|
|||
if (position in typeStart until typeEnd) return type
|
||||
typeStart = typeEnd
|
||||
}
|
||||
throw IllegalStateException("Unknown position " + position)
|
||||
throw IllegalStateException("Unknown position $position")
|
||||
}
|
||||
|
||||
fun getItemTypeStart(position: Int): Int {
|
||||
|
@ -502,10 +502,10 @@ class StatusDetailsAdapter(
|
|||
var isConversationsLoading: Boolean
|
||||
get() = ILoadMoreSupportAdapter.START in loadMoreIndicatorPosition
|
||||
set(loading) {
|
||||
if (loading) {
|
||||
loadMoreIndicatorPosition = loadMoreIndicatorPosition or ILoadMoreSupportAdapter.START
|
||||
loadMoreIndicatorPosition = if (loading) {
|
||||
loadMoreIndicatorPosition or ILoadMoreSupportAdapter.START
|
||||
} else {
|
||||
loadMoreIndicatorPosition = loadMoreIndicatorPosition and ILoadMoreSupportAdapter.START.inv()
|
||||
loadMoreIndicatorPosition and ILoadMoreSupportAdapter.START.inv()
|
||||
}
|
||||
updateItemDecoration()
|
||||
}
|
||||
|
@ -513,10 +513,10 @@ class StatusDetailsAdapter(
|
|||
var isRepliesLoading: Boolean
|
||||
get() = ILoadMoreSupportAdapter.END in loadMoreIndicatorPosition
|
||||
set(loading) {
|
||||
if (loading) {
|
||||
loadMoreIndicatorPosition = loadMoreIndicatorPosition or ILoadMoreSupportAdapter.END
|
||||
loadMoreIndicatorPosition = if (loading) {
|
||||
loadMoreIndicatorPosition or ILoadMoreSupportAdapter.END
|
||||
} else {
|
||||
loadMoreIndicatorPosition = loadMoreIndicatorPosition and ILoadMoreSupportAdapter.END.inv()
|
||||
loadMoreIndicatorPosition and ILoadMoreSupportAdapter.END.inv()
|
||||
}
|
||||
updateItemDecoration()
|
||||
}
|
||||
|
|
|
@ -162,6 +162,6 @@ class SupportTabsAdapter(
|
|||
|
||||
companion object {
|
||||
|
||||
private val EXTRA_ADAPTER_POSITION = "adapter_position"
|
||||
private const val EXTRA_ADAPTER_POSITION = "adapter_position"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,12 +87,12 @@ class VariousItemsAdapter(
|
|||
}
|
||||
|
||||
private fun getItemViewType(obj: Any): Int {
|
||||
when (obj) {
|
||||
is ParcelableStatus -> return VIEW_TYPE_STATUS
|
||||
is ParcelableUser -> return VIEW_TYPE_USER
|
||||
is ParcelableUserList -> return VIEW_TYPE_USER_LIST
|
||||
is ParcelableHashtag -> return VIEW_TYPE_HASHTAG
|
||||
else -> throw UnsupportedOperationException("Unsupported object " + obj)
|
||||
return when (obj) {
|
||||
is ParcelableStatus -> VIEW_TYPE_STATUS
|
||||
is ParcelableUser -> VIEW_TYPE_USER
|
||||
is ParcelableUserList -> VIEW_TYPE_USER_LIST
|
||||
is ParcelableHashtag -> VIEW_TYPE_HASHTAG
|
||||
else -> throw UnsupportedOperationException("Unsupported object $obj")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,9 +112,9 @@ class VariousItemsAdapter(
|
|||
|
||||
companion object {
|
||||
|
||||
val VIEW_TYPE_STATUS = 1
|
||||
val VIEW_TYPE_USER = 2
|
||||
val VIEW_TYPE_USER_LIST = 3
|
||||
val VIEW_TYPE_HASHTAG = 4
|
||||
const val VIEW_TYPE_STATUS = 1
|
||||
const val VIEW_TYPE_USER = 2
|
||||
const val VIEW_TYPE_USER_LIST = 3
|
||||
const val VIEW_TYPE_HASHTAG = 4
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ interface ILoadMoreSupportAdapter {
|
|||
annotation class IndicatorPosition
|
||||
|
||||
companion object {
|
||||
val ITEM_VIEW_TYPE_LOAD_INDICATOR = 0
|
||||
const val ITEM_VIEW_TYPE_LOAD_INDICATOR = 0
|
||||
|
||||
const val NONE: Long = 0
|
||||
const val START: Long = 1
|
||||
|
|
|
@ -329,7 +329,7 @@ class TwidereApplication : Application(), OnSharedPreferenceChangeListener {
|
|||
|
||||
companion object {
|
||||
|
||||
private val KEY_KEYBOARD_SHORTCUT_INITIALIZED = "keyboard_shortcut_initialized"
|
||||
private const val KEY_KEYBOARD_SHORTCUT_INITIALIZED = "keyboard_shortcut_initialized"
|
||||
var instance: TwidereApplication? = null
|
||||
private set
|
||||
|
||||
|
|
|
@ -147,10 +147,10 @@ object profileImageStyleKey : KSimpleKey<Int>(KEY_PROFILE_IMAGE_STYLE, ImageShap
|
|||
|
||||
object mediaPreviewStyleKey : KSimpleKey<Int>(KEY_MEDIA_PREVIEW_STYLE, PreviewStyle.CROP) {
|
||||
override fun read(preferences: SharedPreferences): Int {
|
||||
when (preferences.getString(key, null)) {
|
||||
VALUE_MEDIA_PREVIEW_STYLE_SCALE -> return PreviewStyle.SCALE
|
||||
VALUE_MEDIA_PREVIEW_STYLE_REAL_SIZE -> return PreviewStyle.ACTUAL_SIZE
|
||||
else -> return PreviewStyle.CROP
|
||||
return when (preferences.getString(key, null)) {
|
||||
VALUE_MEDIA_PREVIEW_STYLE_SCALE -> PreviewStyle.SCALE
|
||||
VALUE_MEDIA_PREVIEW_STYLE_REAL_SIZE -> PreviewStyle.ACTUAL_SIZE
|
||||
else -> PreviewStyle.CROP
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.mariotaku.twidere.extension
|
||||
|
||||
import android.graphics.BitmapFactory
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
fun BitmapFactory.Options.calculateInSampleSize(preferredWidth: Int, preferredHeight: Int): Int {
|
||||
if (preferredHeight > outHeight && preferredWidth > outWidth) {
|
||||
|
@ -9,6 +11,7 @@ fun BitmapFactory.Options.calculateInSampleSize(preferredWidth: Int, preferredHe
|
|||
if (preferredHeight <= 0 && preferredWidth <= 0) {
|
||||
return 1
|
||||
}
|
||||
val result = Math.round(Math.max(outWidth, outHeight) / Math.max(preferredWidth, preferredHeight).toFloat())
|
||||
return Math.max(1, result)
|
||||
val result = (max(outWidth, outHeight) / max(preferredWidth, preferredHeight)
|
||||
.toFloat()).roundToInt()
|
||||
return max(1, result)
|
||||
}
|
|
@ -114,20 +114,20 @@ fun RequestManager.loadProfileImage(context: Context, conversation: ParcelableMe
|
|||
size: String? = null): RequestBuilder<*> {
|
||||
if (conversation.conversation_type == ParcelableMessageConversation.ConversationType.ONE_TO_ONE) {
|
||||
val user = conversation.user
|
||||
if (user != null) {
|
||||
return loadProfileImage(context, user, shapeStyle, cornerRadius, cornerRadiusRatio, size)
|
||||
return if (user != null) {
|
||||
loadProfileImage(context, user, shapeStyle, cornerRadius, cornerRadiusRatio, size)
|
||||
} else {
|
||||
// TODO: show default conversation icon
|
||||
return loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle,
|
||||
cornerRadius, cornerRadiusRatio)
|
||||
loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle,
|
||||
cornerRadius, cornerRadiusRatio)
|
||||
}
|
||||
} else {
|
||||
if (conversation.conversation_avatar != null) {
|
||||
return loadProfileImage(context, conversation.conversation_avatar, shapeStyle, cornerRadius,
|
||||
cornerRadiusRatio, size)
|
||||
return if (conversation.conversation_avatar != null) {
|
||||
loadProfileImage(context, conversation.conversation_avatar, shapeStyle, cornerRadius,
|
||||
cornerRadiusRatio, size)
|
||||
} else {
|
||||
return loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle,
|
||||
cornerRadius, cornerRadiusRatio)
|
||||
loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle,
|
||||
cornerRadius, cornerRadiusRatio)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,5 +30,5 @@ fun ListView.updateSelectionItems(menu: Menu) {
|
|||
val listCount = count
|
||||
menu.setItemAvailability(R.id.select_none, checkedCount > 0)
|
||||
menu.setItemAvailability(R.id.select_all, checkedCount < listCount)
|
||||
menu.setItemAvailability(R.id.invert_selection, checkedCount > 0 && checkedCount < listCount)
|
||||
menu.setItemAvailability(R.id.invert_selection, checkedCount in 1 until listCount)
|
||||
}
|
||||
|
|
|
@ -62,17 +62,17 @@ fun Rect.offsetEndTo(x: Int, layoutDirection: Int) {
|
|||
}
|
||||
|
||||
fun Rect.getStart(layoutDirection: Int): Int {
|
||||
if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||
return this.right
|
||||
return if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||
this.right
|
||||
} else {
|
||||
return this.left
|
||||
this.left
|
||||
}
|
||||
}
|
||||
|
||||
fun Rect.getEnd(layoutDirection: Int): Int {
|
||||
if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||
return this.left
|
||||
return if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||
this.left
|
||||
} else {
|
||||
return this.right
|
||||
this.right
|
||||
}
|
||||
}
|
|
@ -43,15 +43,19 @@ fun View.getFrame(rect: Rect) {
|
|||
@UiThread
|
||||
fun View.getFrameRelatedTo(rect: Rect, other: View? = null) {
|
||||
this.getFrame(rect)
|
||||
if (other == null) {
|
||||
offsetToRoot(this, rect)
|
||||
} else if (other === this) {
|
||||
rect.offsetTo(0, 0)
|
||||
} else if (other !== parent) {
|
||||
offsetToRoot(this, rect)
|
||||
other.getFrame(tempRect)
|
||||
offsetToRoot(other, tempRect)
|
||||
rect.offset(-tempRect.left, -tempRect.top)
|
||||
when {
|
||||
other == null -> {
|
||||
offsetToRoot(this, rect)
|
||||
}
|
||||
other === this -> {
|
||||
rect.offsetTo(0, 0)
|
||||
}
|
||||
other !== parent -> {
|
||||
offsetToRoot(this, rect)
|
||||
other.getFrame(tempRect)
|
||||
offsetToRoot(other, tempRect)
|
||||
rect.offset(-tempRect.left, -tempRect.top)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,5 +30,5 @@ fun ContentTypeField.getIntParameter(name: String, def: Int): Int {
|
|||
}
|
||||
|
||||
fun ContentTypeField.getBooleanParameter(name: String): Boolean {
|
||||
return getParameter(name).toBoolean()
|
||||
return this.getParameter(name)!!.toBoolean()
|
||||
}
|
|
@ -15,6 +15,7 @@ import org.mariotaku.twidere.util.InternalTwitterContentUtils
|
|||
import org.mariotaku.twidere.util.text.FanfouValidator
|
||||
import org.mariotaku.twidere.util.text.MastodonValidator
|
||||
import org.mariotaku.twidere.util.text.TwitterValidator
|
||||
import kotlin.math.min
|
||||
|
||||
fun AccountDetails.isOfficial(context: Context?): Boolean {
|
||||
if (context == null) {
|
||||
|
@ -115,10 +116,10 @@ val Array<AccountDetails>.textLimit: Int
|
|||
forEach { details ->
|
||||
val currentLimit = details.textLimit
|
||||
if (currentLimit != 0) {
|
||||
if (limit <= 0) {
|
||||
limit = currentLimit
|
||||
limit = if (limit <= 0) {
|
||||
currentLimit
|
||||
} else {
|
||||
limit = Math.min(limit, currentLimit)
|
||||
min(limit, currentLimit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,10 +175,10 @@ internal object AccountDataQueue {
|
|||
return callable.call()
|
||||
}
|
||||
val future = executor.submit(callable)
|
||||
try {
|
||||
return future.get(1, TimeUnit.SECONDS)
|
||||
return try {
|
||||
future.get(1, TimeUnit.SECONDS)
|
||||
} catch (e: TimeoutException) {
|
||||
return manager.getUserData(account, key)
|
||||
manager.getUserData(account, key)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,10 +190,10 @@ internal object AccountDataQueue {
|
|||
return callable.call()
|
||||
}
|
||||
val future = executor.submit(callable)
|
||||
try {
|
||||
return future.get(1, TimeUnit.SECONDS)
|
||||
return try {
|
||||
future.get(1, TimeUnit.SECONDS)
|
||||
} catch (e: TimeoutException) {
|
||||
return manager.peekAuthToken(account, authTokenType)
|
||||
manager.peekAuthToken(account, authTokenType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,12 +63,11 @@ fun Credentials.getAuthorization(cls: Class<*>?): Authorization {
|
|||
}
|
||||
|
||||
fun Credentials.getEndpoint(cls: Class<*>): Endpoint {
|
||||
val apiUrlFormat: String
|
||||
val noVersionSuffix = this.no_version_suffix
|
||||
if (!TextUtils.isEmpty(this.api_url_format)) {
|
||||
apiUrlFormat = this.api_url_format
|
||||
val apiUrlFormat: String = if (!TextUtils.isEmpty(this.api_url_format)) {
|
||||
this.api_url_format
|
||||
} else {
|
||||
apiUrlFormat = DEFAULT_TWITTER_API_URL_FORMAT
|
||||
DEFAULT_TWITTER_API_URL_FORMAT
|
||||
}
|
||||
val domain: String?
|
||||
val versionSuffix: String?
|
||||
|
@ -113,11 +112,10 @@ fun Credentials.getEndpoint(cls: Class<*>): Endpoint {
|
|||
}
|
||||
val endpointUrl = MicroBlogAPIFactory.getApiUrl(apiUrlFormat, domain, versionSuffix)
|
||||
if (this is OAuthCredentials) {
|
||||
val signEndpointUrl: String
|
||||
if (same_oauth_signing_url) {
|
||||
signEndpointUrl = endpointUrl
|
||||
val signEndpointUrl: String = if (same_oauth_signing_url) {
|
||||
endpointUrl
|
||||
} else {
|
||||
signEndpointUrl = MicroBlogAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix)
|
||||
MicroBlogAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix)
|
||||
}
|
||||
return OAuthEndpoint(endpointUrl, signEndpointUrl)
|
||||
}
|
||||
|
@ -180,11 +178,11 @@ internal fun Credentials.authorizationHeader(
|
|||
): String {
|
||||
val auth = getAuthorization(cls)
|
||||
val endpoint: Endpoint
|
||||
if (auth is OAuthAuthorization) {
|
||||
endpoint = OAuthEndpoint(TwidereMediaDownloader.getEndpoint(modifiedUri),
|
||||
TwidereMediaDownloader.getEndpoint(uri))
|
||||
endpoint = if (auth is OAuthAuthorization) {
|
||||
OAuthEndpoint(TwidereMediaDownloader.getEndpoint(modifiedUri),
|
||||
TwidereMediaDownloader.getEndpoint(uri))
|
||||
} else {
|
||||
endpoint = Endpoint(TwidereMediaDownloader.getEndpoint(modifiedUri))
|
||||
Endpoint(TwidereMediaDownloader.getEndpoint(modifiedUri))
|
||||
}
|
||||
val queries = MultiValueMap<String>()
|
||||
for (name in uri.queryParameterNames) {
|
||||
|
|
|
@ -122,23 +122,23 @@ fun Draft.readMimeMessageFrom(context: Context, st: InputStream): Boolean {
|
|||
fun Draft.getActionName(context: Context): String? {
|
||||
if (TextUtils.isEmpty(action_type)) return context.getString(R.string.update_status)
|
||||
when (action_type) {
|
||||
Draft.Action.UPDATE_STATUS, Draft.Action.UPDATE_STATUS_COMPAT_1,
|
||||
Draft.Action.UPDATE_STATUS_COMPAT_2 -> {
|
||||
Action.UPDATE_STATUS, Action.UPDATE_STATUS_COMPAT_1,
|
||||
Action.UPDATE_STATUS_COMPAT_2 -> {
|
||||
return context.getString(R.string.update_status)
|
||||
}
|
||||
Draft.Action.REPLY -> {
|
||||
Action.REPLY -> {
|
||||
return context.getString(R.string.action_reply)
|
||||
}
|
||||
Draft.Action.QUOTE -> {
|
||||
Action.QUOTE -> {
|
||||
return context.getString(R.string.action_quote)
|
||||
}
|
||||
Draft.Action.FAVORITE -> {
|
||||
Action.FAVORITE -> {
|
||||
return context.getString(R.string.action_favorite)
|
||||
}
|
||||
Draft.Action.RETWEET -> {
|
||||
Action.RETWEET -> {
|
||||
return context.getString(R.string.action_retweet)
|
||||
}
|
||||
Draft.Action.SEND_DIRECT_MESSAGE, Draft.Action.SEND_DIRECT_MESSAGE_COMPAT -> {
|
||||
Action.SEND_DIRECT_MESSAGE, Action.SEND_DIRECT_MESSAGE_COMPAT -> {
|
||||
return context.getString(R.string.send_direct_message)
|
||||
}
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ fun Draft.applyUpdateStatus(statusUpdate: ParcelableStatusUpdate) {
|
|||
|
||||
fun draftActionTypeString(@Draft.Action action: String?): String {
|
||||
return when (action) {
|
||||
Draft.Action.QUOTE -> "quote"
|
||||
Draft.Action.REPLY -> "reply"
|
||||
Action.QUOTE -> "quote"
|
||||
Action.REPLY -> "reply"
|
||||
else -> "tweet"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import androidx.core.os.LocaleListCompat
|
|||
import org.mariotaku.ktextension.localesCompat
|
||||
import org.mariotaku.twidere.model.presentation.LaunchPresentation
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
fun LaunchPresentation.shouldShow(context: Context): Boolean {
|
||||
// Check language
|
||||
|
@ -69,16 +71,16 @@ fun LaunchPresentation.Image.displayingScore(viewDensity: Float, viewWidth: Int,
|
|||
viewWidth < width && viewHeight < height -> {
|
||||
val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f)
|
||||
val diffH = (height / viewHeight.toFloat() - 1).coerceAtMost(0.5f)
|
||||
100 - Math.round(diffH * 100) - Math.round(diffW * 100)
|
||||
100 - (diffH * 100).roundToInt() - (diffW * 100).roundToInt()
|
||||
}
|
||||
else -> {
|
||||
val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f)
|
||||
val diffH = (height / viewHeight.toFloat() - 1).coerceAtMost(0.5f)
|
||||
100 - Math.round(diffH * 50) - Math.round(diffW * 50)
|
||||
100 - (diffH * 50).roundToInt() - (diffW * 50).roundToInt()
|
||||
}
|
||||
}
|
||||
if (this.density != 0f) {
|
||||
score += 100 - Math.round(Math.abs(this.density / viewDensity - 1).coerceAtMost(1f))
|
||||
score += 100 - abs(this.density / viewDensity - 1).coerceAtMost(1f).roundToInt()
|
||||
}
|
||||
return score
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ fun CardEntity.toParcelable(accountKey: UserKey, accountType: String): Parcelabl
|
|||
|
||||
fun ParcelableCardEntity.getAsBoolean(key: String, def: Boolean): Boolean {
|
||||
val value = getValue(key) ?: return def
|
||||
return value.value.toBoolean()
|
||||
return value.value!!.toBoolean()
|
||||
}
|
||||
|
||||
fun ParcelableCardEntity.getAsString(key: String, def: String?): String? {
|
||||
|
@ -71,9 +71,9 @@ fun ParcelableCardEntity.getAsLong(key: String, def: Long): Long {
|
|||
|
||||
fun ParcelableCardEntity.getAsDate(key: String, def: Date): Date {
|
||||
val value = getValue(key) ?: return def
|
||||
try {
|
||||
return ParcelableCardEntityUtils.sISOFormat.parse(value.value)
|
||||
return try {
|
||||
ParcelableCardEntityUtils.sISOFormat.parse(value.value)
|
||||
} catch (e: ParseException) {
|
||||
return def
|
||||
def
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ fun ParcelableMedia.getBestVideoUrlAndType(supportedTypes: Array<String>): Pair<
|
|||
val videoInfo = video_info ?: return Pair(mediaUrl, null)
|
||||
val firstMatch = videoInfo.variants.filter { variant ->
|
||||
supportedTypes.any { it.equals(variant.content_type, ignoreCase = true) }
|
||||
}.sortedByDescending(ParcelableMedia.VideoInfo.Variant::bitrate).firstOrNull() ?: return null
|
||||
}.maxBy(ParcelableMedia.VideoInfo.Variant::bitrate) ?: return null
|
||||
return Pair(firstMatch.url, firstMatch.content_type)
|
||||
}
|
||||
ParcelableMedia.Type.CARD_ANIMATED_GIF -> {
|
||||
|
|
|
@ -12,16 +12,16 @@ import org.mariotaku.twidere.util.BitmapFactoryUtils
|
|||
*/
|
||||
fun ParcelableMediaUpdate.getMimeType(resolver: ContentResolver): String? {
|
||||
val uri = Uri.parse(this.uri)
|
||||
return resolver.getType(uri) ?: when (type) {
|
||||
return resolver.getType(uri) ?: return when (type) {
|
||||
ParcelableMedia.Type.ANIMATED_GIF -> {
|
||||
return "image/gif"
|
||||
"image/gif"
|
||||
}
|
||||
ParcelableMedia.Type.IMAGE -> {
|
||||
val o = BitmapFactory.Options()
|
||||
o.inJustDecodeBounds = true
|
||||
BitmapFactoryUtils.decodeUri(resolver, uri, opts = o)
|
||||
return o.outMimeType
|
||||
o.outMimeType
|
||||
}
|
||||
else -> return null
|
||||
else -> null
|
||||
}
|
||||
}
|
|
@ -53,12 +53,12 @@ val ParcelableMessageConversation.readOnly: Boolean
|
|||
|
||||
var ParcelableMessageConversation.notificationDisabled: Boolean
|
||||
get() {
|
||||
when (conversation_extras_type) {
|
||||
return when (conversation_extras_type) {
|
||||
ExtrasType.TWITTER_OFFICIAL -> {
|
||||
return (conversation_extras as? TwitterOfficialConversationExtras)?.notificationsDisabled ?: false
|
||||
(conversation_extras as? TwitterOfficialConversationExtras)?.notificationsDisabled ?: false
|
||||
}
|
||||
else -> {
|
||||
return (conversation_extras as? DefaultConversationExtras)?.notificationsDisabled ?: false
|
||||
(conversation_extras as? DefaultConversationExtras)?.notificationsDisabled ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,42 +46,42 @@ internal fun getSummaryText(context: Context, manager: UserColorNameManager, nam
|
|||
} else {
|
||||
res.getQuantityString(R.plurals.N_users, users.size, users.size)
|
||||
}
|
||||
if (sender != null) {
|
||||
return res.getString(R.string.message_format_participants_join_added,
|
||||
manager.getDisplayName(sender, nameFirst), joinName)
|
||||
return if (sender != null) {
|
||||
res.getString(R.string.message_format_participants_join_added,
|
||||
manager.getDisplayName(sender, nameFirst), joinName)
|
||||
} else {
|
||||
return res.getString(R.string.message_format_participants_join, joinName)
|
||||
res.getString(R.string.message_format_participants_join, joinName)
|
||||
}
|
||||
}
|
||||
MessageType.PARTICIPANTS_LEAVE -> {
|
||||
val users = (extras as UserArrayExtras).users
|
||||
val res = context.resources
|
||||
if (users.size == 1) {
|
||||
return if (users.size == 1) {
|
||||
val displayName = manager.getDisplayName(users[0], nameFirst)
|
||||
return res.getString(R.string.message_format_participants_leave, displayName)
|
||||
res.getString(R.string.message_format_participants_leave, displayName)
|
||||
} else {
|
||||
val usersName = res.getQuantityString(R.plurals.N_users, users.size, users.size)
|
||||
return res.getString(R.string.message_format_participants_leave, usersName)
|
||||
res.getString(R.string.message_format_participants_leave, usersName)
|
||||
}
|
||||
}
|
||||
MessageType.CONVERSATION_NAME_UPDATE -> {
|
||||
extras as ConversationInfoUpdatedExtras
|
||||
val res = context.resources
|
||||
if (extras.user != null) {
|
||||
return res.getString(R.string.message_format_conversation_name_update_by_user,
|
||||
manager.getDisplayName(extras.user, nameFirst), extras.name)
|
||||
return if (extras.user != null) {
|
||||
res.getString(R.string.message_format_conversation_name_update_by_user,
|
||||
manager.getDisplayName(extras.user, nameFirst), extras.name)
|
||||
} else {
|
||||
return res.getString(R.string.message_format_conversation_name_update, extras.name)
|
||||
res.getString(R.string.message_format_conversation_name_update, extras.name)
|
||||
}
|
||||
}
|
||||
MessageType.CONVERSATION_AVATAR_UPDATE -> {
|
||||
extras as ConversationInfoUpdatedExtras
|
||||
val res = context.resources
|
||||
if (extras.user != null) {
|
||||
return res.getString(R.string.message_format_conversation_avatar_update_by_user,
|
||||
manager.getDisplayName(extras.user, nameFirst))
|
||||
return if (extras.user != null) {
|
||||
res.getString(R.string.message_format_conversation_avatar_update_by_user,
|
||||
manager.getDisplayName(extras.user, nameFirst))
|
||||
} else {
|
||||
return res.getString(R.string.message_format_conversation_avatar_update)
|
||||
res.getString(R.string.message_format_conversation_avatar_update)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ import org.mariotaku.twidere.model.UserKey
|
|||
* Created by mariotaku on 2017/4/23.
|
||||
*/
|
||||
fun ParcelableUserMention.getAcct(accountKey: UserKey): String {
|
||||
if (accountKey.host == key.host) {
|
||||
return screen_name
|
||||
return if (accountKey.host == key.host) {
|
||||
screen_name
|
||||
} else {
|
||||
return "$screen_name@${key.host}"
|
||||
"$screen_name@${key.host}"
|
||||
}
|
||||
}
|
|
@ -220,7 +220,11 @@ fun Status.applyTo(accountKey: UserKey, accountType: String, profileImageSize: S
|
|||
|
||||
fun Status.formattedTextWithIndices(): StatusTextWithIndices {
|
||||
val source = CodePointArray(this.fullText ?: this.text!!)
|
||||
val builder = HtmlBuilder(source, false, true, false)
|
||||
val builder = HtmlBuilder(source,
|
||||
throwExceptions = false,
|
||||
sourceIsEscaped = true,
|
||||
shouldReEscape = false
|
||||
)
|
||||
builder.addEntities(this)
|
||||
val textWithIndices = StatusTextWithIndices()
|
||||
val (text, spans) = builder.buildWithIndices()
|
||||
|
|
|
@ -29,14 +29,18 @@ fun Attachment.toParcelable(externalUrl: String?) : ParcelableMedia? {
|
|||
val mimeType = mimetype ?: return null
|
||||
val result = ParcelableMedia()
|
||||
|
||||
if (mimeType.startsWith("image/")) {
|
||||
result.type = ParcelableMedia.Type.IMAGE
|
||||
} else if (mimeType.startsWith("video/")) {
|
||||
result.type = ParcelableMedia.Type.VIDEO
|
||||
} else {
|
||||
// https://github.com/TwidereProject/Twidere-Android/issues/729
|
||||
// Skip unsupported attachment
|
||||
return null
|
||||
when {
|
||||
mimeType.startsWith("image/") -> {
|
||||
result.type = ParcelableMedia.Type.IMAGE
|
||||
}
|
||||
mimeType.startsWith("video/") -> {
|
||||
result.type = ParcelableMedia.Type.VIDEO
|
||||
}
|
||||
else -> {
|
||||
// https://github.com/TwidereProject/Twidere-Android/issues/729
|
||||
// Skip unsupported attachment
|
||||
return null
|
||||
}
|
||||
}
|
||||
result.width = width
|
||||
result.height = height
|
||||
|
|
|
@ -33,9 +33,9 @@ fun Extractor.extractMentionsAndNonMentionStartIndex(text: String, mentions: Arr
|
|||
if (entity.start != nextExpectedPos) break
|
||||
// Break at first mention not found in `inReplyTo.mentions`
|
||||
if (mentions?.none { entity.value.equals(it.screen_name, ignoreCase = true) } == true) break
|
||||
nextExpectedPos = (entity.end..text.indices.endInclusive).firstOrNull {
|
||||
nextExpectedPos = (entity.end..text.indices.last).firstOrNull {
|
||||
!text[it].isWhitespace()
|
||||
} ?: text.indices.endInclusive + 1
|
||||
} ?: text.indices.last + 1
|
||||
}
|
||||
return MentionsAndNonMentionStartIndex(entities, nextExpectedPos)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.mariotaku.twidere.extension.view
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.recyclerView
|
||||
import kotlin.math.max
|
||||
|
||||
fun RecyclerView.LayoutManager.calculateSpaceItemHeight(child: View, spaceViewType: Int, typeStart: Int): Int {
|
||||
val recyclerView = recyclerView ?: return 0
|
||||
|
@ -39,7 +40,7 @@ fun RecyclerView.LayoutManager.calculateSpaceItemHeight(child: View, spaceViewTy
|
|||
if (heightBeforeSpace != 0) {
|
||||
val spaceHeight = recyclerView.measuredHeight - recyclerView.paddingTop -
|
||||
recyclerView.paddingBottom - heightBeforeSpace
|
||||
return Math.max(0, spaceHeight)
|
||||
return max(0, spaceHeight)
|
||||
}
|
||||
return -1
|
||||
}
|
|
@ -48,14 +48,19 @@ class APIEditorDialogFragment : BaseDialogFragment() {
|
|||
val targetFragment = this.targetFragment
|
||||
val parentFragment = this.parentFragment
|
||||
val host = this.host
|
||||
if (targetFragment is APIEditorCallback) {
|
||||
targetFragment.onSaveAPIConfig(applyCustomAPIConfig())
|
||||
} else if (parentFragment is APIEditorCallback) {
|
||||
parentFragment.onSaveAPIConfig(applyCustomAPIConfig())
|
||||
} else if (host is APIEditorCallback) {
|
||||
host.onSaveAPIConfig(applyCustomAPIConfig())
|
||||
} else {
|
||||
kPreferences[defaultAPIConfigKey] = applyCustomAPIConfig()
|
||||
when {
|
||||
targetFragment is APIEditorCallback -> {
|
||||
targetFragment.onSaveAPIConfig(applyCustomAPIConfig())
|
||||
}
|
||||
parentFragment is APIEditorCallback -> {
|
||||
parentFragment.onSaveAPIConfig(applyCustomAPIConfig())
|
||||
}
|
||||
host is APIEditorCallback -> {
|
||||
host.onSaveAPIConfig(applyCustomAPIConfig())
|
||||
}
|
||||
else -> {
|
||||
kPreferences[defaultAPIConfigKey] = applyCustomAPIConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
|
@ -94,10 +99,10 @@ class APIEditorDialogFragment : BaseDialogFragment() {
|
|||
tag = "api_url_format_help")
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
apiConfig = savedInstanceState.getParcelable(EXTRA_API_CONFIG)!!
|
||||
apiConfig = if (savedInstanceState != null) {
|
||||
savedInstanceState.getParcelable(EXTRA_API_CONFIG)!!
|
||||
} else {
|
||||
apiConfig = arguments?.getParcelable(EXTRA_API_CONFIG) ?: kPreferences[defaultAPIConfigKey]
|
||||
arguments?.getParcelable(EXTRA_API_CONFIG) ?: kPreferences[defaultAPIConfigKey]
|
||||
}
|
||||
displayCustomApiConfig()
|
||||
}
|
||||
|
|
|
@ -103,8 +103,10 @@ abstract class AbsActivitiesFragment protected constructor() :
|
|||
registerForContextMenu(recyclerView)
|
||||
navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter,
|
||||
this)
|
||||
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, false,
|
||||
requestManager)
|
||||
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(
|
||||
pauseOnScroll = false, pauseOnFling = false,
|
||||
requestManager = requestManager
|
||||
)
|
||||
|
||||
val loaderArgs = Bundle(arguments)
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true)
|
||||
|
@ -237,7 +239,7 @@ abstract class AbsActivitiesFragment protected constructor() :
|
|||
adapter.getTimestamp(lastReadPosition)
|
||||
}
|
||||
lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0
|
||||
loadMore = activityRange.endInclusive in 0..lastVisibleItemPosition
|
||||
loadMore = activityRange.last in 0..lastVisibleItemPosition
|
||||
} else if (rememberPosition && readPositionTag != null) {
|
||||
val syncManager = timelineSyncManager
|
||||
val positionTag = this.readPositionTag
|
||||
|
@ -547,13 +549,13 @@ abstract class AbsActivitiesFragment protected constructor() :
|
|||
(recyclerView.layoutManager as LinearLayoutManager).orientation) {
|
||||
override fun isDividerEnabled(childPos: Int): Boolean {
|
||||
if (childPos >= layoutManager.itemCount || childPos < 0) return false
|
||||
when (adapter.getItemViewType(childPos)) {
|
||||
return when (adapter.getItemViewType(childPos)) {
|
||||
ITEM_VIEW_TYPE_STATUS, ITEM_VIEW_TYPE_TITLE_SUMMARY, ITEM_VIEW_TYPE_GAP,
|
||||
ITEM_VIEW_TYPE_STUB -> {
|
||||
return true
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.mariotaku.twidere.util.ContentScrollHandler.ContentListSupport
|
|||
import org.mariotaku.twidere.util.ListViewScrollHandler
|
||||
import org.mariotaku.twidere.util.ThemeUtils
|
||||
import org.mariotaku.twidere.util.TwidereColorUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/16.
|
||||
|
@ -211,10 +212,11 @@ abstract class AbsContentListViewFragment<A : ListAdapter> : BaseFragment(),
|
|||
}
|
||||
val density = resources.displayMetrics.density
|
||||
val progressCircleDiameter = swipeLayout.progressCircleDiameter
|
||||
val controlBarOffsetPixels = Math.round(activity.controlBarHeight * (1 - activity.controlBarOffset))
|
||||
val controlBarOffsetPixels =
|
||||
(activity.controlBarHeight * (1 - activity.controlBarOffset)).roundToInt()
|
||||
val swipeStart = systemWindowsInsets.top - controlBarOffsetPixels - progressCircleDiameter
|
||||
// 64: SwipeRefreshLayout.DEFAULT_CIRCLE_TARGET
|
||||
val swipeDistance = Math.round(64 * density)
|
||||
val swipeDistance = (64 * density).roundToInt()
|
||||
swipeLayout.setProgressViewOffset(false, swipeStart, swipeStart + swipeDistance)
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ abstract class AbsMediaStatusesFragment : AbsContentRecyclerViewFragment<Stagger
|
|||
val maxId = pagination?.maxId?.takeIf(String::isNotEmpty)
|
||||
val sinceId = pagination?.sinceId?.takeIf(String::isNotEmpty)
|
||||
if (sinceId == null && maxId != null) {
|
||||
if (data != null && !data.isEmpty()) {
|
||||
if (data != null && data.isNotEmpty()) {
|
||||
return changed
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,8 +147,10 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
|
|||
adapter.statusClickListener = this
|
||||
registerForContextMenu(recyclerView)
|
||||
navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter, this)
|
||||
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, false,
|
||||
requestManager)
|
||||
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(
|
||||
pauseOnScroll = false, pauseOnFling = false,
|
||||
requestManager = requestManager
|
||||
)
|
||||
|
||||
if (shouldInitLoader) {
|
||||
initLoaderIfNeeded()
|
||||
|
@ -288,15 +290,19 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
|
|||
} else {
|
||||
firstVisibleItemPosition
|
||||
}.coerceInOr(statusRange, -1)
|
||||
lastReadId = if (lastReadPosition < 0) {
|
||||
-1
|
||||
} else if (useSortIdAsReadPosition) {
|
||||
adapter.getStatusSortId(lastReadPosition, false)
|
||||
} else {
|
||||
adapter.getStatusPositionKey(lastReadPosition)
|
||||
lastReadId = when {
|
||||
lastReadPosition < 0 -> {
|
||||
-1
|
||||
}
|
||||
useSortIdAsReadPosition -> {
|
||||
adapter.getStatusSortId(lastReadPosition, false)
|
||||
}
|
||||
else -> {
|
||||
adapter.getStatusPositionKey(lastReadPosition)
|
||||
}
|
||||
}
|
||||
lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0
|
||||
loadMore = statusRange.endInclusive in 0..lastVisibleItemPosition
|
||||
loadMore = statusRange.last in 0..lastVisibleItemPosition
|
||||
} else if (rememberPosition) {
|
||||
val syncManager = timelineSyncManager
|
||||
val positionTag = this.readPositionTag
|
||||
|
@ -621,15 +627,19 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
|
|||
}
|
||||
}
|
||||
R.id.favorite -> {
|
||||
if (fragment.preferences[favoriteConfirmationKey]) {
|
||||
fragment.executeAfterFragmentResumed {
|
||||
FavoriteConfirmDialogFragment.show(it.childFragmentManager,
|
||||
when {
|
||||
fragment.preferences[favoriteConfirmationKey] -> {
|
||||
fragment.executeAfterFragmentResumed {
|
||||
FavoriteConfirmDialogFragment.show(it.childFragmentManager,
|
||||
status.account_key, status.id, status)
|
||||
}
|
||||
}
|
||||
status.is_favorite -> {
|
||||
fragment.twitterWrapper.destroyFavoriteAsync(status.account_key, status.id)
|
||||
}
|
||||
else -> {
|
||||
holder.playLikeAnimation(DefaultOnLikedListener(fragment.twitterWrapper, status))
|
||||
}
|
||||
} else if (status.is_favorite) {
|
||||
fragment.twitterWrapper.destroyFavoriteAsync(status.account_key, status.id)
|
||||
} else {
|
||||
holder.playLikeAnimation(DefaultOnLikedListener(fragment.twitterWrapper, status))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +663,7 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
|
|||
|
||||
fun handleActionActivityResult(fragment: BaseFragment, requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when (requestCode) {
|
||||
AbsStatusesFragment.REQUEST_FAVORITE_SELECT_ACCOUNT -> {
|
||||
REQUEST_FAVORITE_SELECT_ACCOUNT -> {
|
||||
if (resultCode != Activity.RESULT_OK || data == null) return
|
||||
val accountKey = data.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)!!
|
||||
val extras = data.getBundleExtra(EXTRA_EXTRAS)!!
|
||||
|
@ -667,7 +677,7 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
|
|||
fragment.twitterWrapper.createFavoriteAsync(accountKey, status)
|
||||
}
|
||||
}
|
||||
AbsStatusesFragment.REQUEST_RETWEET_SELECT_ACCOUNT -> {
|
||||
REQUEST_RETWEET_SELECT_ACCOUNT -> {
|
||||
if (resultCode != Activity.RESULT_OK || data == null) return
|
||||
val accountKey = data.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)!!
|
||||
val extras = data.getBundleExtra(EXTRA_EXTRAS)!!
|
||||
|
@ -719,16 +729,20 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
|
|||
return true
|
||||
}
|
||||
ACTION_STATUS_FAVORITE -> {
|
||||
if (fragment.preferences[favoriteConfirmationKey]) {
|
||||
fragment.executeAfterFragmentResumed {
|
||||
FavoriteConfirmDialogFragment.show(it.childFragmentManager,
|
||||
when {
|
||||
fragment.preferences[favoriteConfirmationKey] -> {
|
||||
fragment.executeAfterFragmentResumed {
|
||||
FavoriteConfirmDialogFragment.show(it.childFragmentManager,
|
||||
status.account_key, status.id, status)
|
||||
}
|
||||
}
|
||||
status.is_favorite -> {
|
||||
fragment.twitterWrapper.destroyFavoriteAsync(status.account_key, status.id)
|
||||
}
|
||||
else -> {
|
||||
val holder = fragment.recyclerView.findViewHolderForLayoutPosition(position) as StatusViewHolder
|
||||
holder.playLikeAnimation(DefaultOnLikedListener(fragment.twitterWrapper, status))
|
||||
}
|
||||
} else if (status.is_favorite) {
|
||||
fragment.twitterWrapper.destroyFavoriteAsync(status.account_key, status.id)
|
||||
} else {
|
||||
val holder = fragment.recyclerView.findViewHolderForLayoutPosition(position) as StatusViewHolder
|
||||
holder.playLikeAnimation(DefaultOnLikedListener(fragment.twitterWrapper, status))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -532,12 +532,16 @@ class AccountsDashboardFragment : BaseFragment(), LoaderCallbacks<AccountsInfo>,
|
|||
val width = if (bannerWidth > 0) bannerWidth else defWidth
|
||||
val bannerView = accountProfileBanner.nextView as ImageView
|
||||
val user = account.user
|
||||
val fallbackBanner = if (user.link_color != 0) {
|
||||
ColorDrawable(user.link_color)
|
||||
} else if (user.account_color != 0) {
|
||||
ColorDrawable(user.account_color)
|
||||
} else {
|
||||
ColorDrawable(Chameleon.getOverrideTheme(requireActivity(), activity).colorPrimary)
|
||||
val fallbackBanner = when {
|
||||
user.link_color != 0 -> {
|
||||
ColorDrawable(user.link_color)
|
||||
}
|
||||
user.account_color != 0 -> {
|
||||
ColorDrawable(user.account_color)
|
||||
}
|
||||
else -> {
|
||||
ColorDrawable(Chameleon.getOverrideTheme(requireActivity(), activity).colorPrimary)
|
||||
}
|
||||
}
|
||||
|
||||
requestManager.loadProfileBanner(requireContext(), account.user, width).fallback(fallbackBanner)
|
||||
|
|
|
@ -241,6 +241,6 @@ class AccountsManagerFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Li
|
|||
|
||||
companion object {
|
||||
|
||||
private val FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion"
|
||||
private const val FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
|
|||
filterItems = filterItemsInfo
|
||||
val entries = arrayOfNulls<String>(filterItems!!.size)
|
||||
val nameFirst = preferences[nameFirstKey]
|
||||
for (i in 0 until entries.size) {
|
||||
for (i in entries.indices) {
|
||||
val info = filterItems!![i]
|
||||
when (info.type) {
|
||||
FilterItemInfo.FILTER_TYPE_USER -> {
|
||||
|
@ -87,24 +87,29 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
val info = filterItems!![checkPositions.keyAt(i)]
|
||||
val value = info.value
|
||||
if (value is ParcelableUserMention) {
|
||||
userKeys.add(value.key)
|
||||
userValues.add(ContentValuesCreator.createFilteredUser(value))
|
||||
} else if (value is UserItem) {
|
||||
userKeys.add(value.key)
|
||||
userValues.add(createFilteredUser(value))
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_KEYWORD) {
|
||||
val keyword = ParseUtils.parseString(value)
|
||||
keywords.add(keyword)
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Keywords.VALUE, "#$keyword")
|
||||
keywordValues.add(values)
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_SOURCE) {
|
||||
val source = ParseUtils.parseString(value)
|
||||
sources.add(source)
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Sources.VALUE, source)
|
||||
sourceValues.add(values)
|
||||
when {
|
||||
value is ParcelableUserMention -> {
|
||||
userKeys.add(value.key)
|
||||
userValues.add(ContentValuesCreator.createFilteredUser(value))
|
||||
}
|
||||
value is UserItem -> {
|
||||
userKeys.add(value.key)
|
||||
userValues.add(createFilteredUser(value))
|
||||
}
|
||||
info.type == FilterItemInfo.FILTER_TYPE_KEYWORD -> {
|
||||
val keyword = ParseUtils.parseString(value)
|
||||
keywords.add(keyword)
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Keywords.VALUE, "#$keyword")
|
||||
keywordValues.add(values)
|
||||
}
|
||||
info.type == FilterItemInfo.FILTER_TYPE_SOURCE -> {
|
||||
val source = ParseUtils.parseString(value)
|
||||
sources.add(source)
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Sources.VALUE, source)
|
||||
sourceValues.add(values)
|
||||
}
|
||||
}
|
||||
}
|
||||
context?.contentResolver?.let { resolver ->
|
||||
|
@ -164,12 +169,15 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
|
||||
private fun getName(manager: UserColorNameManager, value: Any, nameFirst: Boolean): String {
|
||||
if (value is ParcelableUserMention) {
|
||||
return manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
|
||||
} else if (value is UserItem) {
|
||||
return manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
|
||||
} else
|
||||
return ParseUtils.parseString(value)
|
||||
return when (value) {
|
||||
is ParcelableUserMention -> {
|
||||
manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
|
||||
}
|
||||
is UserItem -> {
|
||||
manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
|
||||
}
|
||||
else -> ParseUtils.parseString(value)
|
||||
}
|
||||
}
|
||||
|
||||
internal data class FilterItemInfo(
|
||||
|
@ -194,7 +202,7 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
|
|||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "add_status_filter"
|
||||
const val FRAGMENT_TAG = "add_status_filter"
|
||||
|
||||
private fun createFilteredUser(item: UserItem): ContentValues {
|
||||
val values = ContentValues()
|
||||
|
|
|
@ -140,8 +140,8 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat(), IBaseFragmen
|
|||
|
||||
companion object {
|
||||
|
||||
private val REQUEST_PICK_RINGTONE = 301
|
||||
private val EXTRA_RINGTONE_PREFERENCE_KEY = "internal:ringtone_preference_key"
|
||||
private const val REQUEST_PICK_RINGTONE = 301
|
||||
private const val EXTRA_RINGTONE_PREFERENCE_KEY = "internal:ringtone_preference_key"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -61,11 +61,8 @@ class ColorPickerDialogFragment : BaseDialogFragment(), DialogInterface.OnClickL
|
|||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val color: Int
|
||||
val args = arguments
|
||||
if (savedInstanceState != null) {
|
||||
color = savedInstanceState.getInt(EXTRA_COLOR, Color.WHITE)
|
||||
} else {
|
||||
color = args!!.getInt(EXTRA_COLOR, Color.WHITE)
|
||||
}
|
||||
color =
|
||||
savedInstanceState?.getInt(EXTRA_COLOR, Color.WHITE) ?: args!!.getInt(EXTRA_COLOR, Color.WHITE)
|
||||
|
||||
val activity = activity
|
||||
val builder = AlertDialog.Builder(requireActivity())
|
||||
|
|
|
@ -48,7 +48,7 @@ class CreateUserBlockDialogFragment : AbsUserMuteBlockDialogFragment() {
|
|||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "create_user_block"
|
||||
const val FRAGMENT_TAG = "create_user_block"
|
||||
|
||||
fun show(fm: FragmentManager, user: ParcelableUser): CreateUserBlockDialogFragment {
|
||||
val args = Bundle()
|
||||
|
|
|
@ -49,7 +49,7 @@ class CreateUserMuteDialogFragment : AbsUserMuteBlockDialogFragment() {
|
|||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "create_user_mute"
|
||||
const val FRAGMENT_TAG = "create_user_mute"
|
||||
|
||||
fun show(fm: FragmentManager, user: ParcelableUser): CreateUserMuteDialogFragment {
|
||||
val args = Bundle()
|
||||
|
|
|
@ -51,6 +51,8 @@ import org.mariotaku.twidere.util.DataStoreUtils
|
|||
import org.mariotaku.twidere.util.DataStoreUtils.getTableNameByUri
|
||||
import org.mariotaku.twidere.util.ErrorInfoStore
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Displays statuses from database
|
||||
|
@ -241,8 +243,8 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
|||
fun replaceStatusStates(result: ParcelableStatus?) {
|
||||
if (result == null) return
|
||||
val lm = layoutManager
|
||||
val rangeStart = Math.max(adapter.activityStartIndex, lm.findFirstVisibleItemPosition())
|
||||
val rangeEnd = Math.min(lm.findLastVisibleItemPosition(), adapter.activityStartIndex + adapter.getActivityCount(false) - 1)
|
||||
val rangeStart = max(adapter.activityStartIndex, lm.findFirstVisibleItemPosition())
|
||||
val rangeEnd = min(lm.findLastVisibleItemPosition(), adapter.activityStartIndex + adapter.getActivityCount(false) - 1)
|
||||
loop@ for (i in rangeStart..rangeEnd) {
|
||||
val activity = adapter.getActivity(i, false)
|
||||
if (result.account_key == activity.account_key && result.id == activity.id) {
|
||||
|
@ -353,7 +355,7 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
|||
|
||||
class ActivityCursor(
|
||||
cursor: Cursor,
|
||||
indies: ObjectCursor.CursorIndices<ParcelableActivity>,
|
||||
indies: CursorIndices<ParcelableActivity>,
|
||||
val filteredUserIds: Array<UserKey>,
|
||||
val filteredUserNames: Array<String>,
|
||||
val filteredUserDescriptions: Array<String>
|
||||
|
|
|
@ -90,7 +90,7 @@ class DeleteUserListMembersDialogFragment : BaseDialogFragment(), DialogInterfac
|
|||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "destroy_user_list_member"
|
||||
const val FRAGMENT_TAG = "destroy_user_list_member"
|
||||
|
||||
fun show(fm: FragmentManager, userList: ParcelableUserList,
|
||||
vararg users: ParcelableUser): DeleteUserListMembersDialogFragment {
|
||||
|
|
|
@ -65,7 +65,7 @@ class DestroyFriendshipDialogFragment : BaseDialogFragment(), DialogInterface.On
|
|||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "destroy_friendship"
|
||||
const val FRAGMENT_TAG = "destroy_friendship"
|
||||
|
||||
fun show(fm: FragmentManager, user: ParcelableUser): DestroyFriendshipDialogFragment {
|
||||
val f = DestroyFriendshipDialogFragment()
|
||||
|
|
|
@ -69,7 +69,7 @@ class DestroyUserListSubscriptionDialogFragment : BaseDialogFragment(), DialogIn
|
|||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "destroy_user_list"
|
||||
const val FRAGMENT_TAG = "destroy_user_list"
|
||||
|
||||
fun show(fm: FragmentManager,
|
||||
userList: ParcelableUserList): DestroyUserListSubscriptionDialogFragment {
|
||||
|
|
|
@ -89,14 +89,19 @@ class ExtraFeaturesIntroductionDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
|
||||
private fun startActivityForResultOnTarget(intent: Intent) {
|
||||
if (targetFragment != null) {
|
||||
targetFragment?.startActivityForResult(intent, targetRequestCode)
|
||||
} else if (requestCode == 0) {
|
||||
startActivity(intent)
|
||||
} else if (parentFragment != null) {
|
||||
parentFragment?.startActivityForResult(intent, requestCode)
|
||||
} else {
|
||||
activity?.startActivityForResult(intent, requestCode)
|
||||
when {
|
||||
targetFragment != null -> {
|
||||
targetFragment?.startActivityForResult(intent, targetRequestCode)
|
||||
}
|
||||
requestCode == 0 -> {
|
||||
startActivity(intent)
|
||||
}
|
||||
parentFragment != null -> {
|
||||
parentFragment?.startActivityForResult(intent, requestCode)
|
||||
}
|
||||
else -> {
|
||||
activity?.startActivityForResult(intent, requestCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,12 +113,16 @@ class GroupFragment : AbsToolbarTabPagesFragment(), LoaderCallbacks<SingleRespon
|
|||
val twitter = MicroBlogAPIFactory.getInstance(context, accountKey) ?:
|
||||
throw MicroBlogException("No account")
|
||||
val group: Group
|
||||
if (groupId != null) {
|
||||
group = twitter.showGroup(groupId)
|
||||
} else if (groupName != null) {
|
||||
group = twitter.showGroupByName(groupName)
|
||||
} else {
|
||||
return SingleResponse()
|
||||
group = when {
|
||||
groupId != null -> {
|
||||
twitter.showGroup(groupId)
|
||||
}
|
||||
groupName != null -> {
|
||||
twitter.showGroupByName(groupName)
|
||||
}
|
||||
else -> {
|
||||
return SingleResponse()
|
||||
}
|
||||
}
|
||||
return SingleResponse.getInstance(ParcelableGroupUtils.from(group, accountKey, 0,
|
||||
group.isMember))
|
||||
|
|
|
@ -257,10 +257,10 @@ class HostMappingsListFragment : AbsContentListViewFragment<HostMappingsListFrag
|
|||
|
||||
companion object {
|
||||
|
||||
private val EXTRA_EDIT_MODE = "edit_mode"
|
||||
private val EXTRA_HOST = "host"
|
||||
private val EXTRA_ADDRESS = "address"
|
||||
private val EXTRA_EXCLUDED = "excluded"
|
||||
private const val EXTRA_EDIT_MODE = "edit_mode"
|
||||
private const val EXTRA_HOST = "host"
|
||||
private const val EXTRA_ADDRESS = "address"
|
||||
private const val EXTRA_EXCLUDED = "excluded"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -153,10 +153,10 @@ class NetworkDiagnosticsFragment : BaseFragment() {
|
|||
logPrintln()
|
||||
|
||||
val baseUrl: String
|
||||
if (details.credentials.api_url_format != null) {
|
||||
baseUrl = MicroBlogAPIFactory.getApiBaseUrl(details.credentials.api_url_format, "api")
|
||||
baseUrl = if (details.credentials.api_url_format != null) {
|
||||
MicroBlogAPIFactory.getApiBaseUrl(details.credentials.api_url_format, "api")
|
||||
} else {
|
||||
baseUrl = MicroBlogAPIFactory.getApiBaseUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api")
|
||||
MicroBlogAPIFactory.getApiBaseUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api")
|
||||
}
|
||||
val client = DependencyHolder.get(context).restHttpClient
|
||||
var response: HttpResponse? = null
|
||||
|
@ -319,8 +319,8 @@ class NetworkDiagnosticsFragment : BaseFragment() {
|
|||
startDiagnostics.setOnClickListener {
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
intent.type = "text/plain"
|
||||
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Twidere Network Diagnostics")
|
||||
intent.putExtra(android.content.Intent.EXTRA_TEXT, logText.text)
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, "Twidere Network Diagnostics")
|
||||
intent.putExtra(Intent.EXTRA_TEXT, logText.text)
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.action_send)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ abstract class ParcelableGroupsFragment : AbsContentListRecyclerViewFragment<Par
|
|||
get() = arguments?.getParcelable<UserKey?>(EXTRA_ACCOUNT_KEY)
|
||||
|
||||
protected fun hasMoreData(data: List<ParcelableGroup>?): Boolean {
|
||||
return data == null || !data.isEmpty()
|
||||
return data == null || data.isNotEmpty()
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<ParcelableGroup>?>, data: List<ParcelableGroup>?) {
|
||||
|
|
|
@ -46,6 +46,8 @@ import org.mariotaku.twidere.model.pagination.Pagination
|
|||
import org.mariotaku.twidere.model.pagination.SinceMaxPagination
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/12/3.
|
||||
|
@ -193,13 +195,12 @@ abstract class ParcelableStatusesFragment : AbsStatusesFragment() {
|
|||
fun removeStatus(statusId: String) {
|
||||
val list = adapterData ?: return
|
||||
val dataToRemove = HashSet<ParcelableStatus>()
|
||||
for (i in 0 until list.size) {
|
||||
val status = list[i]
|
||||
if (status.id == statusId || status.retweet_id == statusId) {
|
||||
dataToRemove.add(status)
|
||||
} else if (status.my_retweet_id == statusId) {
|
||||
status.my_retweet_id = null
|
||||
status.retweet_count = status.retweet_count - 1
|
||||
for (element in list) {
|
||||
if (element.id == statusId || element.retweet_id == statusId) {
|
||||
dataToRemove.add(element)
|
||||
} else if (element.my_retweet_id == statusId) {
|
||||
element.my_retweet_id = null
|
||||
element.retweet_count = element.retweet_count - 1
|
||||
}
|
||||
}
|
||||
if (list is MutableList) {
|
||||
|
@ -211,8 +212,8 @@ abstract class ParcelableStatusesFragment : AbsStatusesFragment() {
|
|||
fun replaceStatusStates(status: ParcelableStatus?) {
|
||||
if (status == null) return
|
||||
val lm = layoutManager
|
||||
val rangeStart = Math.max(adapter.statusStartIndex, lm.findFirstVisibleItemPosition())
|
||||
val rangeEnd = Math.min(lm.findLastVisibleItemPosition(), adapter.statusStartIndex + adapter.getStatusCount(false) - 1)
|
||||
val rangeStart = max(adapter.statusStartIndex, lm.findFirstVisibleItemPosition())
|
||||
val rangeEnd = min(lm.findLastVisibleItemPosition(), adapter.statusStartIndex + adapter.getStatusCount(false) - 1)
|
||||
for (i in rangeStart..rangeEnd) {
|
||||
val item = adapter.getStatus(i, false)
|
||||
if (status == item) {
|
||||
|
|
|
@ -73,7 +73,7 @@ abstract class ParcelableUserListsFragment : AbsContentListRecyclerViewFragment<
|
|||
}
|
||||
|
||||
protected fun hasMoreData(data: List<ParcelableUserList>?): Boolean {
|
||||
return data == null || !data.isEmpty()
|
||||
return data == null || data.isNotEmpty()
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<ParcelableUserList>>, data: List<ParcelableUserList>) {
|
||||
|
|
|
@ -270,7 +270,7 @@ abstract class ParcelableUsersFragment : AbsContentListRecyclerViewFragment<Parc
|
|||
}
|
||||
|
||||
protected fun hasMoreData(data: List<ParcelableUser>?): Boolean {
|
||||
return data == null || !data.isEmpty()
|
||||
return data == null || data.isNotEmpty()
|
||||
}
|
||||
|
||||
protected fun createMessageBusCallback(): Any {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue