Merge pull request #1325 from TacoTheDank/maintenance

Lints and Kotlin
This commit is contained in:
Tlaster 2020-06-09 12:26:01 +08:00 committed by GitHub
commit 4c884673ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
246 changed files with 1727 additions and 1943 deletions

View File

@ -226,6 +226,7 @@ dependencies {
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
implementation 'com.sprylab.android.texturevideoview:texturevideoview:1.2.1' implementation 'com.sprylab.android.texturevideoview:texturevideoview:1.2.1'
implementation 'com.squareup:pollexor:2.0.4' implementation 'com.squareup:pollexor:2.0.4'
implementation 'org.apache.commons:commons-text:1.8'
implementation "org.apache.james:apache-mime4j-core:${libVersions['Mime4J']}" implementation "org.apache.james:apache-mime4j-core:${libVersions['Mime4J']}"
implementation "org.apache.james:apache-mime4j-storage:${libVersions['Mime4J']}" implementation "org.apache.james:apache-mime4j-storage:${libVersions['Mime4J']}"
implementation "com.bluelinelabs:logansquare:${sharedVersions['LoganSquare']}" implementation "com.bluelinelabs:logansquare:${sharedVersions['LoganSquare']}"

View File

@ -316,9 +316,9 @@ class AccountsDumperPlugin(val context: Context) : DumperPlugin {
return JsonPath.parse(JsonSerializer.serialize(details), configuration) return JsonPath.parse(JsonSerializer.serialize(details), configuration)
} }
private fun Any.prettyPrint() = when { private fun Any.prettyPrint() = when (this) {
this is JSONObject -> toString(4) is JSONObject -> toString(4)
this is JSONArray -> toString(4) is JSONArray -> toString(4)
else -> toString() else -> toString()
} }

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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&lt;CharSequence, CharSequence&gt; 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;
}
}

View File

@ -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 &amp;#[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;
}
}

View File

@ -95,8 +95,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
protected void onClick() { protected void onClick() {
final Context context = getContext(); final Context context = getContext();
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class); final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_CONTEXT_TAG(), mContextTag); intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_CONTEXT_TAG, mContextTag);
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_KEY_ACTION(), mAction); intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_KEY_ACTION, mAction);
context.startActivity(intent); context.startActivity(intent);
} }

View File

@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
// Uses https://github.com/george-steel/android-utils/commit/289aff11e53593a55d780f9f5986e49343a79e55
package org.oshkimaadziig.george.androidutils; package org.oshkimaadziig.george.androidutils;
import android.text.Spannable; import android.text.Spannable;
@ -87,7 +89,7 @@ public class SpanFormatter {
if (typeTerm.equals("%")) { if (typeTerm.equals("%")) {
cookedArg = "%"; cookedArg = "%";
} else if (typeTerm.equals("%")) { } else if (typeTerm.equals("n")) {
cookedArg = "\n"; cookedArg = "\n";
} else { } else {
int argIdx; int argIdx;

View File

@ -25,26 +25,38 @@ import java.util.*
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
object LocaleHelperAccessor { object LocaleHelperAccessor {
fun forLanguageTag(str: String): Locale { fun forLanguageTag(str: String): Locale {
if (str.contains("-")) { when {
val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray() str.contains("-") -> {
if (args.size > 2) { val args = str.split("-").dropLastWhile { it.isEmpty() }.toTypedArray()
return Locale(args[0], args[1], args[2]) when {
} else if (args.size > 1) { args.size > 2 -> {
return Locale(args[0], args[1]) return Locale(args[0], args[1], args[2])
} else if (args.size == 1) { }
return Locale(args[0]) args.size > 1 -> {
return Locale(args[0], args[1])
}
args.size == 1 -> {
return Locale(args[0])
}
}
} }
} else if (str.contains("_")) { str.contains("_") -> {
val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray() val args = str.split("_").dropLastWhile { it.isEmpty() }.toTypedArray()
if (args.size > 2) { when {
return Locale(args[0], args[1], args[2]) args.size > 2 -> {
} else if (args.size > 1) { return Locale(args[0], args[1], args[2])
return Locale(args[0], args[1]) }
} else if (args.size == 1) { args.size > 1 -> {
return Locale(args[0]) return Locale(args[0], args[1])
}
args.size == 1 -> {
return Locale(args[0])
}
}
}
else -> {
return Locale(str)
} }
} else {
return Locale(str)
} }
throw IllegalArgumentException("Can not parse language tag: [$str]") throw IllegalArgumentException("Can not parse language tag: [$str]")

View File

@ -10,23 +10,23 @@ import android.os.Handler
fun AccountManager.addOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener, fun AccountManager.addOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener,
handler: Handler? = null, updateImmediately: Boolean = false): Boolean { handler: Handler? = null, updateImmediately: Boolean = false): Boolean {
try { return try {
this.addOnAccountsUpdatedListener(listener, handler, updateImmediately) this.addOnAccountsUpdatedListener(listener, handler, updateImmediately)
return true true
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
return false false
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
return false false
} }
} }
fun AccountManager.removeOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener): Boolean { fun AccountManager.removeOnAccountsUpdatedListenerSafe(listener: OnAccountsUpdateListener): Boolean {
try { return try {
this.removeOnAccountsUpdatedListener(listener) this.removeOnAccountsUpdatedListener(listener)
return true true
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
return false false
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
return false false
} }
} }

View File

@ -13,10 +13,10 @@ fun Collection<*>?.isNullOrEmpty(): Boolean {
} }
fun <T> MutableCollection<T>.addAllEnhanced(collection: Collection<T>, ignoreDuplicates: Boolean): Boolean { fun <T> MutableCollection<T>.addAllEnhanced(collection: Collection<T>, ignoreDuplicates: Boolean): Boolean {
if (ignoreDuplicates) { return if (ignoreDuplicates) {
return addAll(collection.filter { it !in this }) addAll(collection.filter { it !in this })
} else { } else {
return addAll(collection) addAll(collection)
} }
} }
@ -41,7 +41,7 @@ fun <E> Collection<E>.contentEquals(other: Collection<E>): Boolean {
inline fun <reified T> List<T>.subArray(range: IntRange): Array<T> { inline fun <reified T> List<T>.subArray(range: IntRange): Array<T> {
return Array(range.count()) { return Array(range.count()) {
this[range.start + it] this[range.first + it]
} }
} }

View File

@ -20,11 +20,11 @@ fun Context.checkAnySelfPermissionsGranted(vararg permissions: String): Boolean
fun Context.unregisterReceiverSafe(receiver: BroadcastReceiver?): Boolean { fun Context.unregisterReceiverSafe(receiver: BroadcastReceiver?): Boolean {
if (receiver == null) return false if (receiver == null) return false
try { return try {
unregisterReceiver(receiver) unregisterReceiver(receiver)
return true true
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
return false false
} }
} }

View File

@ -26,7 +26,7 @@ fun Cursor.safeGetInt(columnIndex: Int, def: Int = -1) = try {
def def
} }
fun Cursor.safeGetString(columnIndex: Int, def: String = "") = try { fun Cursor.safeGetString(columnIndex: Int, def: String = ""): String = try {
getString(columnIndex) getString(columnIndex)
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
def def

View File

@ -58,10 +58,10 @@ val Locale.bcp47Tag: String
} }
val bcp47Tag = StringBuilder(language) val bcp47Tag = StringBuilder(language)
if (!country.isEmpty()) { if (country.isNotEmpty()) {
bcp47Tag.append(SEP).append(country) bcp47Tag.append(SEP).append(country)
} }
if (!variant.isEmpty()) { if (variant.isNotEmpty()) {
bcp47Tag.append(SEP).append(variant) bcp47Tag.append(SEP).append(variant)
} }

View File

@ -48,7 +48,7 @@ fun Number.toLocalizedString(locale: Locale = Locale.getDefault()): String {
val Int.nextPowerOf2: Int val Int.nextPowerOf2: Int
get() { get() {
var n = this var n = this
if (n <= 0 || n > 1 shl 30) throw IllegalArgumentException("n is invalid: " + n) if (n <= 0 || n > 1 shl 30) throw IllegalArgumentException("n is invalid: $n")
n -= 1 n -= 1
n = n or (n shr 16) n = n or (n shr 16)
n = n or (n shr 8) n = n or (n shr 8)

View File

@ -6,5 +6,5 @@ import androidx.recyclerview.widget.RecyclerView
* Created by mariotaku on 16/8/21. * Created by mariotaku on 16/8/21.
*/ */
fun RecyclerView.Adapter<*>.findPositionByItemId(itemId: Long): Int { fun RecyclerView.Adapter<*>.findPositionByItemId(itemId: Long): Int {
return (0 until itemCount).firstOrNull { getItemId(it) == itemId } ?: androidx.recyclerview.widget.RecyclerView.NO_POSITION return (0 until itemCount).firstOrNull { getItemId(it) == itemId } ?: RecyclerView.NO_POSITION
} }

View File

@ -40,5 +40,5 @@ fun InputStream.expectLine(string: String = "", charset: Charset = Charset.defau
fun InputStream.expectBytes(bytes: ByteArray): Boolean { fun InputStream.expectBytes(bytes: ByteArray): Boolean {
val readBytes = ByteArray(bytes.size) val readBytes = ByteArray(bytes.size)
read(readBytes) read(readBytes)
return Arrays.equals(readBytes, bytes) return readBytes.contentEquals(bytes)
} }

View File

@ -35,20 +35,24 @@ object InternalActivityCreator {
activity.maxSortPosition = activity.minSortPosition activity.maxSortPosition = activity.minSortPosition
activity.createdAt = status.getCreatedAt() activity.createdAt = status.getCreatedAt()
if (status.getInReplyToUserId() == accountId) { when {
activity.action = Activity.Action.REPLY status.getInReplyToUserId() == accountId -> {
activity.targetStatuses = arrayOf(status) activity.action = Activity.Action.REPLY
activity.targetStatuses = arrayOf(status)
//TODO set target statuses (in reply to status) //TODO set target statuses (in reply to status)
activity.targetObjectStatuses = arrayOfNulls<Status>(0) activity.targetObjectStatuses = arrayOfNulls<Status>(0)
} else if (status.quotedStatus?.user?.id == accountId) { }
activity.action = Activity.Action.QUOTE status.quotedStatus?.user?.id == accountId -> {
activity.targetStatuses = arrayOf(status) activity.action = Activity.Action.QUOTE
activity.targetObjectStatuses = arrayOfNulls<Status>(0) activity.targetStatuses = arrayOf(status)
} else { activity.targetObjectStatuses = arrayOfNulls<Status>(0)
activity.action = Activity.Action.MENTION }
activity.targetUsers = arrayOfNulls<User>(0) else -> {
activity.targetObjectStatuses = arrayOf(status) activity.action = Activity.Action.MENTION
activity.targetUsers = arrayOfNulls<User>(0)
activity.targetObjectStatuses = arrayOf(status)
}
} }
activity.sourcesSize = 1 activity.sourcesSize = 1
activity.sources = arrayOf(status.getUser()) activity.sources = arrayOf(status.getUser())

View File

@ -13,8 +13,7 @@ class AssistLauncherActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val prefs = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) val prefs = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
val composeNowAction = prefs.getString(KEY_COMPOSE_NOW_ACTION, VALUE_COMPOSE_NOW_ACTION_COMPOSE) val action = when (prefs.getString(KEY_COMPOSE_NOW_ACTION, VALUE_COMPOSE_NOW_ACTION_COMPOSE)) {
val action = when (composeNowAction) {
VALUE_COMPOSE_NOW_ACTION_TAKE_PHOTO -> INTENT_ACTION_COMPOSE_TAKE_PHOTO VALUE_COMPOSE_NOW_ACTION_TAKE_PHOTO -> INTENT_ACTION_COMPOSE_TAKE_PHOTO
VALUE_COMPOSE_NOW_ACTION_PICK_IMAGE -> INTENT_ACTION_COMPOSE_PICK_IMAGE VALUE_COMPOSE_NOW_ACTION_PICK_IMAGE -> INTENT_ACTION_COMPOSE_PICK_IMAGE
else -> INTENT_ACTION_COMPOSE else -> INTENT_ACTION_COMPOSE

View File

@ -300,7 +300,7 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
for (i in 0 until handlerFilter.countDataAuthorities()) { for (i in 0 until handlerFilter.countDataAuthorities()) {
val authorityEntry = handlerFilter.getDataAuthority(i) val authorityEntry = handlerFilter.getDataAuthority(i)
val port = authorityEntry.port val port = authorityEntry.port
intentFilter.addDataAuthority(authorityEntry.host, if (port < 0) null else Integer.toString(port)) intentFilter.addDataAuthority(authorityEntry.host, if (port < 0) null else port.toString())
} }
try { try {
adapter.enableForegroundDispatch(this, intent, arrayOf(intentFilter), null) adapter.enableForegroundDispatch(this, intent, arrayOf(intentFilter), null)
@ -469,20 +469,20 @@ open class BaseActivity : ChameleonActivity(), IBaseActivity<BaseActivity>, IThe
} }
private fun newInstance(name: String, context: Context, attrs: AttributeSet): View? { private fun newInstance(name: String, context: Context, attrs: AttributeSet): View? {
try { return try {
val cls = findClass(name) ?: throw ClassNotFoundException(name) val cls = findClass(name) ?: throw ClassNotFoundException(name)
val constructor = cls.getConstructor(Context::class.java, AttributeSet::class.java) val constructor = cls.getConstructor(Context::class.java, AttributeSet::class.java)
return constructor.newInstance(context, attrs) as View constructor.newInstance(context, attrs) as View
} catch (e: InstantiationException) { } catch (e: InstantiationException) {
return null null
} catch (e: IllegalAccessException) { } catch (e: IllegalAccessException) {
return null null
} catch (e: InvocationTargetException) { } catch (e: InvocationTargetException) {
return null null
} catch (e: NoSuchMethodException) { } catch (e: NoSuchMethodException) {
return null null
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
return null null
} }
} }

View File

@ -69,7 +69,7 @@ class ColorPickerDialogActivity : BaseActivity(), Callback {
companion object { companion object {
val RESULT_CLEARED = -2 const val RESULT_CLEARED = -2
} }
} }

View File

@ -113,6 +113,7 @@ import java.text.Normalizer
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.math.abs
import android.Manifest.permission as AndroidPermission import android.Manifest.permission as AndroidPermission
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
@ -394,7 +395,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> { REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> {
if (resultCode == Activity.RESULT_OK && data != null) { if (resultCode == Activity.RESULT_OK && data != null) {
val src = MediaPickerActivity.getMediaUris(data) val src = MediaPickerActivity.getMediaUris(data)
TaskStarter.execute(AddMediaTask(this, src, null, false, false)) TaskStarter.execute(AddMediaTask(this, src, null,
copySrc = false,
deleteSrc = false
))
val extras = data.getBundleExtra(MediaPickerActivity.EXTRA_EXTRAS) val extras = data.getBundleExtra(MediaPickerActivity.EXTRA_EXTRAS)
if (extras?.getBoolean(EXTRA_IS_POSSIBLY_SENSITIVE) == true) { if (extras?.getBoolean(EXTRA_IS_POSSIBLY_SENSITIVE) == true) {
possiblySensitive = true possiblySensitive = true
@ -431,7 +435,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
val src = MediaPickerActivity.getMediaUris(data)?.takeIf(Array<Uri>::isNotEmpty) ?: val src = MediaPickerActivity.getMediaUris(data)?.takeIf(Array<Uri>::isNotEmpty) ?:
data.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)?.let { arrayOf(it) } data.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)?.let { arrayOf(it) }
if (src != null) { if (src != null) {
TaskStarter.execute(AddMediaTask(this, src, null, false, false)) TaskStarter.execute(AddMediaTask(this, src, null,
copySrc = false,
deleteSrc = false
))
} }
} }
} }
@ -509,7 +516,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
} }
replyLabel -> { replyLabel -> {
if (replyLabel.visibility != View.VISIBLE) return if (replyLabel.visibility != View.VISIBLE) return
replyLabel.setSingleLine(replyLabel.lineCount > 1) replyLabel.isSingleLine = replyLabel.lineCount > 1
} }
} }
} }
@ -807,8 +814,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
private fun extensionIntentItemSelected(item: MenuItem) { private fun extensionIntentItemSelected(item: MenuItem) {
val intent = item.intent ?: return val intent = item.intent ?: return
try { try {
val action = intent.action when (intent.action) {
when (action) {
INTENT_ACTION_EXTENSION_COMPOSE -> { INTENT_ACTION_EXTENSION_COMPOSE -> {
val accountKeys = accountsAdapter.selectedAccountKeys val accountKeys = accountsAdapter.selectedAccountKeys
intent.putExtra(EXTRA_TEXT, ParseUtils.parseString(editText.text)) intent.putExtra(EXTRA_TEXT, ParseUtils.parseString(editText.text))
@ -1084,16 +1090,20 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
val action = intent.action val action = intent.action
val hasVisibility = intent.hasExtra(EXTRA_VISIBILITY) val hasVisibility = intent.hasExtra(EXTRA_VISIBILITY)
val hasAccountKeys: Boolean val hasAccountKeys: Boolean
if (intent.hasExtra(EXTRA_ACCOUNT_KEYS)) { when {
val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS) intent.hasExtra(EXTRA_ACCOUNT_KEYS) -> {
accountsAdapter.selectedAccountKeys = accountKeys val accountKeys = intent.getTypedArrayExtra<UserKey>(EXTRA_ACCOUNT_KEYS)
hasAccountKeys = true accountsAdapter.selectedAccountKeys = accountKeys
} else if (intent.hasExtra(EXTRA_ACCOUNT_KEY)) { hasAccountKeys = true
val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY) }
accountsAdapter.selectedAccountKeys = arrayOf(accountKey) intent.hasExtra(EXTRA_ACCOUNT_KEY) -> {
hasAccountKeys = true val accountKey = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
} else { accountsAdapter.selectedAccountKeys = arrayOf(accountKey)
hasAccountKeys = false hasAccountKeys = true
}
else -> {
hasAccountKeys = false
}
} }
when (action) { when (action) {
Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE -> { Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE -> {
@ -1102,7 +1112,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
val stream = intent.getStreamExtra() val stream = intent.getStreamExtra()
if (stream != null) { if (stream != null) {
val src = stream.toTypedArray() val src = stream.toTypedArray()
TaskStarter.execute(AddMediaTask(this, src, null, true, false)) TaskStarter.execute(AddMediaTask(this, src, null,
copySrc = true,
deleteSrc = false
))
} }
} }
else -> { else -> {
@ -1111,7 +1124,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
val data = intent.data val data = intent.data
if (data != null) { if (data != null) {
val src = arrayOf(data) val src = arrayOf(data)
TaskStarter.execute(AddMediaTask(this, src, null, true, false)) TaskStarter.execute(AddMediaTask(this, src, null,
copySrc = true,
deleteSrc = false
))
} }
} }
} }
@ -1147,16 +1163,16 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
} }
INTENT_ACTION_EDIT_DRAFT -> { INTENT_ACTION_EDIT_DRAFT -> {
val draft: Draft? = intent.getParcelableExtra(EXTRA_DRAFT) val draft: Draft? = intent.getParcelableExtra(EXTRA_DRAFT)
when (draft?.action_type) { return when (draft?.action_type) {
Draft.Action.REPLY -> { Draft.Action.REPLY -> {
return showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus) showReplyLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
} }
Draft.Action.QUOTE -> { Draft.Action.QUOTE -> {
return showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus) showQuoteLabelAndHint((draft.action_extras as? UpdateStatusActionExtras)?.inReplyToStatus)
} }
else -> { else -> {
showDefaultLabelAndHint() showDefaultLabelAndHint()
return false false
} }
} }
} }
@ -1786,7 +1802,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
s.setSpan(MarkForDeleteSpan(), start, start + count, s.setSpan(MarkForDeleteSpan(), start, start + count,
Spanned.SPAN_INCLUSIVE_INCLUSIVE) Spanned.SPAN_INCLUSIVE_INCLUSIVE)
} }
if (!imageSources.isEmpty()) { if (imageSources.isNotEmpty()) {
val intent = ThemedMediaPickerActivity.withThemed(this@ComposeActivity) val intent = ThemedMediaPickerActivity.withThemed(this@ComposeActivity)
.getMedia(Uri.parse(imageSources[0])) .getMedia(Uri.parse(imageSources[0]))
.build() .build()
@ -1817,7 +1833,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}) })
editText.customSelectionActionModeCallback = this editText.customSelectionActionModeCallback = this
editText.imageInputListener = { contentInfo -> editText.imageInputListener = { contentInfo ->
val task = AddMediaTask(this, arrayOf(contentInfo.contentUri), null, true, false) val task = AddMediaTask(this, arrayOf(contentInfo.contentUri), null,
copySrc = true,
deleteSrc = false
)
task.callback = { task.callback = {
contentInfo.releasePermission() contentInfo.releasePermission()
} }
@ -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 { override fun isLongPressDragEnabled(): Boolean {
return true 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) { override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
// Fade out the view as it is swiped out of the parent's bounds // Fade out the view as it is swiped out of the parent's bounds
val alpha = ALPHA_FULL - Math.abs(dY) / viewHolder.itemView.height.toFloat() val alpha = ALPHA_FULL - abs(dY) / viewHolder.itemView.height.toFloat()
viewHolder.itemView.alpha = alpha viewHolder.itemView.alpha = alpha
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
} else { } else {
@ -1925,7 +1944,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
} }
companion object { companion object {
val ALPHA_FULL = 1.0f const val ALPHA_FULL = 1.0f
} }
} }
@ -1997,7 +2016,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
set(value) { set(value) {
selection.clear() selection.clear()
for (accountKey in value) { for (accountKey in value) {
selection.put(accountKey, true) selection[accountKey] = true
} }
notifyDataSetChanged() notifyDataSetChanged()
} }
@ -2035,7 +2054,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
fun toggleSelection(position: Int) { fun toggleSelection(position: Int) {
if (accounts == null || position < 0) return if (accounts == null || position < 0) return
val account = accounts!![position] val account = accounts!![position]
selection.put(account.key, true != selection[account.key]) selection[account.key] = true != selection[account.key]
activity.updateAccountSelectionState() activity.updateAccountSelectionState()
activity.updateVisibilityState() activity.updateVisibilityState()
activity.updateSummaryTextState() activity.updateSummaryTextState()
@ -2047,7 +2066,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
if (accounts == null || position < 0) return if (accounts == null || position < 0) return
val account = accounts!![position] val account = accounts!![position]
selection.clear() selection.clear()
selection.put(account.key, true != selection[account.key]) selection[account.key] = true != selection[account.key]
activity.updateAccountSelectionState() activity.updateAccountSelectionState()
activity.updateVisibilityState() activity.updateVisibilityState()
activity.updateSummaryTextState() activity.updateSummaryTextState()
@ -2097,12 +2116,12 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
private class DisplayPlaceNameTask : AbstractTask<ParcelableLocation, List<Address>, ComposeActivity>() { private class DisplayPlaceNameTask : AbstractTask<ParcelableLocation, List<Address>, ComposeActivity>() {
override fun doLongOperation(location: ParcelableLocation): List<Address>? { override fun doLongOperation(location: ParcelableLocation): List<Address>? {
try { return try {
val activity = callback ?: throw IOException("Interrupted") val activity = callback ?: throw IOException("Interrupted")
val gcd = Geocoder(activity, Locale.getDefault()) val gcd = Geocoder(activity, Locale.getDefault())
return gcd.getFromLocation(location.latitude, location.longitude, 1) gcd.getFromLocation(location.latitude, location.longitude, 1)
} catch (e: IOException) { } catch (e: IOException) {
return null null
} }
} }
@ -2120,13 +2139,16 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
textView.spannable = ParcelableLocationUtils.getHumanReadableString(location, 3) textView.spannable = ParcelableLocationUtils.getHumanReadableString(location, 3)
textView.tag = location textView.tag = location
} else { } else {
val tag = textView.tag when (val tag = textView.tag) {
if (tag is Address) { is Address -> {
textView.spannable = tag.locality textView.spannable = tag.locality
} else if (tag is NoAddress) { }
textView.setText(R.string.label_location_your_coarse_location) is NoAddress -> {
} else { textView.setText(R.string.label_location_your_coarse_location)
textView.setText(R.string.getting_location) }
else -> {
textView.setText(R.string.getting_location)
}
} }
} }
} else { } else {

View File

@ -105,12 +105,12 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
?: return false ?: return false
// val file = File(folder, fileName) // val file = File(folder, fileName)
// file.delete() // file.delete()
try { return try {
DataImportExportUtils.exportData(activity, file, flags) DataImportExportUtils.exportData(activity, file, flags)
return true true
} catch (e: IOException) { } catch (e: IOException) {
Log.w(LOGTAG, e) Log.w(LOGTAG, e)
return false false
} }
} }
@ -134,7 +134,7 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
} }
companion object { companion object {
private val FRAGMENT_TAG = "import_settings_dialog" private const val FRAGMENT_TAG = "import_settings_dialog"
} }
} }

View File

@ -111,12 +111,12 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
return false return false
} }
if (!file.isFile) return false if (!file.isFile) return false
try { return try {
DataImportExportUtils.importData(activity, file, flags) DataImportExportUtils.importData(activity, file, flags)
return true true
} catch (e: IOException) { } catch (e: IOException) {
Log.w(LOGTAG, e) Log.w(LOGTAG, e)
return false false
} }
} }
@ -140,7 +140,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
} }
companion object { companion object {
private val FRAGMENT_TAG = "import_settings_dialog" private const val FRAGMENT_TAG = "import_settings_dialog"
} }
} }
@ -152,10 +152,10 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
return 0 return 0
} }
if (!file.isFile) return 0 if (!file.isFile) return 0
try { return try {
return DataImportExportUtils.getImportedSettingsFlags(activity, file) DataImportExportUtils.getImportedSettingsFlags(activity, file)
} catch (e: IOException) { } catch (e: IOException) {
return 0 0
} }
} }
@ -185,7 +185,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
companion object { companion object {
private val FRAGMENT_TAG = "read_settings_data_dialog" private const val FRAGMENT_TAG = "read_settings_data_dialog"
} }
} }

View File

@ -87,13 +87,17 @@ class FileSelectorActivity : BaseActivity(), FileSelectorDialogFragment.Callback
finish() finish()
return return
} }
if (checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)) { when {
showPickFileDialog() checkAllSelfPermissionsGranted(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE) -> {
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) { showPickFileDialog()
val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE) }
ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS) Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN -> {
} else { val permissions = arrayOf(AndroidPermissions.READ_EXTERNAL_STORAGE, AndroidPermissions.WRITE_EXTERNAL_STORAGE)
finishWithDeniedMessage() ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS)
}
else -> {
finishWithDeniedMessage()
}
} }
} }

View File

@ -107,6 +107,7 @@ import org.mariotaku.twidere.util.premium.ExtraFeaturesService
import org.mariotaku.twidere.view.HomeDrawerLayout import org.mariotaku.twidere.view.HomeDrawerLayout
import org.mariotaku.twidere.view.TabPagerIndicator import org.mariotaku.twidere.view.TabPagerIndicator
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import kotlin.math.floor
class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, SupportFragmentCallback, class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, SupportFragmentCallback,
OnLongClickListener, DrawerLayout.DrawerListener { OnLongClickListener, DrawerLayout.DrawerListener {
@ -860,7 +861,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
"wide" -> resources.getDimension(R.dimen.preferred_tab_column_width_wide) "wide" -> resources.getDimension(R.dimen.preferred_tab_column_width_wide)
else -> resources.getDimension(R.dimen.preferred_tab_column_width_normal) else -> resources.getDimension(R.dimen.preferred_tab_column_width_normal)
} }
mainTabs.columns = Math.floor(1.0 / pagerAdapter.getPageWidth(0)).toInt() mainTabs.columns = floor(1.0 / pagerAdapter.getPageWidth(0)).toInt()
} else { } else {
mainPager.pageMargin = 0 mainPager.pageMargin = 0
mainPager.setPageMarginDrawable(null) mainPager.setPageMarginDrawable(null)

View File

@ -119,7 +119,7 @@ class KeyboardShortcutPreferenceCompatActivity : BaseActivity(), OnClickListener
companion object { companion object {
val EXTRA_CONTEXT_TAG = "context_tag" const val EXTRA_CONTEXT_TAG = "context_tag"
val EXTRA_KEY_ACTION = "key_action" const val EXTRA_KEY_ACTION = "key_action"
} }
} }

View File

@ -74,6 +74,8 @@ import org.mariotaku.twidere.view.viewer.MediaSwipeCloseContainer
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
import kotlin.concurrent.thread import kotlin.concurrent.thread
import kotlin.math.abs
import kotlin.math.roundToInt
import android.Manifest.permission as AndroidPermissions import android.Manifest.permission as AndroidPermissions
class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeCloseContainer.Listener, class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeCloseContainer.Listener,
@ -145,7 +147,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
activityLayout.statusBarAlpha = offset activityLayout.statusBarAlpha = offset
} }
try { try {
actionBar.hideOffset = Math.round(controlBarHeight * (1f - offset)) actionBar.hideOffset = (controlBarHeight * (1f - offset)).roundToInt()
} catch (e: UnsupportedOperationException) { } catch (e: UnsupportedOperationException) {
// Some device will throw this exception // Some device will throw this exception
hideOffsetNotSupported = true hideOffsetNotSupported = true
@ -367,10 +369,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
ParcelableMedia.Type.IMAGE -> { ParcelableMedia.Type.IMAGE -> {
val mediaUrl = media.media_url ?: return Fragment.instantiate(this, ExternalBrowserPageFragment::class.java.name, args) as MediaViewerFragment val mediaUrl = media.media_url ?: return Fragment.instantiate(this, ExternalBrowserPageFragment::class.java.name, args) as MediaViewerFragment
args.putParcelable(EXTRA_MEDIA_URI, Uri.parse(mediaUrl)) args.putParcelable(EXTRA_MEDIA_URI, Uri.parse(mediaUrl))
if (mediaUrl.endsWith(".gif")) { return if (mediaUrl.endsWith(".gif")) {
return Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment Fragment.instantiate(this, GifPageFragment::class.java.name, args) as MediaViewerFragment
} else { } else {
return Fragment.instantiate(this, ImagePageFragment::class.java.name, args) as MediaViewerFragment Fragment.instantiate(this, ImagePageFragment::class.java.name, args) as MediaViewerFragment
} }
} }
ParcelableMedia.Type.ANIMATED_GIF, ParcelableMedia.Type.CARD_ANIMATED_GIF -> { ParcelableMedia.Type.ANIMATED_GIF, ParcelableMedia.Type.CARD_ANIMATED_GIF -> {
@ -408,10 +410,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
} }
override fun onSwipeOffsetChanged(offset: Int) { override fun onSwipeOffsetChanged(offset: Int) {
val offsetFactor = 1 - (Math.abs(offset).toFloat() / swipeContainer.height) val offsetFactor = 1 - (abs(offset).toFloat() / swipeContainer.height)
swipeContainer.backgroundAlpha = offsetFactor swipeContainer.backgroundAlpha = offsetFactor
val colorToolbar = overrideTheme.colorToolbar val colorToolbar = overrideTheme.colorToolbar
val alpha = Math.round(Color.alpha(colorToolbar) * offsetFactor).coerceIn(0..255) val alpha = (Color.alpha(colorToolbar) * offsetFactor).roundToInt().coerceIn(0..255)
activityLayout.statusBarAlpha = alpha / 255f activityLayout.statusBarAlpha = alpha / 255f
} }
@ -464,11 +466,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
if (checkAllSelfPermissionsGranted(AndroidPermissions.WRITE_EXTERNAL_STORAGE)) { if (checkAllSelfPermissionsGranted(AndroidPermissions.WRITE_EXTERNAL_STORAGE)) {
saveToStorage() saveToStorage()
} else { } else {
val permissions: Array<String> val permissions: Array<String> = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE, AndroidPermissions.READ_EXTERNAL_STORAGE)
} else { } else {
permissions = arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE) arrayOf(AndroidPermissions.WRITE_EXTERNAL_STORAGE)
} }
PermissionRequestDialog.show(supportFragmentManager, getString(R.string.message_permission_request_save_media), PermissionRequestDialog.show(supportFragmentManager, getString(R.string.message_permission_request_save_media),
permissions, REQUEST_PERMISSION_SAVE_MEDIA) permissions, REQUEST_PERMISSION_SAVE_MEDIA)
@ -499,8 +500,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
private fun saveToStorage() { private fun saveToStorage() {
val fileInfo = getCurrentCacheFileInfo(saveToStoragePosition) ?: return val fileInfo = getCurrentCacheFileInfo(saveToStoragePosition) ?: return
val type = (fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType val pubDir = when ((fileInfo as? CacheProvider.CacheFileTypeSupport)?.cacheFileType) {
val pubDir = when (type) {
CacheFileType.VIDEO -> { CacheFileType.VIDEO -> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
@ -636,10 +636,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
companion object { companion object {
private val REQUEST_SHARE_MEDIA = 201 private const val REQUEST_SHARE_MEDIA = 201
private val REQUEST_PERMISSION_SAVE_MEDIA = 202 private const val REQUEST_PERMISSION_SAVE_MEDIA = 202
private val REQUEST_PERMISSION_SHARE_MEDIA = 203 private const val REQUEST_PERMISSION_SHARE_MEDIA = 203
private val REQUEST_SELECT_SAVE_MEDIA = 204 private const val REQUEST_SELECT_SAVE_MEDIA = 204
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN) @RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
const val FLAG_SYSTEM_UI_HIDE_BARS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or const val FLAG_SYSTEM_UI_HIDE_BARS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or

View File

@ -171,7 +171,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
override fun onDismiss(listView: ListView, reverseSortedPositions: IntArray) { override fun onDismiss(listView: ListView, reverseSortedPositions: IntArray) {
val adapter = suggestionsList.adapter as SuggestionsAdapter val adapter = suggestionsList.adapter as SuggestionsAdapter
val ids = LongArray(reverseSortedPositions.size) val ids = LongArray(reverseSortedPositions.size)
for (i in 0 until reverseSortedPositions.size) { for (i in reverseSortedPositions.indices) {
val position = reverseSortedPositions[i] val position = reverseSortedPositions[i]
val item = adapter.getSuggestionItem(position) ?: return val item = adapter.getSuggestionItem(position) ?: return
ids[i] = item._id ids[i] = item._id
@ -505,7 +505,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
private fun getActualPosition(position: Int): Int { private fun getActualPosition(position: Int): Int {
var skipped = 0 var skipped = 0
for (i in 0 until removedPositions.size) { for (i in 0 until removedPositions.size) {
if (position + skipped >= removedPositions.get(i)) { if (position + skipped >= removedPositions[i]) {
skipped++ skipped++
} }
} }
@ -538,10 +538,10 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
companion object { companion object {
internal val VIEW_TYPE_SEARCH_HISTORY = 0 internal const val VIEW_TYPE_SEARCH_HISTORY = 0
internal val VIEW_TYPE_SAVED_SEARCH = 1 internal const val VIEW_TYPE_SAVED_SEARCH = 1
internal val VIEW_TYPE_USER_SUGGESTION_ITEM = 2 internal const val VIEW_TYPE_USER_SUGGESTION_ITEM = 2
internal val VIEW_TYPE_USER_SCREEN_NAME = 3 internal const val VIEW_TYPE_USER_SCREEN_NAME = 3
} }
} }

View File

@ -54,6 +54,7 @@ import org.mariotaku.twidere.util.DeviceUtils
import org.mariotaku.twidere.util.KeyboardShortcutsHandler import org.mariotaku.twidere.util.KeyboardShortcutsHandler
import org.mariotaku.twidere.util.ThemeUtils import org.mariotaku.twidere.util.ThemeUtils
import java.util.* import java.util.*
import kotlin.system.exitProcess
class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartFragmentCallback { class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartFragmentCallback {
@ -74,8 +75,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
shouldTerminate = savedInstanceState.getBoolean(EXTRA_SHOULD_TERMINATE, shouldTerminate) shouldTerminate = savedInstanceState.getBoolean(EXTRA_SHOULD_TERMINATE, shouldTerminate)
} else if (intent.getBooleanExtra(EXTRA_SHOULD_TERMINATE, false)) { } else if (intent.getBooleanExtra(EXTRA_SHOULD_TERMINATE, false)) {
finishNoRestart() finishNoRestart()
System.exit(0) exitProcess(0)
return
} }
val backgroundOption = currentThemeBackgroundOption val backgroundOption = currentThemeBackgroundOption
@ -349,8 +349,8 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
companion object { companion object {
val VIEW_TYPE_PREFERENCE_ENTRY = 0 const val VIEW_TYPE_PREFERENCE_ENTRY = 0
val VIEW_TYPE_HEADER_ENTRY = 1 const val VIEW_TYPE_HEADER_ENTRY = 1
} }
} }
@ -424,7 +424,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
companion object { companion object {
private val RESULT_SETTINGS_CHANGED = 10 private const val RESULT_SETTINGS_CHANGED = 10
fun setShouldRecreate(activity: Activity) { fun setShouldRecreate(activity: Activity) {
if (activity !is SettingsActivity) return if (activity !is SettingsActivity) return

View File

@ -428,23 +428,30 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
internal fun onSignInError(exception: Exception) { internal fun onSignInError(exception: Exception) {
DebugLog.w(LOGTAG, "Sign in error", exception) DebugLog.w(LOGTAG, "Sign in error", exception)
var errorReason: String? = null var errorReason: String? = null
if (exception is AuthenticityTokenException) { when (exception) {
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show() is AuthenticityTokenException -> {
errorReason = "wrong_api_key" Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
} else if (exception is WrongUserPassException) { errorReason = "wrong_api_key"
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show() }
errorReason = "wrong_username_password" is WrongUserPassException -> {
} else if (exception is SignInTask.WrongBasicCredentialException) { Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show() errorReason = "wrong_username_password"
errorReason = "wrong_username_password" }
} else if (exception is SignInTask.WrongAPIURLFormatException) { is SignInTask.WrongBasicCredentialException -> {
Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.message_toast_wrong_username_password, Toast.LENGTH_SHORT).show()
errorReason = "wrong_api_key" errorReason = "wrong_username_password"
} else if (exception is LoginVerificationException) { }
Toast.makeText(this, R.string.message_toast_login_verification_failed, Toast.LENGTH_SHORT).show() is SignInTask.WrongAPIURLFormatException -> {
errorReason = "login_verification_failed" Toast.makeText(this, R.string.message_toast_wrong_api_key, Toast.LENGTH_SHORT).show()
} else { errorReason = "wrong_api_key"
Toast.makeText(this, exception.getErrorMessage(this), Toast.LENGTH_SHORT).show() }
is LoginVerificationException -> {
Toast.makeText(this, R.string.message_toast_login_verification_failed, Toast.LENGTH_SHORT).show()
errorReason = "login_verification_failed"
}
else -> {
Toast.makeText(this, exception.getErrorMessage(this), Toast.LENGTH_SHORT).show()
}
} }
Analyzer.log(SignIn(false, credentialsType = apiConfig.credentialsType, Analyzer.log(SignIn(false, credentialsType = apiConfig.credentialsType,
errorReason = errorReason, accountType = apiConfig.type)) errorReason = errorReason, accountType = apiConfig.type))
@ -809,10 +816,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
val oauth = newMicroBlogInstance(context, endpoint = endpoint, auth = auth, val oauth = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
accountType = apiConfig.type, cls = TwitterOAuth::class.java) accountType = apiConfig.type, cls = TwitterOAuth::class.java)
val accessToken: OAuthToken val accessToken: OAuthToken
if (oauthVerifier != null) { accessToken = if (oauthVerifier != null) {
accessToken = oauth.getAccessToken(requestToken, oauthVerifier) oauth.getAccessToken(requestToken, oauthVerifier)
} else { } else {
accessToken = oauth.getAccessToken(requestToken) oauth.getAccessToken(requestToken)
} }
auth = apiConfig.getOAuthAuthorization(accessToken) ?: auth = apiConfig.getOAuthAuthorization(accessToken) ?:
throw MicroBlogException("Invalid OAuth credential") throw MicroBlogException("Invalid OAuth credential")
@ -823,7 +830,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
accountType = apiConfig.type, cls = MicroBlog::class.java) accountType = apiConfig.type, cls = MicroBlog::class.java)
val apiUser = twitter.verifyCredentials() val apiUser = twitter.verifyCredentials()
var color = analyseUserProfileColor(apiUser) var color = analyseUserProfileColor(apiUser)
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type) val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
val accountKey = apiUser.key val accountKey = apiUser.key
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize) val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
val am = AccountManager.get(context) val am = AccountManager.get(context)
@ -901,7 +908,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
return authOAuth() return authOAuth()
} }
@Throws(OAuthPasswordAuthenticator.AuthenticationException::class, MicroBlogException::class) @Throws(AuthenticationException::class, MicroBlogException::class)
private fun authOAuth(): SignInResponse { private fun authOAuth(): SignInResponse {
val activity = activityRef.get() ?: throw InterruptedException() val activity = activityRef.get() ?: throw InterruptedException()
val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat, val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
@ -940,7 +947,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
return getOAuthSignInResponse(activity, accessToken, Credentials.Type.XAUTH) return getOAuthSignInResponse(activity, accessToken, Credentials.Type.XAUTH)
} }
@Throws(MicroBlogException::class, OAuthPasswordAuthenticator.AuthenticationException::class) @Throws(MicroBlogException::class, AuthenticationException::class)
private fun authBasic(): SignInResponse { private fun authBasic(): SignInResponse {
val activity = activityRef.get() ?: throw InterruptedException() val activity = activityRef.get() ?: throw InterruptedException()
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1" val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
@ -962,7 +969,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
} }
var color = analyseUserProfileColor(apiUser) var color = analyseUserProfileColor(apiUser)
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type) val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
val accountKey = apiUser.key val accountKey = apiUser.key
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize) val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
val am = AccountManager.get(activity) val am = AccountManager.get(activity)
@ -991,7 +998,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
accountType = apiConfig.type, cls = MicroBlog::class.java) accountType = apiConfig.type, cls = MicroBlog::class.java)
val apiUser = twitter.verifyCredentials() val apiUser = twitter.verifyCredentials()
var color = analyseUserProfileColor(apiUser) var color = analyseUserProfileColor(apiUser)
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type) val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
val accountKey = apiUser.key val accountKey = apiUser.key
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize) val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
val am = AccountManager.get(activity) val am = AccountManager.get(activity)
@ -1018,7 +1025,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
accountType = apiConfig.type, cls = MicroBlog::class.java) accountType = apiConfig.type, cls = MicroBlog::class.java)
val apiUser = twitter.verifyCredentials() val apiUser = twitter.verifyCredentials()
var color = analyseUserProfileColor(apiUser) var color = analyseUserProfileColor(apiUser)
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type) val (type, extras) = detectAccountType(twitter, apiUser, apiConfig.type)
val accountKey = apiUser.key val accountKey = apiUser.key
val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize) val user = apiUser.toParcelable(accountKey, type, profileImageSize = profileImageSize)
val am = AccountManager.get(activity) val am = AccountManager.get(activity)
@ -1040,11 +1047,11 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
return SignInResponse(account != null, authType, credentials, user, color, type, extras) return SignInResponse(account != null, authType, credentials, user, color, type, extras)
} }
internal class WrongBasicCredentialException : OAuthPasswordAuthenticator.AuthenticationException() internal class WrongBasicCredentialException : AuthenticationException()
internal class WrongAPIURLFormatException : OAuthPasswordAuthenticator.AuthenticationException() internal class WrongAPIURLFormatException : AuthenticationException()
internal inner class InputLoginVerificationCallback : OAuthPasswordAuthenticator.LoginVerificationCallback { internal inner class InputLoginVerificationCallback : LoginVerificationCallback {
override fun getLoginVerification(challengeType: String): String? { override fun getLoginVerification(challengeType: String): String? {
// Dismiss current progress dialog // Dismiss current progress dialog
@ -1087,10 +1094,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
protected val profileImageSize: String = activity.getString(R.string.profile_image_size) protected val profileImageSize: String = activity.getString(R.string.profile_image_size)
final override fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> { final override fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
try { return try {
return SingleResponse.getInstance(performLogin()) SingleResponse.getInstance(performLogin())
} catch (e: Exception) { } catch (e: Exception) {
return SingleResponse.getInstance(e) SingleResponse.getInstance(e)
} }
} }
@ -1189,8 +1196,8 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
const val REQUEST_BROWSER_TWITTER_SIGN_IN = 101 const val REQUEST_BROWSER_TWITTER_SIGN_IN = 101
const val REQUEST_BROWSER_MASTODON_SIGN_IN = 102 const val REQUEST_BROWSER_MASTODON_SIGN_IN = 102
private val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress" private const val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
private val EXTRA_API_LAST_CHANGE = "api_last_change" private const val EXTRA_API_LAST_CHANGE = "api_last_change"
@Throws(IOException::class) @Throws(IOException::class)
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> { internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {

View File

@ -41,8 +41,8 @@ class ThemedMediaPickerActivity : MediaPickerActivity() {
companion object { companion object {
fun withThemed(context: Context): MediaPickerActivity.IntentBuilder { fun withThemed(context: Context): IntentBuilder {
val builder = MediaPickerActivity.IntentBuilder(context, ThemedMediaPickerActivity::class.java) val builder = IntentBuilder(context, ThemedMediaPickerActivity::class.java)
builder.cropImageActivityClass(ImageCropperActivity::class.java) builder.cropImageActivityClass(ImageCropperActivity::class.java)
builder.streamDownloaderClass(RestFuNetworkStreamDownloader::class.java) builder.streamDownloaderClass(RestFuNetworkStreamDownloader::class.java)
return builder return builder

View File

@ -177,23 +177,14 @@ class TrendsLocationSelectorActivity : BaseActivity() {
} }
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View { override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
val view: View val view: View = convertView ?: inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
if (convertView != null) {
view = convertView
} else {
view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
}
view.findViewById<TextView>(android.R.id.text1).text = getGroup(groupPosition).name view.findViewById<TextView>(android.R.id.text1).text = getGroup(groupPosition).name
return view return view
} }
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View { override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
val view: View val view: View =
if (convertView != null) { convertView ?: inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
view = convertView
} else {
view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
}
val location = getChild(groupPosition, childPosition) val location = getChild(groupPosition, childPosition)
val text1 = view.findViewById<TextView>(android.R.id.text1) val text1 = view.findViewById<TextView>(android.R.id.text1)
if (location.parentId == WORLDWIDE) { if (location.parentId == WORLDWIDE) {

View File

@ -95,8 +95,7 @@ class UserListSelectorActivity : BaseActivity(),
listView.setOnScrollListener(handler) listView.setOnScrollListener(handler)
listView.setOnTouchListener(handler.touchListener) listView.setOnTouchListener(handler.touchListener)
listView.onItemClickListener = OnItemClickListener { view, _, position, _ -> listView.onItemClickListener = OnItemClickListener { view, _, position, _ ->
val item = view.getItemAtPosition(position) when (val item = view.getItemAtPosition(position)) {
when (item) {
is ParcelableUserList -> { is ParcelableUserList -> {
val data = Intent() val data = Intent()
data.putExtra(EXTRA_USER_LIST, item) data.putExtra(EXTRA_USER_LIST, item)

View File

@ -114,7 +114,10 @@ class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.
if (!fromCache) { if (!fromCache) {
showProgress() 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>>) { override fun onLoaderReset(loader: Loader<List<ParcelableUser>>) {
@ -126,12 +129,16 @@ class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.
listContainer.visibility = View.VISIBLE listContainer.visibility = View.VISIBLE
adapter.setData(data, true) adapter.setData(data, true)
loader as CacheUserSearchLoader loader as CacheUserSearchLoader
if (data.isNotNullOrEmpty()) { when {
showList() data.isNotNullOrEmpty() -> {
} else if (loader.query.isEmpty()) { showList()
showSearchHint() }
} else { loader.query.isEmpty() -> {
showNotFound() showSearchHint()
}
else -> {
showNotFound()
}
} }
} }

View File

@ -47,7 +47,7 @@ class WebLinkHandlerActivity : Activity() {
startActivity(handledIntent) startActivity(handledIntent)
} else { } else {
if (!handledSuccessfully) { 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) val fallbackIntent = Intent(Intent.ACTION_VIEW, uri)
fallbackIntent.addCategory(Intent.CATEGORY_BROWSABLE) fallbackIntent.addCategory(Intent.CATEGORY_BROWSABLE)
@ -277,7 +277,7 @@ class WebLinkHandlerActivity : Activity() {
sb.append(text) sb.append(text)
} }
if (!url.isNullOrEmpty()) { if (!url.isNullOrEmpty()) {
if (!sb.isEmpty()) { if (sb.isNotEmpty()) {
sb.append(" ") sb.append(" ")
} }
sb.append(url) sb.append(url)
@ -366,7 +366,7 @@ class WebLinkHandlerActivity : Activity() {
"photo", "album", "paipai", "q", "userview", "dialogue") "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 { private fun regulateTwitterUri(data: Uri): Uri {

View File

@ -63,12 +63,12 @@ interface IControlBarActivity {
} }
val animator: ObjectAnimator val animator: ObjectAnimator
val offset = activity.controlBarOffset val offset = activity.controlBarOffset
if (visible) { animator = if (visible) {
if (offset >= 1) return if (offset >= 1) return
animator = ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 1f) ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 1f)
} else { } else {
if (offset <= 0) return if (offset <= 0) return
animator = ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 0f) ObjectAnimator.ofFloat(activity, ControlBarOffsetProperty, offset, 0f)
} }
animator.interpolator = DecelerateInterpolator() animator.interpolator = DecelerateInterpolator()
animator.addListener(object : AnimatorListener { animator.addListener(object : AnimatorListener {

View File

@ -31,6 +31,7 @@ import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.view.holder.AccountProfileImageViewHolder import org.mariotaku.twidere.view.holder.AccountProfileImageViewHolder
import org.mariotaku.twidere.view.transformer.AccountsSelectorTransformer import org.mariotaku.twidere.view.transformer.AccountsSelectorTransformer
import java.util.* import java.util.*
import kotlin.math.max
class AccountSelectorAdapter( class AccountSelectorAdapter(
private val inflater: LayoutInflater, private val inflater: LayoutInflater,
@ -46,7 +47,7 @@ class AccountSelectorAdapter(
set(value) { set(value) {
if (value != null) { if (value != null) {
val previousAccounts = accounts val previousAccounts = accounts
if (previousAccounts != null) { field = if (previousAccounts != null) {
val tmpList = arrayListOf(*value) val tmpList = arrayListOf(*value)
val tmpResult = ArrayList<AccountDetails>() val tmpResult = ArrayList<AccountDetails>()
previousAccounts.forEach { previousAccount -> previousAccounts.forEach { previousAccount ->
@ -56,9 +57,9 @@ class AccountSelectorAdapter(
} }
} }
tmpResult.addAll(tmpList) tmpResult.addAll(tmpList)
field = tmpResult.toTypedArray() tmpResult.toTypedArray()
} else { } else {
field = value value
} }
} else { } else {
field = null field = null
@ -115,16 +116,16 @@ class AccountSelectorAdapter(
} }
override fun getCount(): Int { override fun getCount(): Int {
return Math.max(3, accountsCount) return max(3, accountsCount)
} }
val accountStart: Int val accountStart: Int
get() = Math.max(0, 3 - accountsCount) get() = max(0, 3 - accountsCount)
val accountsCount: Int val accountsCount: Int
get() { get() {
val accounts = this.accounts ?: return 0 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 { override fun getPageWidth(position: Int): Float {

View File

@ -80,14 +80,18 @@ class DummyItemAdapter(
} }
override fun getStatus(position: Int, raw: Boolean): ParcelableStatus { override fun getStatus(position: Int, raw: Boolean): ParcelableStatus {
if (adapter is ParcelableStatusesAdapter) { return when (adapter) {
return adapter.getStatus(position, raw) is ParcelableStatusesAdapter -> {
} else if (adapter is VariousItemsAdapter) { adapter.getStatus(position, raw)
return adapter.getItem(position) as ParcelableStatus }
} else if (adapter is ParcelableActivitiesAdapter) { is VariousItemsAdapter -> {
return adapter.getActivity(position).activityStatus!! adapter.getItem(position) as ParcelableStatus
}
is ParcelableActivitiesAdapter -> {
adapter.getActivity(position).activityStatus!!
}
else -> throw IndexOutOfBoundsException()
} }
throw IndexOutOfBoundsException()
} }
override fun getStatusCount(raw: Boolean) = 0 override fun getStatusCount(raw: Boolean) = 0

View File

@ -150,20 +150,19 @@ class MessagesConversationAdapter(
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
val countIndex = itemCounts.getItemCountIndex(position) return when (val countIndex = itemCounts.getItemCountIndex(position)) {
when (countIndex) {
ITEM_START_MESSAGE -> when (getMessage(position, reuse = true).message_type) { ITEM_START_MESSAGE -> when (getMessage(position, reuse = true).message_type) {
MessageType.STICKER -> { MessageType.STICKER -> {
return ITEM_TYPE_STICKER_MESSAGE ITEM_TYPE_STICKER_MESSAGE
} }
MessageType.CONVERSATION_CREATE, MessageType.JOIN_CONVERSATION, MessageType.CONVERSATION_CREATE, MessageType.JOIN_CONVERSATION,
MessageType.PARTICIPANTS_LEAVE, MessageType.PARTICIPANTS_JOIN, MessageType.PARTICIPANTS_LEAVE, MessageType.PARTICIPANTS_JOIN,
MessageType.CONVERSATION_NAME_UPDATE, MessageType.CONVERSATION_AVATAR_UPDATE -> { 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) else -> throw UnsupportedCountIndexException(countIndex, position)
} }
} }

View File

@ -77,10 +77,9 @@ class MessagesEntriesAdapter(
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
val countIndex = itemCounts.getItemCountIndex(position) return when (val countIndex = itemCounts.getItemCountIndex(position)) {
when (countIndex) { 0 -> ITEM_TYPE_MESSAGE_ENTRY
0 -> return ITEM_TYPE_MESSAGE_ENTRY 1 -> ITEM_VIEW_TYPE_LOAD_INDICATOR
1 -> return ITEM_VIEW_TYPE_LOAD_INDICATOR
else -> throw UnsupportedCountIndexException(countIndex, position) else -> throw UnsupportedCountIndexException(countIndex, position)
} }
} }

View File

@ -152,13 +152,12 @@ class ParcelableActivitiesAdapter(
} }
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
val countIndex = itemCounts.getItemCountIndex(position) return when (val countIndex = itemCounts.getItemCountIndex(position)) {
when (countIndex) {
ITEM_INDEX_ACTIVITY -> { ITEM_INDEX_ACTIVITY -> {
return getRowId(position, false) getRowId(position, false)
} }
else -> { 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)) 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 { override fun getItemViewType(position: Int): Int {
val countIndex = getItemCountIndex(position) when (val countIndex = getItemCountIndex(position)) {
when (countIndex) {
ITEM_INDEX_ACTIVITY -> { ITEM_INDEX_ACTIVITY -> {
if (isGapItem(position)) { if (isGapItem(position)) {
return ITEM_VIEW_TYPE_GAP return ITEM_VIEW_TYPE_GAP
} }
val action = getAction(position) when (getAction(position)) {
when (action) {
Activity.Action.MENTION, Activity.Action.QUOTE, Activity.Action.REPLY -> { Activity.Action.MENTION, Activity.Action.QUOTE, Activity.Action.REPLY -> {
return ITEM_VIEW_TYPE_STATUS return ITEM_VIEW_TYPE_STATUS
} }
@ -350,12 +347,12 @@ class ParcelableActivitiesAdapter(
throw IndexOutOfBoundsException("index: $position, valid range is $validRange") throw IndexOutOfBoundsException("index: $position, valid range is $validRange")
} }
val data = this.data!! val data = this.data!!
if (reuse && data is ObjectCursor) { return if (reuse && data is ObjectCursor) {
val activity = data.setInto(dataPosition, reuseActivity) val activity = data.setInto(dataPosition, reuseActivity)
activity.after_filtered_sources = null activity.after_filtered_sources = null
return activity activity
} else { } else {
return data[dataPosition] data[dataPosition]
} }
} }
@ -428,7 +425,7 @@ class ParcelableActivitiesAdapter(
internal val text2 = itemView.findViewById<TextView>(android.R.id.text2) internal val text2 = itemView.findViewById<TextView>(android.R.id.text2)
init { init {
text2.setSingleLine(false) text2.isSingleLine = false
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ -529,7 +526,7 @@ class ParcelableActivitiesAdapter(
result = 31 * result + timestamp.hashCode() result = 31 * result + timestamp.hashCode()
result = 31 * result + gap.hashCode() result = 31 * result + gap.hashCode()
result = 31 * result + action.hashCode() result = 31 * result + action.hashCode()
result = 31 * result + (filteredSources?.let { Arrays.hashCode(it) } ?: 0) result = 31 * result + (filteredSources?.contentHashCode() ?: 0)
return result return result
} }
} }

View File

@ -108,7 +108,7 @@ class ParcelableGroupsAdapter(
return LoadIndicatorViewHolder(view) return LoadIndicatorViewHolder(view)
} }
} }
throw IllegalStateException("Unknown view type " + viewType) throw IllegalStateException("Unknown view type $viewType")
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
@ -142,6 +142,6 @@ class ParcelableGroupsAdapter(
companion object { companion object {
val ITEM_VIEW_TYPE_USER_LIST = 2 const val ITEM_VIEW_TYPE_USER_LIST = 2
} }
} }

View File

@ -171,25 +171,29 @@ abstract class ParcelableStatusesAdapter(
override fun setData(data: List<ParcelableStatus>?): Boolean { override fun setData(data: List<ParcelableStatus>?): Boolean {
var changed = true var changed = true
if (data == null) { when (data) {
displayPositions = null null -> {
displayDataCount = 0 displayPositions = null
} else if (data is ObjectCursor) { displayDataCount = 0
displayPositions = null }
displayDataCount = data.size is ObjectCursor -> {
} else { displayPositions = null
var filteredCount = 0 displayDataCount = data.size
displayPositions = IntArray(data.size).apply { }
data.forEachIndexed { i, item -> else -> {
if (!item.is_gap && item.is_filtered) { var filteredCount = 0
filteredCount++ displayPositions = IntArray(data.size).apply {
} else { data.forEachIndexed { i, item ->
this[i - filteredCount] = i 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.data = data
this.infoCache = if (data != null) arrayOfNulls(data.size) else null this.infoCache = if (data != null) arrayOfNulls(data.size) else null
@ -324,7 +328,7 @@ abstract class ParcelableStatusesAdapter(
return TimelineFilterHeaderViewHolder(this, view) return TimelineFilterHeaderViewHolder(this, view)
} }
} }
throw IllegalStateException("Unknown view type " + viewType) throw IllegalStateException("Unknown view type $viewType")
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
@ -350,8 +354,7 @@ abstract class ParcelableStatusesAdapter(
if (position == 0 && ILoadMoreSupportAdapter.START in loadMoreIndicatorPosition) { if (position == 0 && ILoadMoreSupportAdapter.START in loadMoreIndicatorPosition) {
return ITEM_VIEW_TYPE_LOAD_INDICATOR return ITEM_VIEW_TYPE_LOAD_INDICATOR
} }
val countIndex = getItemCountIndex(position) when (val countIndex = getItemCountIndex(position)) {
when (countIndex) {
ITEM_INDEX_LOAD_START_INDICATOR, ITEM_INDEX_LOAD_END_INDICATOR -> { ITEM_INDEX_LOAD_START_INDICATOR, ITEM_INDEX_LOAD_END_INDICATOR -> {
return ITEM_VIEW_TYPE_LOAD_INDICATOR return ITEM_VIEW_TYPE_LOAD_INDICATOR
} }
@ -410,7 +413,7 @@ abstract class ParcelableStatusesAdapter(
// lesser equals than read position // lesser equals than read position
if (positionKey <= 0) return RecyclerView.NO_POSITION if (positionKey <= 0) return RecyclerView.NO_POSITION
val range = rangeOfSize(statusStartIndex, getStatusCount(raw)) 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)) { if (positionKey < getStatusPositionKey(range.last, raw)) {
return range.last return range.last
} }
@ -422,7 +425,7 @@ abstract class ParcelableStatusesAdapter(
// lesser equals than read position // lesser equals than read position
if (sortId <= 0) return RecyclerView.NO_POSITION if (sortId <= 0) return RecyclerView.NO_POSITION
val range = rangeOfSize(statusStartIndex, getStatusCount(raw)) 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)) { if (sortId < getStatusSortId(range.last, raw)) {
return range.last return range.last
} }
@ -489,11 +492,11 @@ abstract class ParcelableStatusesAdapter(
} else { } else {
dataPosition dataPosition
} }
if (reuse && data is ObjectCursor) { return if (reuse && data is ObjectCursor) {
reuseStatus.is_filtered = false reuseStatus.is_filtered = false
return data.setInto(listPosition, reuseStatus) data.setInto(listPosition, reuseStatus)
} else { } else {
return data[listPosition] data[listPosition]
} }
} }
} }

View File

@ -99,7 +99,7 @@ class ParcelableUserListsAdapter(
return LoadIndicatorViewHolder(view) return LoadIndicatorViewHolder(view)
} }
} }
throw IllegalStateException("Unknown view type " + viewType) throw IllegalStateException("Unknown view type $viewType")
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
@ -122,7 +122,7 @@ class ParcelableUserListsAdapter(
companion object { companion object {
val ITEM_VIEW_TYPE_USER_LIST = 2 const val ITEM_VIEW_TYPE_USER_LIST = 2
fun createUserListViewHolder(adapter: IUserListsAdapter<*>, fun createUserListViewHolder(adapter: IUserListsAdapter<*>,
inflater: LayoutInflater, inflater: LayoutInflater,

View File

@ -140,7 +140,7 @@ class ParcelableUsersAdapter(
return LoadIndicatorViewHolder(view) return LoadIndicatorViewHolder(view)
} }
} }
throw IllegalStateException("Unknown view type " + viewType) throw IllegalStateException("Unknown view type $viewType")
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

View File

@ -77,7 +77,7 @@ class SelectableUsersAdapter(
return LoadIndicatorViewHolder(view) return LoadIndicatorViewHolder(view)
} }
} }
throw IllegalStateException("Unknown view type " + viewType) throw IllegalStateException("Unknown view type $viewType")
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
@ -89,18 +89,16 @@ class SelectableUsersAdapter(
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
val countIndex = itemCounts.getItemCountIndex(position) return when (val countIndex = itemCounts.getItemCountIndex(position)) {
when (countIndex) { ITEM_TYPE_START_INDICATOR, ITEM_TYPE_END_INDICATOR -> ITEM_VIEW_TYPE_LOAD_INDICATOR
ITEM_TYPE_START_INDICATOR, ITEM_TYPE_END_INDICATOR -> return ITEM_VIEW_TYPE_LOAD_INDICATOR ITEM_TYPE_USER -> ITEM_VIEW_TYPE_USER
ITEM_TYPE_USER -> return ITEM_VIEW_TYPE_USER
else -> throw UnsupportedCountIndexException(countIndex, position) else -> throw UnsupportedCountIndexException(countIndex, position)
} }
} }
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
val countIndex = itemCounts.getItemCountIndex(position) return when (val countIndex = itemCounts.getItemCountIndex(position)) {
return when (countIndex) {
ITEM_TYPE_START_INDICATOR, ITEM_TYPE_END_INDICATOR -> (countIndex.toLong() shl 32) ITEM_TYPE_START_INDICATOR, ITEM_TYPE_END_INDICATOR -> (countIndex.toLong() shl 32)
ITEM_TYPE_USER -> (countIndex.toLong() shl 32) or getUser(position).hashCode().toLong() ITEM_TYPE_USER -> (countIndex.toLong() shl 32) or getUser(position).hashCode().toLong()
else -> throw UnsupportedCountIndexException(countIndex, position) else -> throw UnsupportedCountIndexException(countIndex, position)

View File

@ -36,11 +36,7 @@ class SimpleParcelableUsersAdapter(
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
val item = getItem(position) val item = getItem(position)
if (item != null) { return item?.hashCode()?.toLong() ?: -1
return item.hashCode().toLong()
} else {
return -1
}
} }
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {

View File

@ -80,10 +80,10 @@ class StatusDetailsAdapter(
internal set internal set
var translationResult: TranslationResult? = null var translationResult: TranslationResult? = null
internal set(translation) { internal set(translation) {
if (translation == null || status?.originalId != translation.id) { field = if (translation == null || status?.originalId != translation.id) {
field = null null
} else { } else {
field = translation translation
} }
notifyDataSetChanged() notifyDataSetChanged()
} }
@ -402,7 +402,7 @@ class StatusDetailsAdapter(
if (position in typeStart until typeEnd) return type if (position in typeStart until typeEnd) return type
typeStart = typeEnd typeStart = typeEnd
} }
throw IllegalStateException("Unknown position " + position) throw IllegalStateException("Unknown position $position")
} }
fun getItemTypeStart(position: Int): Int { fun getItemTypeStart(position: Int): Int {
@ -502,10 +502,10 @@ class StatusDetailsAdapter(
var isConversationsLoading: Boolean var isConversationsLoading: Boolean
get() = ILoadMoreSupportAdapter.START in loadMoreIndicatorPosition get() = ILoadMoreSupportAdapter.START in loadMoreIndicatorPosition
set(loading) { set(loading) {
if (loading) { loadMoreIndicatorPosition = if (loading) {
loadMoreIndicatorPosition = loadMoreIndicatorPosition or ILoadMoreSupportAdapter.START loadMoreIndicatorPosition or ILoadMoreSupportAdapter.START
} else { } else {
loadMoreIndicatorPosition = loadMoreIndicatorPosition and ILoadMoreSupportAdapter.START.inv() loadMoreIndicatorPosition and ILoadMoreSupportAdapter.START.inv()
} }
updateItemDecoration() updateItemDecoration()
} }
@ -513,10 +513,10 @@ class StatusDetailsAdapter(
var isRepliesLoading: Boolean var isRepliesLoading: Boolean
get() = ILoadMoreSupportAdapter.END in loadMoreIndicatorPosition get() = ILoadMoreSupportAdapter.END in loadMoreIndicatorPosition
set(loading) { set(loading) {
if (loading) { loadMoreIndicatorPosition = if (loading) {
loadMoreIndicatorPosition = loadMoreIndicatorPosition or ILoadMoreSupportAdapter.END loadMoreIndicatorPosition or ILoadMoreSupportAdapter.END
} else { } else {
loadMoreIndicatorPosition = loadMoreIndicatorPosition and ILoadMoreSupportAdapter.END.inv() loadMoreIndicatorPosition and ILoadMoreSupportAdapter.END.inv()
} }
updateItemDecoration() updateItemDecoration()
} }

View File

@ -162,6 +162,6 @@ class SupportTabsAdapter(
companion object { companion object {
private val EXTRA_ADAPTER_POSITION = "adapter_position" private const val EXTRA_ADAPTER_POSITION = "adapter_position"
} }
} }

View File

@ -87,12 +87,12 @@ class VariousItemsAdapter(
} }
private fun getItemViewType(obj: Any): Int { private fun getItemViewType(obj: Any): Int {
when (obj) { return when (obj) {
is ParcelableStatus -> return VIEW_TYPE_STATUS is ParcelableStatus -> VIEW_TYPE_STATUS
is ParcelableUser -> return VIEW_TYPE_USER is ParcelableUser -> VIEW_TYPE_USER
is ParcelableUserList -> return VIEW_TYPE_USER_LIST is ParcelableUserList -> VIEW_TYPE_USER_LIST
is ParcelableHashtag -> return VIEW_TYPE_HASHTAG is ParcelableHashtag -> VIEW_TYPE_HASHTAG
else -> throw UnsupportedOperationException("Unsupported object " + obj) else -> throw UnsupportedOperationException("Unsupported object $obj")
} }
} }
@ -112,9 +112,9 @@ class VariousItemsAdapter(
companion object { companion object {
val VIEW_TYPE_STATUS = 1 const val VIEW_TYPE_STATUS = 1
val VIEW_TYPE_USER = 2 const val VIEW_TYPE_USER = 2
val VIEW_TYPE_USER_LIST = 3 const val VIEW_TYPE_USER_LIST = 3
val VIEW_TYPE_HASHTAG = 4 const val VIEW_TYPE_HASHTAG = 4
} }
} }

View File

@ -36,7 +36,7 @@ interface ILoadMoreSupportAdapter {
annotation class IndicatorPosition annotation class IndicatorPosition
companion object { companion object {
val ITEM_VIEW_TYPE_LOAD_INDICATOR = 0 const val ITEM_VIEW_TYPE_LOAD_INDICATOR = 0
const val NONE: Long = 0 const val NONE: Long = 0
const val START: Long = 1 const val START: Long = 1

View File

@ -329,7 +329,7 @@ class TwidereApplication : Application(), OnSharedPreferenceChangeListener {
companion object { 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 var instance: TwidereApplication? = null
private set private set

View File

@ -147,10 +147,10 @@ object profileImageStyleKey : KSimpleKey<Int>(KEY_PROFILE_IMAGE_STYLE, ImageShap
object mediaPreviewStyleKey : KSimpleKey<Int>(KEY_MEDIA_PREVIEW_STYLE, PreviewStyle.CROP) { object mediaPreviewStyleKey : KSimpleKey<Int>(KEY_MEDIA_PREVIEW_STYLE, PreviewStyle.CROP) {
override fun read(preferences: SharedPreferences): Int { override fun read(preferences: SharedPreferences): Int {
when (preferences.getString(key, null)) { return when (preferences.getString(key, null)) {
VALUE_MEDIA_PREVIEW_STYLE_SCALE -> return PreviewStyle.SCALE VALUE_MEDIA_PREVIEW_STYLE_SCALE -> PreviewStyle.SCALE
VALUE_MEDIA_PREVIEW_STYLE_REAL_SIZE -> return PreviewStyle.ACTUAL_SIZE VALUE_MEDIA_PREVIEW_STYLE_REAL_SIZE -> PreviewStyle.ACTUAL_SIZE
else -> return PreviewStyle.CROP else -> PreviewStyle.CROP
} }
} }

View File

@ -1,6 +1,8 @@
package org.mariotaku.twidere.extension package org.mariotaku.twidere.extension
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import kotlin.math.max
import kotlin.math.roundToInt
fun BitmapFactory.Options.calculateInSampleSize(preferredWidth: Int, preferredHeight: Int): Int { fun BitmapFactory.Options.calculateInSampleSize(preferredWidth: Int, preferredHeight: Int): Int {
if (preferredHeight > outHeight && preferredWidth > outWidth) { if (preferredHeight > outHeight && preferredWidth > outWidth) {
@ -9,6 +11,7 @@ fun BitmapFactory.Options.calculateInSampleSize(preferredWidth: Int, preferredHe
if (preferredHeight <= 0 && preferredWidth <= 0) { if (preferredHeight <= 0 && preferredWidth <= 0) {
return 1 return 1
} }
val result = Math.round(Math.max(outWidth, outHeight) / Math.max(preferredWidth, preferredHeight).toFloat()) val result = (max(outWidth, outHeight) / max(preferredWidth, preferredHeight)
return Math.max(1, result) .toFloat()).roundToInt()
return max(1, result)
} }

View File

@ -114,20 +114,20 @@ fun RequestManager.loadProfileImage(context: Context, conversation: ParcelableMe
size: String? = null): RequestBuilder<*> { size: String? = null): RequestBuilder<*> {
if (conversation.conversation_type == ParcelableMessageConversation.ConversationType.ONE_TO_ONE) { if (conversation.conversation_type == ParcelableMessageConversation.ConversationType.ONE_TO_ONE) {
val user = conversation.user val user = conversation.user
if (user != null) { return if (user != null) {
return loadProfileImage(context, user, shapeStyle, cornerRadius, cornerRadiusRatio, size) loadProfileImage(context, user, shapeStyle, cornerRadius, cornerRadiusRatio, size)
} else { } else {
// TODO: show default conversation icon // TODO: show default conversation icon
return loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle, loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle,
cornerRadius, cornerRadiusRatio) cornerRadius, cornerRadiusRatio)
} }
} else { } else {
if (conversation.conversation_avatar != null) { return if (conversation.conversation_avatar != null) {
return loadProfileImage(context, conversation.conversation_avatar, shapeStyle, cornerRadius, loadProfileImage(context, conversation.conversation_avatar, shapeStyle, cornerRadius,
cornerRadiusRatio, size) cornerRadiusRatio, size)
} else { } else {
return loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle, loadProfileImage(context, R.drawable.ic_profile_image_default_group, shapeStyle,
cornerRadius, cornerRadiusRatio) cornerRadius, cornerRadiusRatio)
} }
} }
} }

View File

@ -30,5 +30,5 @@ fun ListView.updateSelectionItems(menu: Menu) {
val listCount = count val listCount = count
menu.setItemAvailability(R.id.select_none, checkedCount > 0) menu.setItemAvailability(R.id.select_none, checkedCount > 0)
menu.setItemAvailability(R.id.select_all, checkedCount < listCount) 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)
} }

View File

@ -62,17 +62,17 @@ fun Rect.offsetEndTo(x: Int, layoutDirection: Int) {
} }
fun Rect.getStart(layoutDirection: Int): Int { fun Rect.getStart(layoutDirection: Int): Int {
if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { return if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
return this.right this.right
} else { } else {
return this.left this.left
} }
} }
fun Rect.getEnd(layoutDirection: Int): Int { fun Rect.getEnd(layoutDirection: Int): Int {
if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { return if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
return this.left this.left
} else { } else {
return this.right this.right
} }
} }

View File

@ -43,15 +43,19 @@ fun View.getFrame(rect: Rect) {
@UiThread @UiThread
fun View.getFrameRelatedTo(rect: Rect, other: View? = null) { fun View.getFrameRelatedTo(rect: Rect, other: View? = null) {
this.getFrame(rect) this.getFrame(rect)
if (other == null) { when {
offsetToRoot(this, rect) other == null -> {
} else if (other === this) { offsetToRoot(this, rect)
rect.offsetTo(0, 0) }
} else if (other !== parent) { other === this -> {
offsetToRoot(this, rect) rect.offsetTo(0, 0)
other.getFrame(tempRect) }
offsetToRoot(other, tempRect) other !== parent -> {
rect.offset(-tempRect.left, -tempRect.top) offsetToRoot(this, rect)
other.getFrame(tempRect)
offsetToRoot(other, tempRect)
rect.offset(-tempRect.left, -tempRect.top)
}
} }
} }

View File

@ -30,5 +30,5 @@ fun ContentTypeField.getIntParameter(name: String, def: Int): Int {
} }
fun ContentTypeField.getBooleanParameter(name: String): Boolean { fun ContentTypeField.getBooleanParameter(name: String): Boolean {
return getParameter(name).toBoolean() return this.getParameter(name)!!.toBoolean()
} }

View File

@ -15,6 +15,7 @@ import org.mariotaku.twidere.util.InternalTwitterContentUtils
import org.mariotaku.twidere.util.text.FanfouValidator import org.mariotaku.twidere.util.text.FanfouValidator
import org.mariotaku.twidere.util.text.MastodonValidator import org.mariotaku.twidere.util.text.MastodonValidator
import org.mariotaku.twidere.util.text.TwitterValidator import org.mariotaku.twidere.util.text.TwitterValidator
import kotlin.math.min
fun AccountDetails.isOfficial(context: Context?): Boolean { fun AccountDetails.isOfficial(context: Context?): Boolean {
if (context == null) { if (context == null) {
@ -115,10 +116,10 @@ val Array<AccountDetails>.textLimit: Int
forEach { details -> forEach { details ->
val currentLimit = details.textLimit val currentLimit = details.textLimit
if (currentLimit != 0) { if (currentLimit != 0) {
if (limit <= 0) { limit = if (limit <= 0) {
limit = currentLimit currentLimit
} else { } else {
limit = Math.min(limit, currentLimit) min(limit, currentLimit)
} }
} }
} }

View File

@ -175,10 +175,10 @@ internal object AccountDataQueue {
return callable.call() return callable.call()
} }
val future = executor.submit(callable) val future = executor.submit(callable)
try { return try {
return future.get(1, TimeUnit.SECONDS) future.get(1, TimeUnit.SECONDS)
} catch (e: TimeoutException) { } catch (e: TimeoutException) {
return manager.getUserData(account, key) manager.getUserData(account, key)
} }
} }
@ -190,10 +190,10 @@ internal object AccountDataQueue {
return callable.call() return callable.call()
} }
val future = executor.submit(callable) val future = executor.submit(callable)
try { return try {
return future.get(1, TimeUnit.SECONDS) future.get(1, TimeUnit.SECONDS)
} catch (e: TimeoutException) { } catch (e: TimeoutException) {
return manager.peekAuthToken(account, authTokenType) manager.peekAuthToken(account, authTokenType)
} }
} }
} }

View File

@ -63,12 +63,11 @@ fun Credentials.getAuthorization(cls: Class<*>?): Authorization {
} }
fun Credentials.getEndpoint(cls: Class<*>): Endpoint { fun Credentials.getEndpoint(cls: Class<*>): Endpoint {
val apiUrlFormat: String
val noVersionSuffix = this.no_version_suffix val noVersionSuffix = this.no_version_suffix
if (!TextUtils.isEmpty(this.api_url_format)) { val apiUrlFormat: String = if (!TextUtils.isEmpty(this.api_url_format)) {
apiUrlFormat = this.api_url_format this.api_url_format
} else { } else {
apiUrlFormat = DEFAULT_TWITTER_API_URL_FORMAT DEFAULT_TWITTER_API_URL_FORMAT
} }
val domain: String? val domain: String?
val versionSuffix: String? val versionSuffix: String?
@ -113,11 +112,10 @@ fun Credentials.getEndpoint(cls: Class<*>): Endpoint {
} }
val endpointUrl = MicroBlogAPIFactory.getApiUrl(apiUrlFormat, domain, versionSuffix) val endpointUrl = MicroBlogAPIFactory.getApiUrl(apiUrlFormat, domain, versionSuffix)
if (this is OAuthCredentials) { if (this is OAuthCredentials) {
val signEndpointUrl: String val signEndpointUrl: String = if (same_oauth_signing_url) {
if (same_oauth_signing_url) { endpointUrl
signEndpointUrl = endpointUrl
} else { } else {
signEndpointUrl = MicroBlogAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix) MicroBlogAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix)
} }
return OAuthEndpoint(endpointUrl, signEndpointUrl) return OAuthEndpoint(endpointUrl, signEndpointUrl)
} }
@ -180,11 +178,11 @@ internal fun Credentials.authorizationHeader(
): String { ): String {
val auth = getAuthorization(cls) val auth = getAuthorization(cls)
val endpoint: Endpoint val endpoint: Endpoint
if (auth is OAuthAuthorization) { endpoint = if (auth is OAuthAuthorization) {
endpoint = OAuthEndpoint(TwidereMediaDownloader.getEndpoint(modifiedUri), OAuthEndpoint(TwidereMediaDownloader.getEndpoint(modifiedUri),
TwidereMediaDownloader.getEndpoint(uri)) TwidereMediaDownloader.getEndpoint(uri))
} else { } else {
endpoint = Endpoint(TwidereMediaDownloader.getEndpoint(modifiedUri)) Endpoint(TwidereMediaDownloader.getEndpoint(modifiedUri))
} }
val queries = MultiValueMap<String>() val queries = MultiValueMap<String>()
for (name in uri.queryParameterNames) { for (name in uri.queryParameterNames) {

View File

@ -122,23 +122,23 @@ fun Draft.readMimeMessageFrom(context: Context, st: InputStream): Boolean {
fun Draft.getActionName(context: Context): String? { fun Draft.getActionName(context: Context): String? {
if (TextUtils.isEmpty(action_type)) return context.getString(R.string.update_status) if (TextUtils.isEmpty(action_type)) return context.getString(R.string.update_status)
when (action_type) { when (action_type) {
Draft.Action.UPDATE_STATUS, Draft.Action.UPDATE_STATUS_COMPAT_1, Action.UPDATE_STATUS, Action.UPDATE_STATUS_COMPAT_1,
Draft.Action.UPDATE_STATUS_COMPAT_2 -> { Action.UPDATE_STATUS_COMPAT_2 -> {
return context.getString(R.string.update_status) return context.getString(R.string.update_status)
} }
Draft.Action.REPLY -> { Action.REPLY -> {
return context.getString(R.string.action_reply) return context.getString(R.string.action_reply)
} }
Draft.Action.QUOTE -> { Action.QUOTE -> {
return context.getString(R.string.action_quote) return context.getString(R.string.action_quote)
} }
Draft.Action.FAVORITE -> { Action.FAVORITE -> {
return context.getString(R.string.action_favorite) return context.getString(R.string.action_favorite)
} }
Draft.Action.RETWEET -> { Action.RETWEET -> {
return context.getString(R.string.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) return context.getString(R.string.send_direct_message)
} }
} }
@ -157,8 +157,8 @@ fun Draft.applyUpdateStatus(statusUpdate: ParcelableStatusUpdate) {
fun draftActionTypeString(@Draft.Action action: String?): String { fun draftActionTypeString(@Draft.Action action: String?): String {
return when (action) { return when (action) {
Draft.Action.QUOTE -> "quote" Action.QUOTE -> "quote"
Draft.Action.REPLY -> "reply" Action.REPLY -> "reply"
else -> "tweet" else -> "tweet"
} }
} }

View File

@ -24,6 +24,8 @@ import androidx.core.os.LocaleListCompat
import org.mariotaku.ktextension.localesCompat import org.mariotaku.ktextension.localesCompat
import org.mariotaku.twidere.model.presentation.LaunchPresentation import org.mariotaku.twidere.model.presentation.LaunchPresentation
import java.util.* import java.util.*
import kotlin.math.abs
import kotlin.math.roundToInt
fun LaunchPresentation.shouldShow(context: Context): Boolean { fun LaunchPresentation.shouldShow(context: Context): Boolean {
// Check language // Check language
@ -69,16 +71,16 @@ fun LaunchPresentation.Image.displayingScore(viewDensity: Float, viewWidth: Int,
viewWidth < width && viewHeight < height -> { viewWidth < width && viewHeight < height -> {
val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f) val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f)
val diffH = (height / viewHeight.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 -> { else -> {
val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f) val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f)
val diffH = (height / viewHeight.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) { 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 return score
} }

View File

@ -46,7 +46,7 @@ fun CardEntity.toParcelable(accountKey: UserKey, accountType: String): Parcelabl
fun ParcelableCardEntity.getAsBoolean(key: String, def: Boolean): Boolean { fun ParcelableCardEntity.getAsBoolean(key: String, def: Boolean): Boolean {
val value = getValue(key) ?: return def val value = getValue(key) ?: return def
return value.value.toBoolean() return value.value!!.toBoolean()
} }
fun ParcelableCardEntity.getAsString(key: String, def: String?): String? { 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 { fun ParcelableCardEntity.getAsDate(key: String, def: Date): Date {
val value = getValue(key) ?: return def val value = getValue(key) ?: return def
try { return try {
return ParcelableCardEntityUtils.sISOFormat.parse(value.value) ParcelableCardEntityUtils.sISOFormat.parse(value.value)
} catch (e: ParseException) { } catch (e: ParseException) {
return def def
} }
} }

View File

@ -27,7 +27,7 @@ fun ParcelableMedia.getBestVideoUrlAndType(supportedTypes: Array<String>): Pair<
val videoInfo = video_info ?: return Pair(mediaUrl, null) val videoInfo = video_info ?: return Pair(mediaUrl, null)
val firstMatch = videoInfo.variants.filter { variant -> val firstMatch = videoInfo.variants.filter { variant ->
supportedTypes.any { it.equals(variant.content_type, ignoreCase = true) } 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) return Pair(firstMatch.url, firstMatch.content_type)
} }
ParcelableMedia.Type.CARD_ANIMATED_GIF -> { ParcelableMedia.Type.CARD_ANIMATED_GIF -> {

View File

@ -12,16 +12,16 @@ import org.mariotaku.twidere.util.BitmapFactoryUtils
*/ */
fun ParcelableMediaUpdate.getMimeType(resolver: ContentResolver): String? { fun ParcelableMediaUpdate.getMimeType(resolver: ContentResolver): String? {
val uri = Uri.parse(this.uri) val uri = Uri.parse(this.uri)
return resolver.getType(uri) ?: when (type) { return resolver.getType(uri) ?: return when (type) {
ParcelableMedia.Type.ANIMATED_GIF -> { ParcelableMedia.Type.ANIMATED_GIF -> {
return "image/gif" "image/gif"
} }
ParcelableMedia.Type.IMAGE -> { ParcelableMedia.Type.IMAGE -> {
val o = BitmapFactory.Options() val o = BitmapFactory.Options()
o.inJustDecodeBounds = true o.inJustDecodeBounds = true
BitmapFactoryUtils.decodeUri(resolver, uri, opts = o) BitmapFactoryUtils.decodeUri(resolver, uri, opts = o)
return o.outMimeType o.outMimeType
} }
else -> return null else -> null
} }
} }

View File

@ -53,12 +53,12 @@ val ParcelableMessageConversation.readOnly: Boolean
var ParcelableMessageConversation.notificationDisabled: Boolean var ParcelableMessageConversation.notificationDisabled: Boolean
get() { get() {
when (conversation_extras_type) { return when (conversation_extras_type) {
ExtrasType.TWITTER_OFFICIAL -> { ExtrasType.TWITTER_OFFICIAL -> {
return (conversation_extras as? TwitterOfficialConversationExtras)?.notificationsDisabled ?: false (conversation_extras as? TwitterOfficialConversationExtras)?.notificationsDisabled ?: false
} }
else -> { else -> {
return (conversation_extras as? DefaultConversationExtras)?.notificationsDisabled ?: false (conversation_extras as? DefaultConversationExtras)?.notificationsDisabled ?: false
} }
} }
} }

View File

@ -46,42 +46,42 @@ internal fun getSummaryText(context: Context, manager: UserColorNameManager, nam
} else { } else {
res.getQuantityString(R.plurals.N_users, users.size, users.size) res.getQuantityString(R.plurals.N_users, users.size, users.size)
} }
if (sender != null) { return if (sender != null) {
return res.getString(R.string.message_format_participants_join_added, res.getString(R.string.message_format_participants_join_added,
manager.getDisplayName(sender, nameFirst), joinName) manager.getDisplayName(sender, nameFirst), joinName)
} else { } else {
return res.getString(R.string.message_format_participants_join, joinName) res.getString(R.string.message_format_participants_join, joinName)
} }
} }
MessageType.PARTICIPANTS_LEAVE -> { MessageType.PARTICIPANTS_LEAVE -> {
val users = (extras as UserArrayExtras).users val users = (extras as UserArrayExtras).users
val res = context.resources val res = context.resources
if (users.size == 1) { return if (users.size == 1) {
val displayName = manager.getDisplayName(users[0], nameFirst) 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 { } else {
val usersName = res.getQuantityString(R.plurals.N_users, users.size, users.size) 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 -> { MessageType.CONVERSATION_NAME_UPDATE -> {
extras as ConversationInfoUpdatedExtras extras as ConversationInfoUpdatedExtras
val res = context.resources val res = context.resources
if (extras.user != null) { return if (extras.user != null) {
return res.getString(R.string.message_format_conversation_name_update_by_user, res.getString(R.string.message_format_conversation_name_update_by_user,
manager.getDisplayName(extras.user, nameFirst), extras.name) manager.getDisplayName(extras.user, nameFirst), extras.name)
} else { } 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 -> { MessageType.CONVERSATION_AVATAR_UPDATE -> {
extras as ConversationInfoUpdatedExtras extras as ConversationInfoUpdatedExtras
val res = context.resources val res = context.resources
if (extras.user != null) { return if (extras.user != null) {
return res.getString(R.string.message_format_conversation_avatar_update_by_user, res.getString(R.string.message_format_conversation_avatar_update_by_user,
manager.getDisplayName(extras.user, nameFirst)) manager.getDisplayName(extras.user, nameFirst))
} else { } else {
return res.getString(R.string.message_format_conversation_avatar_update) res.getString(R.string.message_format_conversation_avatar_update)
} }
} }
} }

View File

@ -26,9 +26,9 @@ import org.mariotaku.twidere.model.UserKey
* Created by mariotaku on 2017/4/23. * Created by mariotaku on 2017/4/23.
*/ */
fun ParcelableUserMention.getAcct(accountKey: UserKey): String { fun ParcelableUserMention.getAcct(accountKey: UserKey): String {
if (accountKey.host == key.host) { return if (accountKey.host == key.host) {
return screen_name screen_name
} else { } else {
return "$screen_name@${key.host}" "$screen_name@${key.host}"
} }
} }

View File

@ -220,7 +220,11 @@ fun Status.applyTo(accountKey: UserKey, accountType: String, profileImageSize: S
fun Status.formattedTextWithIndices(): StatusTextWithIndices { fun Status.formattedTextWithIndices(): StatusTextWithIndices {
val source = CodePointArray(this.fullText ?: this.text!!) 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) builder.addEntities(this)
val textWithIndices = StatusTextWithIndices() val textWithIndices = StatusTextWithIndices()
val (text, spans) = builder.buildWithIndices() val (text, spans) = builder.buildWithIndices()

View File

@ -29,14 +29,18 @@ fun Attachment.toParcelable(externalUrl: String?) : ParcelableMedia? {
val mimeType = mimetype ?: return null val mimeType = mimetype ?: return null
val result = ParcelableMedia() val result = ParcelableMedia()
if (mimeType.startsWith("image/")) { when {
result.type = ParcelableMedia.Type.IMAGE mimeType.startsWith("image/") -> {
} else if (mimeType.startsWith("video/")) { result.type = ParcelableMedia.Type.IMAGE
result.type = ParcelableMedia.Type.VIDEO }
} else { mimeType.startsWith("video/") -> {
// https://github.com/TwidereProject/Twidere-Android/issues/729 result.type = ParcelableMedia.Type.VIDEO
// Skip unsupported attachment }
return null else -> {
// https://github.com/TwidereProject/Twidere-Android/issues/729
// Skip unsupported attachment
return null
}
} }
result.width = width result.width = width
result.height = height result.height = height

View File

@ -33,9 +33,9 @@ fun Extractor.extractMentionsAndNonMentionStartIndex(text: String, mentions: Arr
if (entity.start != nextExpectedPos) break if (entity.start != nextExpectedPos) break
// Break at first mention not found in `inReplyTo.mentions` // Break at first mention not found in `inReplyTo.mentions`
if (mentions?.none { entity.value.equals(it.screen_name, ignoreCase = true) } == true) break 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[it].isWhitespace()
} ?: text.indices.endInclusive + 1 } ?: text.indices.last + 1
} }
return MentionsAndNonMentionStartIndex(entities, nextExpectedPos) return MentionsAndNonMentionStartIndex(entities, nextExpectedPos)
} }

View File

@ -22,6 +22,7 @@ package org.mariotaku.twidere.extension.view
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.view.View import android.view.View
import androidx.recyclerview.widget.recyclerView import androidx.recyclerview.widget.recyclerView
import kotlin.math.max
fun RecyclerView.LayoutManager.calculateSpaceItemHeight(child: View, spaceViewType: Int, typeStart: Int): Int { fun RecyclerView.LayoutManager.calculateSpaceItemHeight(child: View, spaceViewType: Int, typeStart: Int): Int {
val recyclerView = recyclerView ?: return 0 val recyclerView = recyclerView ?: return 0
@ -39,7 +40,7 @@ fun RecyclerView.LayoutManager.calculateSpaceItemHeight(child: View, spaceViewTy
if (heightBeforeSpace != 0) { if (heightBeforeSpace != 0) {
val spaceHeight = recyclerView.measuredHeight - recyclerView.paddingTop - val spaceHeight = recyclerView.measuredHeight - recyclerView.paddingTop -
recyclerView.paddingBottom - heightBeforeSpace recyclerView.paddingBottom - heightBeforeSpace
return Math.max(0, spaceHeight) return max(0, spaceHeight)
} }
return -1 return -1
} }

View File

@ -48,14 +48,19 @@ class APIEditorDialogFragment : BaseDialogFragment() {
val targetFragment = this.targetFragment val targetFragment = this.targetFragment
val parentFragment = this.parentFragment val parentFragment = this.parentFragment
val host = this.host val host = this.host
if (targetFragment is APIEditorCallback) { when {
targetFragment.onSaveAPIConfig(applyCustomAPIConfig()) targetFragment is APIEditorCallback -> {
} else if (parentFragment is APIEditorCallback) { targetFragment.onSaveAPIConfig(applyCustomAPIConfig())
parentFragment.onSaveAPIConfig(applyCustomAPIConfig()) }
} else if (host is APIEditorCallback) { parentFragment is APIEditorCallback -> {
host.onSaveAPIConfig(applyCustomAPIConfig()) parentFragment.onSaveAPIConfig(applyCustomAPIConfig())
} else { }
kPreferences[defaultAPIConfigKey] = applyCustomAPIConfig() host is APIEditorCallback -> {
host.onSaveAPIConfig(applyCustomAPIConfig())
}
else -> {
kPreferences[defaultAPIConfigKey] = applyCustomAPIConfig()
}
} }
} }
builder.setNegativeButton(android.R.string.cancel, null) builder.setNegativeButton(android.R.string.cancel, null)
@ -94,10 +99,10 @@ class APIEditorDialogFragment : BaseDialogFragment() {
tag = "api_url_format_help") tag = "api_url_format_help")
} }
if (savedInstanceState != null) { apiConfig = if (savedInstanceState != null) {
apiConfig = savedInstanceState.getParcelable(EXTRA_API_CONFIG)!! savedInstanceState.getParcelable(EXTRA_API_CONFIG)!!
} else { } else {
apiConfig = arguments?.getParcelable(EXTRA_API_CONFIG) ?: kPreferences[defaultAPIConfigKey] arguments?.getParcelable(EXTRA_API_CONFIG) ?: kPreferences[defaultAPIConfigKey]
} }
displayCustomApiConfig() displayCustomApiConfig()
} }

View File

@ -103,8 +103,10 @@ abstract class AbsActivitiesFragment protected constructor() :
registerForContextMenu(recyclerView) registerForContextMenu(recyclerView)
navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter, navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter,
this) this)
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, false, pauseOnScrollListener = PauseRecyclerViewOnScrollListener(
requestManager) pauseOnScroll = false, pauseOnFling = false,
requestManager = requestManager
)
val loaderArgs = Bundle(arguments) val loaderArgs = Bundle(arguments)
loaderArgs.putBoolean(EXTRA_FROM_USER, true) loaderArgs.putBoolean(EXTRA_FROM_USER, true)
@ -237,7 +239,7 @@ abstract class AbsActivitiesFragment protected constructor() :
adapter.getTimestamp(lastReadPosition) adapter.getTimestamp(lastReadPosition)
} }
lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0 lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0
loadMore = activityRange.endInclusive in 0..lastVisibleItemPosition loadMore = activityRange.last in 0..lastVisibleItemPosition
} else if (rememberPosition && readPositionTag != null) { } else if (rememberPosition && readPositionTag != null) {
val syncManager = timelineSyncManager val syncManager = timelineSyncManager
val positionTag = this.readPositionTag val positionTag = this.readPositionTag
@ -547,13 +549,13 @@ abstract class AbsActivitiesFragment protected constructor() :
(recyclerView.layoutManager as LinearLayoutManager).orientation) { (recyclerView.layoutManager as LinearLayoutManager).orientation) {
override fun isDividerEnabled(childPos: Int): Boolean { override fun isDividerEnabled(childPos: Int): Boolean {
if (childPos >= layoutManager.itemCount || childPos < 0) return false 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_STATUS, ITEM_VIEW_TYPE_TITLE_SUMMARY, ITEM_VIEW_TYPE_GAP,
ITEM_VIEW_TYPE_STUB -> { ITEM_VIEW_TYPE_STUB -> {
return true true
} }
else -> { else -> {
return false false
} }
} }
} }

View File

@ -39,6 +39,7 @@ import org.mariotaku.twidere.util.ContentScrollHandler.ContentListSupport
import org.mariotaku.twidere.util.ListViewScrollHandler import org.mariotaku.twidere.util.ListViewScrollHandler
import org.mariotaku.twidere.util.ThemeUtils import org.mariotaku.twidere.util.ThemeUtils
import org.mariotaku.twidere.util.TwidereColorUtils import org.mariotaku.twidere.util.TwidereColorUtils
import kotlin.math.roundToInt
/** /**
* Created by mariotaku on 15/4/16. * Created by mariotaku on 15/4/16.
@ -211,10 +212,11 @@ abstract class AbsContentListViewFragment<A : ListAdapter> : BaseFragment(),
} }
val density = resources.displayMetrics.density val density = resources.displayMetrics.density
val progressCircleDiameter = swipeLayout.progressCircleDiameter 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 val swipeStart = systemWindowsInsets.top - controlBarOffsetPixels - progressCircleDiameter
// 64: SwipeRefreshLayout.DEFAULT_CIRCLE_TARGET // 64: SwipeRefreshLayout.DEFAULT_CIRCLE_TARGET
val swipeDistance = Math.round(64 * density) val swipeDistance = (64 * density).roundToInt()
swipeLayout.setProgressViewOffset(false, swipeStart, swipeStart + swipeDistance) swipeLayout.setProgressViewOffset(false, swipeStart, swipeStart + swipeDistance)
} }

View File

@ -146,7 +146,7 @@ abstract class AbsMediaStatusesFragment : AbsContentRecyclerViewFragment<Stagger
val maxId = pagination?.maxId?.takeIf(String::isNotEmpty) val maxId = pagination?.maxId?.takeIf(String::isNotEmpty)
val sinceId = pagination?.sinceId?.takeIf(String::isNotEmpty) val sinceId = pagination?.sinceId?.takeIf(String::isNotEmpty)
if (sinceId == null && maxId != null) { if (sinceId == null && maxId != null) {
if (data != null && !data.isEmpty()) { if (data != null && data.isNotEmpty()) {
return changed return changed
} }
} }

View File

@ -147,8 +147,10 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
adapter.statusClickListener = this adapter.statusClickListener = this
registerForContextMenu(recyclerView) registerForContextMenu(recyclerView)
navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter, this) navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter, this)
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, false, pauseOnScrollListener = PauseRecyclerViewOnScrollListener(
requestManager) pauseOnScroll = false, pauseOnFling = false,
requestManager = requestManager
)
if (shouldInitLoader) { if (shouldInitLoader) {
initLoaderIfNeeded() initLoaderIfNeeded()
@ -288,15 +290,19 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
} else { } else {
firstVisibleItemPosition firstVisibleItemPosition
}.coerceInOr(statusRange, -1) }.coerceInOr(statusRange, -1)
lastReadId = if (lastReadPosition < 0) { lastReadId = when {
-1 lastReadPosition < 0 -> {
} else if (useSortIdAsReadPosition) { -1
adapter.getStatusSortId(lastReadPosition, false) }
} else { useSortIdAsReadPosition -> {
adapter.getStatusPositionKey(lastReadPosition) adapter.getStatusSortId(lastReadPosition, false)
}
else -> {
adapter.getStatusPositionKey(lastReadPosition)
}
} }
lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0 lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0
loadMore = statusRange.endInclusive in 0..lastVisibleItemPosition loadMore = statusRange.last in 0..lastVisibleItemPosition
} else if (rememberPosition) { } else if (rememberPosition) {
val syncManager = timelineSyncManager val syncManager = timelineSyncManager
val positionTag = this.readPositionTag val positionTag = this.readPositionTag
@ -621,15 +627,19 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
} }
} }
R.id.favorite -> { R.id.favorite -> {
if (fragment.preferences[favoriteConfirmationKey]) { when {
fragment.executeAfterFragmentResumed { fragment.preferences[favoriteConfirmationKey] -> {
FavoriteConfirmDialogFragment.show(it.childFragmentManager, fragment.executeAfterFragmentResumed {
FavoriteConfirmDialogFragment.show(it.childFragmentManager,
status.account_key, status.id, status) 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?) { fun handleActionActivityResult(fragment: BaseFragment, requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) { when (requestCode) {
AbsStatusesFragment.REQUEST_FAVORITE_SELECT_ACCOUNT -> { REQUEST_FAVORITE_SELECT_ACCOUNT -> {
if (resultCode != Activity.RESULT_OK || data == null) return if (resultCode != Activity.RESULT_OK || data == null) return
val accountKey = data.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)!! val accountKey = data.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)!!
val extras = data.getBundleExtra(EXTRA_EXTRAS)!! val extras = data.getBundleExtra(EXTRA_EXTRAS)!!
@ -667,7 +677,7 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
fragment.twitterWrapper.createFavoriteAsync(accountKey, status) fragment.twitterWrapper.createFavoriteAsync(accountKey, status)
} }
} }
AbsStatusesFragment.REQUEST_RETWEET_SELECT_ACCOUNT -> { REQUEST_RETWEET_SELECT_ACCOUNT -> {
if (resultCode != Activity.RESULT_OK || data == null) return if (resultCode != Activity.RESULT_OK || data == null) return
val accountKey = data.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)!! val accountKey = data.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)!!
val extras = data.getBundleExtra(EXTRA_EXTRAS)!! val extras = data.getBundleExtra(EXTRA_EXTRAS)!!
@ -719,16 +729,20 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
return true return true
} }
ACTION_STATUS_FAVORITE -> { ACTION_STATUS_FAVORITE -> {
if (fragment.preferences[favoriteConfirmationKey]) { when {
fragment.executeAfterFragmentResumed { fragment.preferences[favoriteConfirmationKey] -> {
FavoriteConfirmDialogFragment.show(it.childFragmentManager, fragment.executeAfterFragmentResumed {
FavoriteConfirmDialogFragment.show(it.childFragmentManager,
status.account_key, status.id, status) 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 return true
} }

View File

@ -532,12 +532,16 @@ class AccountsDashboardFragment : BaseFragment(), LoaderCallbacks<AccountsInfo>,
val width = if (bannerWidth > 0) bannerWidth else defWidth val width = if (bannerWidth > 0) bannerWidth else defWidth
val bannerView = accountProfileBanner.nextView as ImageView val bannerView = accountProfileBanner.nextView as ImageView
val user = account.user val user = account.user
val fallbackBanner = if (user.link_color != 0) { val fallbackBanner = when {
ColorDrawable(user.link_color) user.link_color != 0 -> {
} else if (user.account_color != 0) { ColorDrawable(user.link_color)
ColorDrawable(user.account_color) }
} else { user.account_color != 0 -> {
ColorDrawable(Chameleon.getOverrideTheme(requireActivity(), activity).colorPrimary) ColorDrawable(user.account_color)
}
else -> {
ColorDrawable(Chameleon.getOverrideTheme(requireActivity(), activity).colorPrimary)
}
} }
requestManager.loadProfileBanner(requireContext(), account.user, width).fallback(fallbackBanner) requestManager.loadProfileBanner(requireContext(), account.user, width).fallback(fallbackBanner)

View File

@ -241,6 +241,6 @@ class AccountsManagerFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Li
companion object { companion object {
private val FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion" private const val FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion"
} }
} }

View File

@ -52,7 +52,7 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
filterItems = filterItemsInfo filterItems = filterItemsInfo
val entries = arrayOfNulls<String>(filterItems!!.size) val entries = arrayOfNulls<String>(filterItems!!.size)
val nameFirst = preferences[nameFirstKey] val nameFirst = preferences[nameFirstKey]
for (i in 0 until entries.size) { for (i in entries.indices) {
val info = filterItems!![i] val info = filterItems!![i]
when (info.type) { when (info.type) {
FilterItemInfo.FILTER_TYPE_USER -> { FilterItemInfo.FILTER_TYPE_USER -> {
@ -87,24 +87,29 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
} }
val info = filterItems!![checkPositions.keyAt(i)] val info = filterItems!![checkPositions.keyAt(i)]
val value = info.value val value = info.value
if (value is ParcelableUserMention) { when {
userKeys.add(value.key) value is ParcelableUserMention -> {
userValues.add(ContentValuesCreator.createFilteredUser(value)) userKeys.add(value.key)
} else if (value is UserItem) { userValues.add(ContentValuesCreator.createFilteredUser(value))
userKeys.add(value.key) }
userValues.add(createFilteredUser(value)) value is UserItem -> {
} else if (info.type == FilterItemInfo.FILTER_TYPE_KEYWORD) { userKeys.add(value.key)
val keyword = ParseUtils.parseString(value) userValues.add(createFilteredUser(value))
keywords.add(keyword) }
val values = ContentValues() info.type == FilterItemInfo.FILTER_TYPE_KEYWORD -> {
values.put(Filters.Keywords.VALUE, "#$keyword") val keyword = ParseUtils.parseString(value)
keywordValues.add(values) keywords.add(keyword)
} else if (info.type == FilterItemInfo.FILTER_TYPE_SOURCE) { val values = ContentValues()
val source = ParseUtils.parseString(value) values.put(Filters.Keywords.VALUE, "#$keyword")
sources.add(source) keywordValues.add(values)
val values = ContentValues() }
values.put(Filters.Sources.VALUE, source) info.type == FilterItemInfo.FILTER_TYPE_SOURCE -> {
sourceValues.add(values) val source = ParseUtils.parseString(value)
sources.add(source)
val values = ContentValues()
values.put(Filters.Sources.VALUE, source)
sourceValues.add(values)
}
} }
} }
context?.contentResolver?.let { resolver -> context?.contentResolver?.let { resolver ->
@ -164,12 +169,15 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
} }
private fun getName(manager: UserColorNameManager, value: Any, nameFirst: Boolean): String { private fun getName(manager: UserColorNameManager, value: Any, nameFirst: Boolean): String {
if (value is ParcelableUserMention) { return when (value) {
return manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst) is ParcelableUserMention -> {
} else if (value is UserItem) { manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
return manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst) }
} else is UserItem -> {
return ParseUtils.parseString(value) manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
}
else -> ParseUtils.parseString(value)
}
} }
internal data class FilterItemInfo( internal data class FilterItemInfo(
@ -194,7 +202,7 @@ class AddStatusFilterDialogFragment : BaseDialogFragment() {
companion object { companion object {
val FRAGMENT_TAG = "add_status_filter" const val FRAGMENT_TAG = "add_status_filter"
private fun createFilteredUser(item: UserItem): ContentValues { private fun createFilteredUser(item: UserItem): ContentValues {
val values = ContentValues() val values = ContentValues()

View File

@ -140,8 +140,8 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat(), IBaseFragmen
companion object { companion object {
private val REQUEST_PICK_RINGTONE = 301 private const val REQUEST_PICK_RINGTONE = 301
private val EXTRA_RINGTONE_PREFERENCE_KEY = "internal:ringtone_preference_key" private const val EXTRA_RINGTONE_PREFERENCE_KEY = "internal:ringtone_preference_key"
} }
} }

View File

@ -61,11 +61,8 @@ class ColorPickerDialogFragment : BaseDialogFragment(), DialogInterface.OnClickL
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val color: Int val color: Int
val args = arguments val args = arguments
if (savedInstanceState != null) { color =
color = savedInstanceState.getInt(EXTRA_COLOR, Color.WHITE) savedInstanceState?.getInt(EXTRA_COLOR, Color.WHITE) ?: args!!.getInt(EXTRA_COLOR, Color.WHITE)
} else {
color = args!!.getInt(EXTRA_COLOR, Color.WHITE)
}
val activity = activity val activity = activity
val builder = AlertDialog.Builder(requireActivity()) val builder = AlertDialog.Builder(requireActivity())

View File

@ -48,7 +48,7 @@ class CreateUserBlockDialogFragment : AbsUserMuteBlockDialogFragment() {
companion object { companion object {
val FRAGMENT_TAG = "create_user_block" const val FRAGMENT_TAG = "create_user_block"
fun show(fm: FragmentManager, user: ParcelableUser): CreateUserBlockDialogFragment { fun show(fm: FragmentManager, user: ParcelableUser): CreateUserBlockDialogFragment {
val args = Bundle() val args = Bundle()

View File

@ -49,7 +49,7 @@ class CreateUserMuteDialogFragment : AbsUserMuteBlockDialogFragment() {
companion object { companion object {
val FRAGMENT_TAG = "create_user_mute" const val FRAGMENT_TAG = "create_user_mute"
fun show(fm: FragmentManager, user: ParcelableUser): CreateUserMuteDialogFragment { fun show(fm: FragmentManager, user: ParcelableUser): CreateUserMuteDialogFragment {
val args = Bundle() val args = Bundle()

View File

@ -51,6 +51,8 @@ import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.DataStoreUtils.getTableNameByUri import org.mariotaku.twidere.util.DataStoreUtils.getTableNameByUri
import org.mariotaku.twidere.util.ErrorInfoStore import org.mariotaku.twidere.util.ErrorInfoStore
import org.mariotaku.twidere.util.Utils import org.mariotaku.twidere.util.Utils
import kotlin.math.max
import kotlin.math.min
/** /**
* Displays statuses from database * Displays statuses from database
@ -241,8 +243,8 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
fun replaceStatusStates(result: ParcelableStatus?) { fun replaceStatusStates(result: ParcelableStatus?) {
if (result == null) return if (result == null) return
val lm = layoutManager val lm = layoutManager
val rangeStart = Math.max(adapter.activityStartIndex, lm.findFirstVisibleItemPosition()) val rangeStart = max(adapter.activityStartIndex, lm.findFirstVisibleItemPosition())
val rangeEnd = Math.min(lm.findLastVisibleItemPosition(), adapter.activityStartIndex + adapter.getActivityCount(false) - 1) val rangeEnd = min(lm.findLastVisibleItemPosition(), adapter.activityStartIndex + adapter.getActivityCount(false) - 1)
loop@ for (i in rangeStart..rangeEnd) { loop@ for (i in rangeStart..rangeEnd) {
val activity = adapter.getActivity(i, false) val activity = adapter.getActivity(i, false)
if (result.account_key == activity.account_key && result.id == activity.id) { if (result.account_key == activity.account_key && result.id == activity.id) {
@ -353,7 +355,7 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
class ActivityCursor( class ActivityCursor(
cursor: Cursor, cursor: Cursor,
indies: ObjectCursor.CursorIndices<ParcelableActivity>, indies: CursorIndices<ParcelableActivity>,
val filteredUserIds: Array<UserKey>, val filteredUserIds: Array<UserKey>,
val filteredUserNames: Array<String>, val filteredUserNames: Array<String>,
val filteredUserDescriptions: Array<String> val filteredUserDescriptions: Array<String>

View File

@ -90,7 +90,7 @@ class DeleteUserListMembersDialogFragment : BaseDialogFragment(), DialogInterfac
companion object { companion object {
val FRAGMENT_TAG = "destroy_user_list_member" const val FRAGMENT_TAG = "destroy_user_list_member"
fun show(fm: FragmentManager, userList: ParcelableUserList, fun show(fm: FragmentManager, userList: ParcelableUserList,
vararg users: ParcelableUser): DeleteUserListMembersDialogFragment { vararg users: ParcelableUser): DeleteUserListMembersDialogFragment {

View File

@ -65,7 +65,7 @@ class DestroyFriendshipDialogFragment : BaseDialogFragment(), DialogInterface.On
companion object { companion object {
val FRAGMENT_TAG = "destroy_friendship" const val FRAGMENT_TAG = "destroy_friendship"
fun show(fm: FragmentManager, user: ParcelableUser): DestroyFriendshipDialogFragment { fun show(fm: FragmentManager, user: ParcelableUser): DestroyFriendshipDialogFragment {
val f = DestroyFriendshipDialogFragment() val f = DestroyFriendshipDialogFragment()

View File

@ -69,7 +69,7 @@ class DestroyUserListSubscriptionDialogFragment : BaseDialogFragment(), DialogIn
companion object { companion object {
val FRAGMENT_TAG = "destroy_user_list" const val FRAGMENT_TAG = "destroy_user_list"
fun show(fm: FragmentManager, fun show(fm: FragmentManager,
userList: ParcelableUserList): DestroyUserListSubscriptionDialogFragment { userList: ParcelableUserList): DestroyUserListSubscriptionDialogFragment {

View File

@ -89,14 +89,19 @@ class ExtraFeaturesIntroductionDialogFragment : BaseDialogFragment() {
} }
private fun startActivityForResultOnTarget(intent: Intent) { private fun startActivityForResultOnTarget(intent: Intent) {
if (targetFragment != null) { when {
targetFragment?.startActivityForResult(intent, targetRequestCode) targetFragment != null -> {
} else if (requestCode == 0) { targetFragment?.startActivityForResult(intent, targetRequestCode)
startActivity(intent) }
} else if (parentFragment != null) { requestCode == 0 -> {
parentFragment?.startActivityForResult(intent, requestCode) startActivity(intent)
} else { }
activity?.startActivityForResult(intent, requestCode) parentFragment != null -> {
parentFragment?.startActivityForResult(intent, requestCode)
}
else -> {
activity?.startActivityForResult(intent, requestCode)
}
} }
} }

View File

@ -113,12 +113,16 @@ class GroupFragment : AbsToolbarTabPagesFragment(), LoaderCallbacks<SingleRespon
val twitter = MicroBlogAPIFactory.getInstance(context, accountKey) ?: val twitter = MicroBlogAPIFactory.getInstance(context, accountKey) ?:
throw MicroBlogException("No account") throw MicroBlogException("No account")
val group: Group val group: Group
if (groupId != null) { group = when {
group = twitter.showGroup(groupId) groupId != null -> {
} else if (groupName != null) { twitter.showGroup(groupId)
group = twitter.showGroupByName(groupName) }
} else { groupName != null -> {
return SingleResponse() twitter.showGroupByName(groupName)
}
else -> {
return SingleResponse()
}
} }
return SingleResponse.getInstance(ParcelableGroupUtils.from(group, accountKey, 0, return SingleResponse.getInstance(ParcelableGroupUtils.from(group, accountKey, 0,
group.isMember)) group.isMember))

View File

@ -257,10 +257,10 @@ class HostMappingsListFragment : AbsContentListViewFragment<HostMappingsListFrag
companion object { companion object {
private val EXTRA_EDIT_MODE = "edit_mode" private const val EXTRA_EDIT_MODE = "edit_mode"
private val EXTRA_HOST = "host" private const val EXTRA_HOST = "host"
private val EXTRA_ADDRESS = "address" private const val EXTRA_ADDRESS = "address"
private val EXTRA_EXCLUDED = "excluded" private const val EXTRA_EXCLUDED = "excluded"
} }
} }

View File

@ -153,10 +153,10 @@ class NetworkDiagnosticsFragment : BaseFragment() {
logPrintln() logPrintln()
val baseUrl: String val baseUrl: String
if (details.credentials.api_url_format != null) { baseUrl = if (details.credentials.api_url_format != null) {
baseUrl = MicroBlogAPIFactory.getApiBaseUrl(details.credentials.api_url_format, "api") MicroBlogAPIFactory.getApiBaseUrl(details.credentials.api_url_format, "api")
} else { } else {
baseUrl = MicroBlogAPIFactory.getApiBaseUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api") MicroBlogAPIFactory.getApiBaseUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api")
} }
val client = DependencyHolder.get(context).restHttpClient val client = DependencyHolder.get(context).restHttpClient
var response: HttpResponse? = null var response: HttpResponse? = null
@ -319,8 +319,8 @@ class NetworkDiagnosticsFragment : BaseFragment() {
startDiagnostics.setOnClickListener { startDiagnostics.setOnClickListener {
val intent = Intent(Intent.ACTION_SEND) val intent = Intent(Intent.ACTION_SEND)
intent.type = "text/plain" intent.type = "text/plain"
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Twidere Network Diagnostics") intent.putExtra(Intent.EXTRA_SUBJECT, "Twidere Network Diagnostics")
intent.putExtra(android.content.Intent.EXTRA_TEXT, logText.text) intent.putExtra(Intent.EXTRA_TEXT, logText.text)
startActivity(Intent.createChooser(intent, getString(R.string.action_send))) startActivity(Intent.createChooser(intent, getString(R.string.action_send)))
} }
} }

View File

@ -71,7 +71,7 @@ abstract class ParcelableGroupsFragment : AbsContentListRecyclerViewFragment<Par
get() = arguments?.getParcelable<UserKey?>(EXTRA_ACCOUNT_KEY) get() = arguments?.getParcelable<UserKey?>(EXTRA_ACCOUNT_KEY)
protected fun hasMoreData(data: List<ParcelableGroup>?): Boolean { 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>?) { override fun onLoadFinished(loader: Loader<List<ParcelableGroup>?>, data: List<ParcelableGroup>?) {

View File

@ -46,6 +46,8 @@ import org.mariotaku.twidere.model.pagination.Pagination
import org.mariotaku.twidere.model.pagination.SinceMaxPagination import org.mariotaku.twidere.model.pagination.SinceMaxPagination
import org.mariotaku.twidere.util.Utils import org.mariotaku.twidere.util.Utils
import java.util.* import java.util.*
import kotlin.math.max
import kotlin.math.min
/** /**
* Created by mariotaku on 14/12/3. * Created by mariotaku on 14/12/3.
@ -193,13 +195,12 @@ abstract class ParcelableStatusesFragment : AbsStatusesFragment() {
fun removeStatus(statusId: String) { fun removeStatus(statusId: String) {
val list = adapterData ?: return val list = adapterData ?: return
val dataToRemove = HashSet<ParcelableStatus>() val dataToRemove = HashSet<ParcelableStatus>()
for (i in 0 until list.size) { for (element in list) {
val status = list[i] if (element.id == statusId || element.retweet_id == statusId) {
if (status.id == statusId || status.retweet_id == statusId) { dataToRemove.add(element)
dataToRemove.add(status) } else if (element.my_retweet_id == statusId) {
} else if (status.my_retweet_id == statusId) { element.my_retweet_id = null
status.my_retweet_id = null element.retweet_count = element.retweet_count - 1
status.retweet_count = status.retweet_count - 1
} }
} }
if (list is MutableList) { if (list is MutableList) {
@ -211,8 +212,8 @@ abstract class ParcelableStatusesFragment : AbsStatusesFragment() {
fun replaceStatusStates(status: ParcelableStatus?) { fun replaceStatusStates(status: ParcelableStatus?) {
if (status == null) return if (status == null) return
val lm = layoutManager val lm = layoutManager
val rangeStart = Math.max(adapter.statusStartIndex, lm.findFirstVisibleItemPosition()) val rangeStart = max(adapter.statusStartIndex, lm.findFirstVisibleItemPosition())
val rangeEnd = Math.min(lm.findLastVisibleItemPosition(), adapter.statusStartIndex + adapter.getStatusCount(false) - 1) val rangeEnd = min(lm.findLastVisibleItemPosition(), adapter.statusStartIndex + adapter.getStatusCount(false) - 1)
for (i in rangeStart..rangeEnd) { for (i in rangeStart..rangeEnd) {
val item = adapter.getStatus(i, false) val item = adapter.getStatus(i, false)
if (status == item) { if (status == item) {

View File

@ -73,7 +73,7 @@ abstract class ParcelableUserListsFragment : AbsContentListRecyclerViewFragment<
} }
protected fun hasMoreData(data: List<ParcelableUserList>?): Boolean { 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>) { override fun onLoadFinished(loader: Loader<List<ParcelableUserList>>, data: List<ParcelableUserList>) {

View File

@ -270,7 +270,7 @@ abstract class ParcelableUsersFragment : AbsContentListRecyclerViewFragment<Parc
} }
protected fun hasMoreData(data: List<ParcelableUser>?): Boolean { protected fun hasMoreData(data: List<ParcelableUser>?): Boolean {
return data == null || !data.isEmpty() return data == null || data.isNotEmpty()
} }
protected fun createMessageBusCallback(): Any { protected fun createMessageBusCallback(): Any {

Some files were not shown because too many files have changed in this diff Show More