mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-17 04:00:48 +01:00
improved activities text
improved activities in streaming mode
This commit is contained in:
parent
17418bebf8
commit
ed469b2c82
@ -21,11 +21,43 @@
|
||||
|
||||
package org.mariotaku.microblog.library.twitter.model;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.twidere.model.util.UnixEpochMillisDateConverter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/3/26.
|
||||
*/
|
||||
@JsonObject
|
||||
public class MutedKeyword {
|
||||
@JsonField(name = "id")
|
||||
String id;
|
||||
@JsonField(name = "keyword")
|
||||
String keyword;
|
||||
@JsonField(name = "created_at", typeConverter = UnixEpochMillisDateConverter.class)
|
||||
Date createdAt;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MutedKeyword{" +
|
||||
"id='" + id + '\'' +
|
||||
", keyword='" + keyword + '\'' +
|
||||
", createdAt=" + createdAt +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.model.util;
|
||||
|
||||
import com.bluelinelabs.logansquare.typeconverters.TypeConverter;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/3/25.
|
||||
*/
|
||||
|
||||
public class UnixEpochMillisDateConverter implements TypeConverter<Date> {
|
||||
@Override
|
||||
public Date parse(final JsonParser jsonParser) throws IOException {
|
||||
long value = jsonParser.nextLongValue(-1);
|
||||
return new Date(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Date object, final String fieldName,
|
||||
final boolean writeFieldNameForObject, final JsonGenerator jsonGenerator) throws IOException {
|
||||
if (writeFieldNameForObject) {
|
||||
jsonGenerator.writeFieldName(fieldName);
|
||||
}
|
||||
if (object == null) {
|
||||
jsonGenerator.writeNull();
|
||||
} else {
|
||||
jsonGenerator.writeNumber(object.getTime());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.model.util;
|
||||
|
||||
import com.bluelinelabs.logansquare.typeconverters.TypeConverter;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/3/25.
|
||||
*/
|
||||
|
||||
public class UnixEpochSecondDateConverter implements TypeConverter<Date> {
|
||||
@Override
|
||||
public Date parse(final JsonParser jsonParser) throws IOException {
|
||||
long value = jsonParser.nextLongValue(-1);
|
||||
return new Date(TimeUnit.MILLISECONDS.toSeconds(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Date object, final String fieldName,
|
||||
final boolean writeFieldNameForObject, final JsonGenerator jsonGenerator) throws IOException {
|
||||
if (writeFieldNameForObject) {
|
||||
jsonGenerator.writeFieldName(fieldName);
|
||||
}
|
||||
if (object == null) {
|
||||
jsonGenerator.writeNull();
|
||||
} else {
|
||||
jsonGenerator.writeNumber(TimeUnit.SECONDS.toMillis(object.getTime()));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,333 +0,0 @@
|
||||
package org.mariotaku.twidere.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.StyleSpan;
|
||||
|
||||
import org.mariotaku.microblog.library.twitter.model.Activity;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.model.util.ParcelableActivityExtensionsKt;
|
||||
import org.mariotaku.twidere.util.UserColorNameManager;
|
||||
import org.oshkimaadziig.george.androidutils.SpanFormatter;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/1.
|
||||
*/
|
||||
public class ActivityTitleSummaryMessage {
|
||||
private final int icon;
|
||||
private final int color;
|
||||
@NonNull
|
||||
private final CharSequence title;
|
||||
private final CharSequence summary;
|
||||
|
||||
private ActivityTitleSummaryMessage(int icon, int color, @NonNull CharSequence title, @Nullable CharSequence summary) {
|
||||
this.icon = icon;
|
||||
this.color = color;
|
||||
this.title = title;
|
||||
this.summary = summary;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ActivityTitleSummaryMessage get(Context context, UserColorNameManager manager, ParcelableActivity activity,
|
||||
ParcelableUser[] sources, int defaultColor,
|
||||
boolean shouldUseStarsForLikes,
|
||||
boolean nameFirst) {
|
||||
final Resources resources = context.getResources();
|
||||
switch (activity.action) {
|
||||
case Activity.Action.FOLLOW: {
|
||||
int typeIcon = R.drawable.ic_activity_action_follow;
|
||||
int color = ContextCompat.getColor(context, R.color.highlight_follow);
|
||||
CharSequence title;
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_follow,
|
||||
R.string.activity_about_me_follow_multi, sources, nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, null);
|
||||
}
|
||||
case Activity.Action.FAVORITE: {
|
||||
int typeIcon;
|
||||
int color;
|
||||
CharSequence title;
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite);
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorite,
|
||||
R.string.activity_about_me_favorite_multi, sources, nameFirst);
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like);
|
||||
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_like,
|
||||
R.string.activity_about_me_like_multi, sources, nameFirst);
|
||||
}
|
||||
final CharSequence summary = generateTextOnlySummary(context, activity.target_statuses);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.RETWEET: {
|
||||
int typeIcon = R.drawable.ic_activity_action_retweet;
|
||||
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
|
||||
CharSequence title;
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweet,
|
||||
R.string.activity_about_me_retweet_multi, sources, nameFirst);
|
||||
final CharSequence summary = generateTextOnlySummary(context,
|
||||
activity.target_object_statuses);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.FAVORITED_RETWEET: {
|
||||
int typeIcon;
|
||||
int color;
|
||||
CharSequence title;
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite);
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorited_retweet,
|
||||
R.string.activity_about_me_favorited_retweet_multi, sources, nameFirst);
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like);
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_liked_retweet,
|
||||
R.string.activity_about_me_liked_retweet_multi, sources, nameFirst);
|
||||
}
|
||||
final Spanned summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.RETWEETED_RETWEET: {
|
||||
int typeIcon = R.drawable.ic_activity_action_retweet;
|
||||
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
|
||||
CharSequence title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_retweet,
|
||||
R.string.activity_about_me_retweeted_retweet_multi, sources, nameFirst);
|
||||
final Spanned summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.RETWEETED_MENTION: {
|
||||
int typeIcon = R.drawable.ic_activity_action_retweet;
|
||||
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
|
||||
CharSequence title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_mention,
|
||||
R.string.activity_about_me_retweeted_mention_multi, sources, nameFirst);
|
||||
final Spanned summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.FAVORITED_MENTION: {
|
||||
int typeIcon;
|
||||
int color;
|
||||
CharSequence title;
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite);
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorited_mention,
|
||||
R.string.activity_about_me_favorited_mention_multi, sources, nameFirst);
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like);
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_liked_mention,
|
||||
R.string.activity_about_me_liked_mention_multi, sources, nameFirst);
|
||||
}
|
||||
final Spanned summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.LIST_MEMBER_ADDED: {
|
||||
CharSequence title;
|
||||
int icon = R.drawable.ic_activity_action_list_added;
|
||||
if ((sources.length == 1) && (activity.target_object_user_lists != null)
|
||||
&& (activity.target_object_user_lists.length == 1)) {
|
||||
final SpannableString firstDisplayName = new SpannableString(manager.getDisplayName(
|
||||
sources[0], nameFirst));
|
||||
final SpannableString listName = new SpannableString(activity.target_object_user_lists[0].name);
|
||||
firstDisplayName.setSpan(new StyleSpan(Typeface.BOLD), 0, firstDisplayName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
listName.setSpan(new StyleSpan(Typeface.BOLD), 0, listName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
final String format = context.getString(R.string.activity_about_me_list_member_added_with_name);
|
||||
final Configuration configuration = resources.getConfiguration();
|
||||
title = SpanFormatter.format(configuration.locale, format, firstDisplayName,
|
||||
listName);
|
||||
} else {
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_list_member_added,
|
||||
R.string.activity_about_me_list_member_added_multi, sources, nameFirst);
|
||||
}
|
||||
return new ActivityTitleSummaryMessage(icon, defaultColor, title, null);
|
||||
}
|
||||
case Activity.Action.MENTION:
|
||||
case Activity.Action.REPLY:
|
||||
case Activity.Action.QUOTE: {
|
||||
final ParcelableStatus status = ParcelableActivityExtensionsKt.getActivityStatus(activity);
|
||||
if (status == null) return null;
|
||||
final SpannableString title = new SpannableString(manager.getDisplayName(status,
|
||||
nameFirst));
|
||||
title.setSpan(new StyleSpan(Typeface.BOLD), 0, title.length(),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return new ActivityTitleSummaryMessage(0, 0, title, status.text_unescaped);
|
||||
}
|
||||
case Activity.Action.JOINED_TWITTER: {
|
||||
int typeIcon = R.drawable.ic_activity_action_follow;
|
||||
int color = ContextCompat.getColor(context, R.color.highlight_follow);
|
||||
CharSequence title = getTitleStringAboutMe(resources, manager,
|
||||
R.string.activity_joined_twitter, R.string.activity_joined_twitter_multi,
|
||||
sources, nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, null);
|
||||
}
|
||||
case Activity.Action.MEDIA_TAGGED: {
|
||||
int typeIcon = R.drawable.ic_activity_action_media_tagged;
|
||||
int color = ContextCompat.getColor(context, R.color.highlight_tagged);
|
||||
CharSequence title;
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_media_tagged,
|
||||
R.string.activity_about_me_media_tagged_multi, sources, nameFirst);
|
||||
final Spanned summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.FAVORITED_MEDIA_TAGGED: {
|
||||
int typeIcon;
|
||||
int color;
|
||||
CharSequence title;
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite);
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorited_media_tagged,
|
||||
R.string.activity_about_me_favorited_media_tagged_multi, sources, nameFirst);
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like;
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like);
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_liked_media_tagged,
|
||||
R.string.activity_about_me_liked_media_tagged_multi, sources, nameFirst);
|
||||
}
|
||||
final Spanned summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
case Activity.Action.RETWEETED_MEDIA_TAGGED: {
|
||||
int typeIcon = R.drawable.ic_activity_action_retweet;
|
||||
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
|
||||
CharSequence title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_media_tagged,
|
||||
R.string.activity_about_me_retweeted_media_tagged_multi, sources, nameFirst);
|
||||
final Spanned summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst);
|
||||
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Spanned generateStatusTextSummary(Context context, UserColorNameManager manager,
|
||||
ParcelableStatus[] statuses, boolean nameFirst) {
|
||||
if (statuses == null) return null;
|
||||
final SpannableStringBuilder summaryBuilder = new SpannableStringBuilder();
|
||||
boolean first = true;
|
||||
for (ParcelableStatus status : statuses) {
|
||||
if (!first) {
|
||||
summaryBuilder.append('\n');
|
||||
}
|
||||
final SpannableString displayName = new SpannableString(manager.getDisplayName(status.user_key,
|
||||
status.user_name, status.user_screen_name, nameFirst));
|
||||
displayName.setSpan(new StyleSpan(Typeface.BOLD), 0, displayName.length(),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
summaryBuilder.append(SpanFormatter.format(context.getString(R.string.title_summary_line_format),
|
||||
displayName, status.text_unescaped.replace('\n', ' ')));
|
||||
first = false;
|
||||
}
|
||||
return summaryBuilder;
|
||||
}
|
||||
|
||||
public static CharSequence generateTextOnlySummary(Context context, ParcelableStatus[] statuses) {
|
||||
if (statuses == null) return null;
|
||||
final StringBuilder summaryBuilder = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (ParcelableStatus status : statuses) {
|
||||
if (!first) {
|
||||
summaryBuilder.append('\n');
|
||||
}
|
||||
summaryBuilder.append(status.text_unescaped.replace('\n', ' '));
|
||||
first = false;
|
||||
}
|
||||
return summaryBuilder;
|
||||
}
|
||||
|
||||
private static Spanned getTitleStringAboutMe(Resources resources, UserColorNameManager manager,
|
||||
int stringRes, int stringResMulti,
|
||||
ParcelableUser[] sources, boolean nameFirst) {
|
||||
if (sources == null || sources.length == 0) return null;
|
||||
final Configuration configuration = resources.getConfiguration();
|
||||
final SpannableString firstDisplayName = new SpannableString(manager.getDisplayName(sources[0],
|
||||
nameFirst));
|
||||
firstDisplayName.setSpan(new StyleSpan(Typeface.BOLD), 0, firstDisplayName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
if (sources.length == 1) {
|
||||
final String format = resources.getString(stringRes);
|
||||
return SpanFormatter.format(configuration.locale, format, firstDisplayName);
|
||||
} else if (sources.length == 2) {
|
||||
final String format = resources.getString(stringResMulti);
|
||||
final SpannableString secondDisplayName = new SpannableString(manager.getDisplayName(sources[1],
|
||||
nameFirst));
|
||||
secondDisplayName.setSpan(new StyleSpan(Typeface.BOLD), 0, secondDisplayName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return SpanFormatter.format(configuration.locale, format, firstDisplayName,
|
||||
secondDisplayName);
|
||||
} else {
|
||||
final int othersCount = sources.length - 1;
|
||||
final String nOthers = resources.getQuantityString(R.plurals.N_others, othersCount, othersCount);
|
||||
final String format = resources.getString(stringResMulti);
|
||||
return SpanFormatter.format(configuration.locale, format, firstDisplayName, nOthers);
|
||||
}
|
||||
}
|
||||
|
||||
private static Spanned getTitleStringByFriends(Resources resources, UserColorNameManager manager,
|
||||
int stringRes, int stringResMulti,
|
||||
ParcelableUser[] sources, Object[] targets, boolean nameFirst) {
|
||||
if (sources == null || sources.length == 0) return null;
|
||||
final Configuration configuration = resources.getConfiguration();
|
||||
final SpannableString firstSourceName = new SpannableString(manager.getDisplayName(
|
||||
sources[0], nameFirst));
|
||||
firstSourceName.setSpan(new StyleSpan(Typeface.BOLD), 0, firstSourceName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
final String displayName;
|
||||
final Object target = targets[0];
|
||||
if (target instanceof ParcelableUser) {
|
||||
displayName = manager.getDisplayName((ParcelableUser) target, nameFirst);
|
||||
} else if (target instanceof ParcelableStatus) {
|
||||
displayName = manager.getDisplayName((ParcelableStatus) target, nameFirst);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
final SpannableString firstTargetName = new SpannableString(displayName);
|
||||
firstTargetName.setSpan(new StyleSpan(Typeface.BOLD), 0, firstTargetName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
if (sources.length == 1) {
|
||||
final String format = resources.getString(stringRes);
|
||||
return SpanFormatter.format(configuration.locale, format, firstSourceName, firstTargetName);
|
||||
} else if (sources.length == 2) {
|
||||
final String format = resources.getString(stringResMulti);
|
||||
final SpannableString secondSourceName = new SpannableString(manager.getDisplayName(sources[1],
|
||||
nameFirst));
|
||||
secondSourceName.setSpan(new StyleSpan(Typeface.BOLD), 0, secondSourceName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return SpanFormatter.format(configuration.locale, format, firstSourceName,
|
||||
secondSourceName, firstTargetName);
|
||||
} else {
|
||||
final int othersCount = sources.length - 1;
|
||||
final String nOthers = resources.getQuantityString(R.plurals.N_others, othersCount, othersCount);
|
||||
final String format = resources.getString(stringResMulti);
|
||||
return SpanFormatter.format(configuration.locale, format, firstSourceName, nOthers, firstTargetName);
|
||||
}
|
||||
}
|
||||
|
||||
public int getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public CharSequence getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CharSequence getSummary() {
|
||||
return summary;
|
||||
}
|
||||
}
|
@ -24,6 +24,10 @@ fun <T> Collection<T>.addAllTo(collection: MutableCollection<T>): Boolean {
|
||||
return collection.addAll(this)
|
||||
}
|
||||
|
||||
fun <T> Array<T>.addAllTo(collection: MutableCollection<T>): Boolean {
|
||||
return collection.addAll(this)
|
||||
}
|
||||
|
||||
fun <E> Collection<E>?.nullableContentEquals(other: Collection<E>?): Boolean {
|
||||
if (this == null) return other.isNullOrEmpty()
|
||||
return contentEquals(other!!)
|
||||
|
@ -79,12 +79,10 @@ import org.mariotaku.twidere.extension.loadProfileImage
|
||||
import org.mariotaku.twidere.extension.model.getAccountUser
|
||||
import org.mariotaku.twidere.extension.model.textLimit
|
||||
import org.mariotaku.twidere.extension.model.unique_id_non_null
|
||||
import org.mariotaku.twidere.fragment.BaseDialogFragment
|
||||
import org.mariotaku.twidere.fragment.EditAltTextDialogFragment
|
||||
import org.mariotaku.twidere.fragment.PermissionRequestDialog
|
||||
import org.mariotaku.twidere.fragment.*
|
||||
import org.mariotaku.twidere.fragment.PermissionRequestDialog.PermissionRequestCancelCallback
|
||||
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.analyzer.PurchaseFinished
|
||||
import org.mariotaku.twidere.model.draft.UpdateStatusActionExtras
|
||||
import org.mariotaku.twidere.model.schedule.ScheduleInfo
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
@ -328,27 +326,27 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||
}
|
||||
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when (requestCode) {
|
||||
REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> {
|
||||
if (resultCode == Activity.RESULT_OK && intent != null) {
|
||||
val src = MediaPickerActivity.getMediaUris(intent)
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val src = MediaPickerActivity.getMediaUris(data)
|
||||
TaskStarter.execute(AddMediaTask(this, src, false, false))
|
||||
}
|
||||
}
|
||||
REQUEST_EDIT_IMAGE -> {
|
||||
if (resultCode == Activity.RESULT_OK && intent != null) {
|
||||
if (intent.data != null) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
if (data.data != null) {
|
||||
setMenu()
|
||||
updateTextCount()
|
||||
}
|
||||
}
|
||||
}
|
||||
REQUEST_EXTENSION_COMPOSE -> {
|
||||
if (resultCode == Activity.RESULT_OK && intent != null) {
|
||||
val text = intent.getStringExtra(EXTRA_TEXT)
|
||||
val append = intent.getStringExtra(EXTRA_APPEND_TEXT)
|
||||
val imageUri = intent.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val text = data.getStringExtra(EXTRA_TEXT)
|
||||
val append = data.getStringExtra(EXTRA_APPEND_TEXT)
|
||||
val imageUri = data.getParcelableExtra<Uri>(EXTRA_IMAGE_URI)
|
||||
if (text != null) {
|
||||
editText.setText(text)
|
||||
} else if (append != null) {
|
||||
@ -360,9 +358,14 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||
updateTextCount()
|
||||
}
|
||||
}
|
||||
REQUEST_PURCHASE_EXTRA_FEATURES -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Analyzer.log(PurchaseFinished.create(data!!))
|
||||
}
|
||||
}
|
||||
REQUEST_SET_SCHEDULE -> {
|
||||
if (resultCode == Activity.RESULT_OK && intent != null) {
|
||||
scheduleInfo = intent.getParcelableExtra(EXTRA_SCHEDULE_INFO)
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
scheduleInfo = data?.getParcelableExtra(EXTRA_SCHEDULE_INFO)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -545,7 +548,13 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||
}
|
||||
R.id.schedule -> {
|
||||
val controller = statusScheduleController ?: return true
|
||||
startActivityForResult(controller.createSetScheduleIntent(), REQUEST_SET_SCHEDULE)
|
||||
if (extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_SCHEDULE_STATUS)) {
|
||||
startActivityForResult(controller.createSetScheduleIntent(), REQUEST_SET_SCHEDULE)
|
||||
} else {
|
||||
ExtraFeaturesIntroductionDialogFragment.show(supportFragmentManager,
|
||||
feature = ExtraFeaturesService.FEATURE_SCHEDULE_STATUS,
|
||||
requestCode = REQUEST_PURCHASE_EXTRA_FEATURES)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val intent = item.intent
|
||||
|
@ -1,9 +1,66 @@
|
||||
package org.mariotaku.twidere.extension.model
|
||||
|
||||
import org.mariotaku.ktextension.addAllTo
|
||||
import org.mariotaku.ktextension.isNullOrEmpty
|
||||
import org.mariotaku.twidere.model.ParcelableActivity
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2016/12/6.
|
||||
*/
|
||||
val ParcelableActivity.id: String
|
||||
get() = "$min_position-$max_position"
|
||||
get() = "$min_position-$max_position"
|
||||
|
||||
val ParcelableActivity.reachedCountLimit: Boolean get() {
|
||||
fun Array<*>?.reachedCountLimit() = if (this == null) false else size > 10
|
||||
|
||||
return sources.reachedCountLimit() || target_statuses.reachedCountLimit() ||
|
||||
target_users.reachedCountLimit() || target_user_lists.reachedCountLimit() ||
|
||||
target_object_statuses.reachedCountLimit() || target_object_users.reachedCountLimit() ||
|
||||
target_object_user_lists.reachedCountLimit()
|
||||
}
|
||||
|
||||
fun ParcelableActivity.isSameSources(another: ParcelableActivity): Boolean {
|
||||
return Arrays.equals(sources, another.sources)
|
||||
}
|
||||
|
||||
fun ParcelableActivity.isSameTarget(another: ParcelableActivity): Boolean {
|
||||
if (target_statuses.isNullOrEmpty() && target_users.isNullOrEmpty() && target_user_lists
|
||||
.isNullOrEmpty()) {
|
||||
return false
|
||||
}
|
||||
return Arrays.equals(target_users, another.target_users) && Arrays.equals(target_statuses,
|
||||
another.target_statuses) && Arrays.equals(target_user_lists, another.target_user_lists)
|
||||
}
|
||||
|
||||
fun ParcelableActivity.isSameTargetObject(another: ParcelableActivity): Boolean {
|
||||
if (target_object_statuses.isNullOrEmpty() && target_object_users.isNullOrEmpty()
|
||||
&& target_object_user_lists.isNullOrEmpty()) {
|
||||
return false
|
||||
}
|
||||
return Arrays.equals(target_object_users, another.target_object_users)
|
||||
&& Arrays.equals(target_object_statuses, another.target_object_statuses)
|
||||
&& Arrays.equals(target_object_user_lists, another.target_object_user_lists)
|
||||
}
|
||||
|
||||
fun ParcelableActivity.prependSources(another: ParcelableActivity) {
|
||||
sources = uniqCombine(another.sources, sources)
|
||||
}
|
||||
|
||||
fun ParcelableActivity.prependTargets(another: ParcelableActivity) {
|
||||
target_statuses = uniqCombine(another.target_statuses, target_statuses)
|
||||
target_users = uniqCombine(another.target_users, target_users)
|
||||
target_user_lists = uniqCombine(another.target_user_lists, target_user_lists)
|
||||
}
|
||||
|
||||
fun ParcelableActivity.prependTargetObjects(another: ParcelableActivity) {
|
||||
target_object_statuses = uniqCombine(another.target_object_statuses, target_object_statuses)
|
||||
target_object_users = uniqCombine(another.target_object_users, target_object_users)
|
||||
target_object_user_lists = uniqCombine(another.target_object_user_lists, target_object_user_lists)
|
||||
}
|
||||
|
||||
private inline fun <reified T> uniqCombine(vararg arrays: Array<T>?): Array<T> {
|
||||
val set = mutableSetOf<T>()
|
||||
arrays.forEach { array -> array?.addAllTo(set) }
|
||||
return set.toTypedArray()
|
||||
}
|
@ -41,6 +41,7 @@ import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.ktextension.coerceInOr
|
||||
import org.mariotaku.ktextension.isNullOrEmpty
|
||||
import org.mariotaku.ktextension.rangeOfSize
|
||||
import org.mariotaku.microblog.library.twitter.model.Activity
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter
|
||||
@ -58,6 +59,7 @@ import org.mariotaku.twidere.constant.newDocumentApiKey
|
||||
import org.mariotaku.twidere.constant.readFromBottomKey
|
||||
import org.mariotaku.twidere.constant.rememberPositionKey
|
||||
import org.mariotaku.twidere.extension.model.getAccountType
|
||||
import org.mariotaku.twidere.extension.model.id
|
||||
import org.mariotaku.twidere.fragment.AbsStatusesFragment.DefaultOnLikedListener
|
||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
||||
import org.mariotaku.twidere.model.*
|
||||
@ -310,6 +312,14 @@ abstract class AbsActivitiesFragment protected constructor() :
|
||||
override fun onGapClick(holder: GapViewHolder, position: Int) {
|
||||
val activity = adapter.getActivity(position)
|
||||
DebugLog.v(msg = "Load activity gap $activity")
|
||||
if (!Utils.isOfficialCredentials(context, activity.account_key)) {
|
||||
// Skip if item is not a status
|
||||
if (activity.action !in Activity.Action.MENTION_ACTIONS) {
|
||||
adapter.removeGapLoadingId(ObjectId(activity.account_key, activity.id))
|
||||
adapter.notifyItemChanged(position)
|
||||
return
|
||||
}
|
||||
}
|
||||
val accountIds = arrayOf(activity.account_key)
|
||||
val maxIds = arrayOf(activity.min_position)
|
||||
val maxSortIds = longArrayOf(activity.min_sort_position)
|
||||
|
@ -144,18 +144,23 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
||||
if (ILoadMoreSupportAdapter.START in position || refreshing) return
|
||||
super.onLoadMoreContents(position)
|
||||
if (position == 0L) return
|
||||
val contentUri = this.contentUri
|
||||
getActivities(object : SimpleRefreshTaskParam() {
|
||||
override val accountKeys: Array<UserKey> by lazy {
|
||||
this@CursorActivitiesFragment.accountKeys
|
||||
}
|
||||
|
||||
override val maxIds: Array<String?>?
|
||||
get() = getOldestActivityIds(accountKeys)
|
||||
get() {
|
||||
val context = context ?: return null
|
||||
return DataStoreUtils.getRefreshOldestActivityMaxPositions(context, contentUri,
|
||||
accountKeys.toNulls())
|
||||
}
|
||||
|
||||
override val maxSortIds: LongArray?
|
||||
get() {
|
||||
val context = context ?: return null
|
||||
return DataStoreUtils.getOldestActivityMaxSortPositions(context,
|
||||
return DataStoreUtils.getRefreshOldestActivityMaxSortPositions(context,
|
||||
contentUri, accountKeys.toNulls())
|
||||
}
|
||||
|
||||
@ -167,20 +172,28 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun triggerRefresh(): Boolean {
|
||||
super.triggerRefresh()
|
||||
val contentUri = this.contentUri
|
||||
getActivities(object : SimpleRefreshTaskParam() {
|
||||
override val accountKeys: Array<UserKey> by lazy {
|
||||
this@CursorActivitiesFragment.accountKeys
|
||||
}
|
||||
|
||||
override val sinceIds: Array<String?>?
|
||||
get() = DataStoreUtils.getNewestActivityMaxPositions(context, contentUri,
|
||||
accountKeys.toNulls())
|
||||
get() {
|
||||
val context = context ?: return null
|
||||
return DataStoreUtils.getRefreshNewestActivityMaxPositions(context, contentUri,
|
||||
accountKeys.toNulls())
|
||||
}
|
||||
|
||||
override val sinceSortIds: LongArray?
|
||||
get() = DataStoreUtils.getNewestActivityMaxSortPositions(context, contentUri,
|
||||
accountKeys.toNulls())
|
||||
get() {
|
||||
val context = context ?: return null
|
||||
return DataStoreUtils.getRefreshNewestActivityMaxSortPositions(context,
|
||||
contentUri, accountKeys.toNulls())
|
||||
}
|
||||
|
||||
override val hasSinceIds: Boolean
|
||||
get() = true
|
||||
@ -209,11 +222,6 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
protected fun getOldestActivityIds(accountKeys: Array<UserKey>): Array<String?>? {
|
||||
val context = context ?: return null
|
||||
return DataStoreUtils.getOldestActivityMaxPositions(context, contentUri, accountKeys.toNulls())
|
||||
}
|
||||
|
||||
protected abstract val isFilterEnabled: Boolean
|
||||
|
||||
protected open fun processWhere(where: Expression, whereArgs: Array<String>): ParameterizedExpression {
|
||||
@ -345,4 +353,8 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
||||
class ActivityCursor(cursor: Cursor, indies: ObjectCursor.CursorIndices<ParcelableActivity>,
|
||||
val filteredUserIds: Array<UserKey>) : ObjectCursor<ParcelableActivity>(cursor, indies)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,252 @@
|
||||
package org.mariotaku.twidere.model
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Typeface
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.text.SpannableString
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.style.StyleSpan
|
||||
import org.mariotaku.microblog.library.twitter.model.Activity
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.model.util.getActivityStatus
|
||||
import org.mariotaku.twidere.text.style.NonBreakEllipseSpan
|
||||
import org.mariotaku.twidere.util.UserColorNameManager
|
||||
import org.oshkimaadziig.george.androidutils.SpanFormatter
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/1.
|
||||
*/
|
||||
class ActivityTitleSummaryMessage private constructor(val icon: Int, val color: Int, val title: CharSequence, val summary: CharSequence?) {
|
||||
companion object {
|
||||
|
||||
fun get(context: Context, manager: UserColorNameManager, activity: ParcelableActivity,
|
||||
sources: Array<ParcelableUser>, defaultColor: Int, shouldUseStarsForLikes: Boolean,
|
||||
nameFirst: Boolean): ActivityTitleSummaryMessage? {
|
||||
val resources = context.resources
|
||||
when (activity.action) {
|
||||
Activity.Action.FOLLOW -> {
|
||||
val typeIcon = R.drawable.ic_activity_action_follow
|
||||
val color = ContextCompat.getColor(context, R.color.highlight_follow)
|
||||
val title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_follow,
|
||||
R.string.activity_about_me_follow_multi, sources, nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, null)
|
||||
}
|
||||
Activity.Action.FAVORITE -> {
|
||||
val typeIcon: Int
|
||||
val color: Int
|
||||
val title: CharSequence
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite)
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorite,
|
||||
R.string.activity_about_me_favorite_multi, sources, nameFirst)
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like)
|
||||
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_like,
|
||||
R.string.activity_about_me_like_multi, sources, nameFirst)
|
||||
}
|
||||
val summary = generateTextOnlySummary(activity.target_statuses)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.RETWEET -> {
|
||||
val typeIcon = R.drawable.ic_activity_action_retweet
|
||||
val color = ContextCompat.getColor(context, R.color.highlight_retweet)
|
||||
val title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweet,
|
||||
R.string.activity_about_me_retweet_multi, sources, nameFirst)
|
||||
val summary = generateTextOnlySummary(activity.target_object_statuses)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.FAVORITED_RETWEET -> {
|
||||
val typeIcon: Int
|
||||
val color: Int
|
||||
val title: CharSequence
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite)
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorited_retweet,
|
||||
R.string.activity_about_me_favorited_retweet_multi, sources, nameFirst)
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like)
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_liked_retweet,
|
||||
R.string.activity_about_me_liked_retweet_multi, sources, nameFirst)
|
||||
}
|
||||
val summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.RETWEETED_RETWEET -> {
|
||||
val typeIcon = R.drawable.ic_activity_action_retweet
|
||||
val color = ContextCompat.getColor(context, R.color.highlight_retweet)
|
||||
val title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_retweet,
|
||||
R.string.activity_about_me_retweeted_retweet_multi, sources, nameFirst)
|
||||
val summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.RETWEETED_MENTION -> {
|
||||
val typeIcon = R.drawable.ic_activity_action_retweet
|
||||
val color = ContextCompat.getColor(context, R.color.highlight_retweet)
|
||||
val title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_mention,
|
||||
R.string.activity_about_me_retweeted_mention_multi, sources, nameFirst)
|
||||
val summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.FAVORITED_MENTION -> {
|
||||
val typeIcon: Int
|
||||
val color: Int
|
||||
val title: CharSequence
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite)
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorited_mention,
|
||||
R.string.activity_about_me_favorited_mention_multi, sources, nameFirst)
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like)
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_liked_mention,
|
||||
R.string.activity_about_me_liked_mention_multi, sources, nameFirst)
|
||||
}
|
||||
val summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.LIST_MEMBER_ADDED -> {
|
||||
val title: CharSequence
|
||||
val icon = R.drawable.ic_activity_action_list_added
|
||||
if (sources.size == 1 && activity.target_object_user_lists != null
|
||||
&& activity.target_object_user_lists.size == 1) {
|
||||
val firstDisplayName = SpannableString(manager.getDisplayName(
|
||||
sources[0], nameFirst))
|
||||
val listName = SpannableString(activity.target_object_user_lists[0].name)
|
||||
firstDisplayName.setSpan(StyleSpan(Typeface.BOLD), 0, firstDisplayName.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
listName.setSpan(StyleSpan(Typeface.BOLD), 0, listName.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
val format = context.getString(R.string.activity_about_me_list_member_added_with_name)
|
||||
title = SpanFormatter.format(format, firstDisplayName, listName)
|
||||
} else {
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_list_member_added,
|
||||
R.string.activity_about_me_list_member_added_multi, sources, nameFirst)
|
||||
}
|
||||
return ActivityTitleSummaryMessage(icon, defaultColor, title, null)
|
||||
}
|
||||
Activity.Action.MENTION, Activity.Action.REPLY, Activity.Action.QUOTE -> {
|
||||
val status = activity.getActivityStatus() ?: return null
|
||||
val title = SpannableString(manager.getDisplayName(status,
|
||||
nameFirst))
|
||||
title.setSpan(StyleSpan(Typeface.BOLD), 0, title.length,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return ActivityTitleSummaryMessage(0, 0, title, status.text_unescaped)
|
||||
}
|
||||
Activity.Action.JOINED_TWITTER -> {
|
||||
val typeIcon = R.drawable.ic_activity_action_follow
|
||||
val color = ContextCompat.getColor(context, R.color.highlight_follow)
|
||||
val title = getTitleStringAboutMe(resources, manager,
|
||||
R.string.activity_joined_twitter, R.string.activity_joined_twitter_multi,
|
||||
sources, nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, null)
|
||||
}
|
||||
Activity.Action.MEDIA_TAGGED -> {
|
||||
val typeIcon = R.drawable.ic_activity_action_media_tagged
|
||||
val color = ContextCompat.getColor(context, R.color.highlight_tagged)
|
||||
val title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_media_tagged,
|
||||
R.string.activity_about_me_media_tagged_multi, sources, nameFirst)
|
||||
val summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.FAVORITED_MEDIA_TAGGED -> {
|
||||
val typeIcon: Int
|
||||
val color: Int
|
||||
val title: CharSequence
|
||||
if (shouldUseStarsForLikes) {
|
||||
typeIcon = R.drawable.ic_activity_action_favorite
|
||||
color = ContextCompat.getColor(context, R.color.highlight_favorite)
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorited_media_tagged,
|
||||
R.string.activity_about_me_favorited_media_tagged_multi, sources, nameFirst)
|
||||
} else {
|
||||
typeIcon = R.drawable.ic_activity_action_like
|
||||
color = ContextCompat.getColor(context, R.color.highlight_like)
|
||||
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_liked_media_tagged,
|
||||
R.string.activity_about_me_liked_media_tagged_multi, sources, nameFirst)
|
||||
}
|
||||
val summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
Activity.Action.RETWEETED_MEDIA_TAGGED -> {
|
||||
val typeIcon = R.drawable.ic_activity_action_retweet
|
||||
val color = ContextCompat.getColor(context, R.color.highlight_retweet)
|
||||
val title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_media_tagged,
|
||||
R.string.activity_about_me_retweeted_media_tagged_multi, sources, nameFirst)
|
||||
val summary = generateStatusTextSummary(context, manager, activity.target_statuses,
|
||||
nameFirst)
|
||||
return ActivityTitleSummaryMessage(typeIcon, color, title, summary)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun generateStatusTextSummary(context: Context, manager: UserColorNameManager,
|
||||
statuses: Array<ParcelableStatus>?, nameFirst: Boolean): Spanned? {
|
||||
return statuses?.joinTo(SpannableStringBuilder(), separator = "\n") { status ->
|
||||
val displayName = SpannableString(manager.getDisplayName(status.user_key,
|
||||
status.user_name, status.user_screen_name, nameFirst)).also {
|
||||
it.setSpan(StyleSpan(Typeface.BOLD), 0, it.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
|
||||
val statusText = if (statuses.size > 1) {
|
||||
SpannableString(status.text_unescaped.replace('\n', ' ')).also {
|
||||
it.setSpan(NonBreakEllipseSpan(), 0, it.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
} else {
|
||||
status.text_unescaped
|
||||
}
|
||||
return@joinTo SpanFormatter.format(context.getString(R.string.title_summary_line_format),
|
||||
displayName, statusText)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTextOnlySummary(statuses: Array<ParcelableStatus>?): CharSequence? {
|
||||
return statuses?.joinTo(SpannableStringBuilder(), separator = "\n") { status ->
|
||||
if (statuses.size > 1) {
|
||||
return@joinTo SpannableString(status.text_unescaped.replace('\n', ' ')).also {
|
||||
it.setSpan(NonBreakEllipseSpan(), 0, it.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
} else {
|
||||
return@joinTo status.text_unescaped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTitleStringAboutMe(resources: Resources, manager: UserColorNameManager,
|
||||
stringRes: Int, stringResMulti: Int, sources: Array<ParcelableUser>,
|
||||
nameFirst: Boolean): CharSequence {
|
||||
val firstDisplayName = SpannableString(manager.getDisplayName(sources[0],
|
||||
nameFirst))
|
||||
firstDisplayName.setSpan(StyleSpan(Typeface.BOLD), 0, firstDisplayName.length,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
if (sources.size == 1) {
|
||||
val format = resources.getString(stringRes)
|
||||
return SpanFormatter.format(format, firstDisplayName)
|
||||
} else if (sources.size == 2) {
|
||||
val format = resources.getString(stringResMulti)
|
||||
val secondDisplayName = SpannableString(manager.getDisplayName(sources[1],
|
||||
nameFirst))
|
||||
secondDisplayName.setSpan(StyleSpan(Typeface.BOLD), 0, secondDisplayName.length,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return SpanFormatter.format(format, firstDisplayName,
|
||||
secondDisplayName)
|
||||
} else {
|
||||
val othersCount = sources.size - 1
|
||||
val nOthers = resources.getQuantityString(R.plurals.N_others, othersCount, othersCount)
|
||||
val format = resources.getString(stringResMulti)
|
||||
return SpanFormatter.format(format, firstDisplayName, nOthers)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ import org.mariotaku.abstask.library.TaskStarter
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
|
||||
import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe
|
||||
import org.mariotaku.ktextension.toLong
|
||||
import org.mariotaku.library.objectcursor.ObjectCursor
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.twitter.TwitterUserStream
|
||||
@ -29,9 +30,7 @@ import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.constant.streamingEnabledKey
|
||||
import org.mariotaku.twidere.constant.streamingNonMeteredNetworkKey
|
||||
import org.mariotaku.twidere.constant.streamingPowerSavingKey
|
||||
import org.mariotaku.twidere.extension.model.isOfficial
|
||||
import org.mariotaku.twidere.extension.model.isStreamingSupported
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
import org.mariotaku.twidere.extension.model.*
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
|
||||
@ -257,6 +256,8 @@ class StreamingService : BaseService() {
|
||||
private var homeInsertGap = false
|
||||
private var interactionsInsertGap = false
|
||||
|
||||
private var lastActivityAboutMe: ParcelableActivity? = null
|
||||
|
||||
override fun onConnected(): Boolean {
|
||||
homeInsertGap = true
|
||||
interactionsInsertGap = true
|
||||
@ -303,13 +304,61 @@ class StreamingService : BaseService() {
|
||||
handler.postDelayed(interactionsTimeoutRunnable, TimeUnit.SECONDS.toMillis(30))
|
||||
}
|
||||
} else {
|
||||
val parcelableActivity = ParcelableActivityUtils.fromActivity(activity,
|
||||
account.key, interactionsInsertGap, profileImageSize)
|
||||
parcelableActivity.position_key = parcelableActivity.timestamp
|
||||
val insertGap: Boolean
|
||||
if (activity.action in Activity.Action.MENTION_ACTIONS) {
|
||||
insertGap = interactionsInsertGap
|
||||
interactionsInsertGap = false
|
||||
} else {
|
||||
insertGap = false
|
||||
}
|
||||
val curActivity = ParcelableActivityUtils.fromActivity(activity, account.key,
|
||||
insertGap, profileImageSize)
|
||||
curActivity.position_key = curActivity.timestamp
|
||||
var updateId = -1L
|
||||
if (curActivity.action !in Activity.Action.MENTION_ACTIONS) {
|
||||
/* Merge two activities if:
|
||||
* * Not mention/reply/quote
|
||||
* * Same action
|
||||
* * Same source or target or target object
|
||||
*/
|
||||
val lastActivity = this.lastActivityAboutMe
|
||||
if (lastActivity != null && curActivity.action == lastActivity.action) {
|
||||
if (curActivity.reachedCountLimit) {
|
||||
// Skip if more than 10 sources/targets/target_objects
|
||||
} else if (curActivity.isSameSources(lastActivity)) {
|
||||
curActivity.prependTargets(lastActivity)
|
||||
curActivity.prependTargetObjects(lastActivity)
|
||||
updateId = lastActivity._id
|
||||
} else if (curActivity.isSameTarget(lastActivity)) {
|
||||
curActivity.prependSources(lastActivity)
|
||||
curActivity.prependTargets(lastActivity)
|
||||
updateId = lastActivity._id
|
||||
} else if (curActivity.isSameTargetObject(lastActivity)) {
|
||||
curActivity.prependSources(lastActivity)
|
||||
curActivity.prependTargets(lastActivity)
|
||||
updateId = lastActivity._id
|
||||
}
|
||||
if (updateId > 0) {
|
||||
curActivity.min_position = lastActivity.min_position
|
||||
curActivity.min_sort_position = lastActivity.min_sort_position
|
||||
}
|
||||
}
|
||||
}
|
||||
val values = ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java)
|
||||
.create(parcelableActivity)
|
||||
context.contentResolver.insert(Activities.AboutMe.CONTENT_URI, values)
|
||||
interactionsInsertGap = false
|
||||
.create(curActivity)
|
||||
val resolver = context.contentResolver
|
||||
if (updateId > 0) {
|
||||
val where = Expression.equalsArgs(Activities._ID).sql
|
||||
val whereArgs = arrayOf(updateId.toString())
|
||||
resolver.update(Activities.AboutMe.CONTENT_URI, values, where, whereArgs)
|
||||
curActivity._id = updateId
|
||||
} else {
|
||||
val uri = resolver.insert(Activities.AboutMe.CONTENT_URI, values)
|
||||
if (uri != null) {
|
||||
curActivity._id = uri.lastPathSegment.toLong(-1)
|
||||
}
|
||||
}
|
||||
lastActivityAboutMe = curActivity
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -374,11 +423,11 @@ class StreamingService : BaseService() {
|
||||
|
||||
override val sinceIds: Array<String?>?
|
||||
get() = DataStoreUtils.getNewestActivityMaxPositions(context,
|
||||
Activities.AboutMe.CONTENT_URI, arrayOf(account.key))
|
||||
Activities.AboutMe.CONTENT_URI, arrayOf(account.key), null, null)
|
||||
|
||||
override val sinceSortIds: LongArray?
|
||||
get() = DataStoreUtils.getNewestActivityMaxSortPositions(context,
|
||||
Activities.AboutMe.CONTENT_URI, arrayOf(account.key))
|
||||
Activities.AboutMe.CONTENT_URI, arrayOf(account.key), null, null)
|
||||
|
||||
override val hasSinceIds: Boolean = true
|
||||
|
||||
|
@ -36,6 +36,7 @@ import org.mariotaku.twidere.model.AccountDetails
|
||||
import org.mariotaku.twidere.model.ParcelableMessage
|
||||
import org.mariotaku.twidere.model.ParcelableMessageConversation
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.event.UnreadCountUpdatedEvent
|
||||
import org.mariotaku.twidere.model.message.conversation.TwitterOfficialConversationExtras
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Messages
|
||||
@ -77,6 +78,10 @@ class MarkMessageReadTask(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSucceed(callback: Unit?, result: Boolean) {
|
||||
bus.post(UnreadCountUpdatedEvent(-1))
|
||||
}
|
||||
|
||||
private fun performMarkRead(microBlog: MicroBlog, account: AccountDetails,
|
||||
conversation: ParcelableMessageConversation): Pair<String, Long>? {
|
||||
when (account.type) {
|
||||
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.text.style
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.text.TextPaint
|
||||
import android.text.TextUtils
|
||||
import android.text.style.ReplacementSpan
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/3/26.
|
||||
*/
|
||||
|
||||
class NonBreakEllipseSpan : ReplacementSpan() {
|
||||
override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int,
|
||||
y: Int, bottom: Int, paint: Paint) {
|
||||
if (paint !is TextPaint) return
|
||||
val ellipsized = TextUtils.ellipsize(text.substring(start, end), paint, canvas.width - x,
|
||||
TextUtils.TruncateAt.END)
|
||||
canvas.drawText(ellipsized, 0, ellipsized.length, x, y.toFloat(), paint)
|
||||
}
|
||||
|
||||
}
|
@ -283,7 +283,7 @@ class AsyncTwitterWrapper(
|
||||
override val accountKeys: Array<UserKey> by lazy { action() }
|
||||
|
||||
override val sinceIds: Array<String?>? by lazy {
|
||||
DataStoreUtils.getNewestActivityMaxPositions(context,
|
||||
DataStoreUtils.getRefreshNewestActivityMaxPositions(context,
|
||||
Activities.AboutMe.CONTENT_URI, accountKeys.toNulls())
|
||||
}
|
||||
})
|
||||
|
@ -189,28 +189,76 @@ object DataStoreUtils {
|
||||
OrderBy(SQLFunctions.MIN(Statuses.STATUS_TIMESTAMP)), null, null)
|
||||
}
|
||||
|
||||
fun getNewestActivityMaxPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>): Array<String?> {
|
||||
fun getNewestActivityMaxPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>,
|
||||
extraWhere: Expression?, extraWhereArgs: Array<String>?): Array<String?> {
|
||||
return getStringFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
|
||||
Activities.MAX_REQUEST_POSITION, OrderBy(SQLFunctions.MAX(Activities.TIMESTAMP)),
|
||||
null, null)
|
||||
extraWhere, extraWhereArgs)
|
||||
}
|
||||
|
||||
fun getOldestActivityMaxPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>): Array<String?> {
|
||||
fun getRefreshNewestActivityMaxPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>):
|
||||
Array<String?> {
|
||||
return getOfficialSeparatedIds(context, { accountKeys, isOfficial ->
|
||||
val (where, whereArgs) = getIdsWhere(isOfficial)
|
||||
DataStoreUtils.getNewestActivityMaxPositions(context, uri, accountKeys,
|
||||
where, whereArgs)
|
||||
}, { arr1, arr2 ->
|
||||
Array(accountKeys.size) { arr1[it] ?: arr2[it] }
|
||||
}, accountKeys)
|
||||
}
|
||||
|
||||
fun getOldestActivityMaxPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>,
|
||||
extraWhere: Expression?, extraWhereArgs: Array<String>?): Array<String?> {
|
||||
return getStringFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
|
||||
Activities.MAX_REQUEST_POSITION, OrderBy(SQLFunctions.MIN(Activities.TIMESTAMP)),
|
||||
null, null)
|
||||
extraWhere, extraWhereArgs)
|
||||
}
|
||||
|
||||
fun getNewestActivityMaxSortPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>): LongArray {
|
||||
fun getRefreshOldestActivityMaxPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>):
|
||||
Array<String?> {
|
||||
return getOfficialSeparatedIds(context, { accountKeys, isOfficial ->
|
||||
val (where, whereArgs) = getIdsWhere(isOfficial)
|
||||
DataStoreUtils.getOldestActivityMaxPositions(context, uri, accountKeys,
|
||||
where, whereArgs)
|
||||
}, { arr1, arr2 ->
|
||||
Array(accountKeys.size) { arr1[it] ?: arr2[it] }
|
||||
}, accountKeys)
|
||||
}
|
||||
|
||||
fun getNewestActivityMaxSortPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>,
|
||||
extraWhere: Expression?, extraWhereArgs: Array<String>?): LongArray {
|
||||
return getLongFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
|
||||
Activities.MAX_SORT_POSITION, OrderBy(SQLFunctions.MAX(Activities.TIMESTAMP)),
|
||||
null, null)
|
||||
extraWhere, extraWhereArgs)
|
||||
}
|
||||
|
||||
fun getOldestActivityMaxSortPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>): LongArray {
|
||||
fun getRefreshNewestActivityMaxSortPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>):
|
||||
LongArray {
|
||||
return getOfficialSeparatedIds(context, { accountKeys, isOfficial ->
|
||||
val (where, whereArgs) = getIdsWhere(isOfficial)
|
||||
DataStoreUtils.getNewestActivityMaxSortPositions(context, uri, accountKeys,
|
||||
where, whereArgs)
|
||||
}, { arr1, arr2 ->
|
||||
LongArray(accountKeys.size) { arr1[it].takeIf { it > 0 } ?: arr2[it] }
|
||||
}, accountKeys)
|
||||
}
|
||||
|
||||
fun getOldestActivityMaxSortPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>,
|
||||
extraWhere: Expression?, extraWhereArgs: Array<String>?): LongArray {
|
||||
return getLongFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
|
||||
Activities.MAX_SORT_POSITION, OrderBy(SQLFunctions.MIN(Activities.TIMESTAMP)),
|
||||
null, null)
|
||||
extraWhere, extraWhereArgs)
|
||||
}
|
||||
|
||||
fun getRefreshOldestActivityMaxSortPositions(context: Context, uri: Uri, accountKeys: Array<UserKey?>):
|
||||
LongArray {
|
||||
return getOfficialSeparatedIds(context, { accountKeys, isOfficial ->
|
||||
val (where, whereArgs) = getIdsWhere(isOfficial)
|
||||
DataStoreUtils.getOldestActivityMaxSortPositions(context, uri, accountKeys,
|
||||
where, whereArgs)
|
||||
}, { arr1, arr2 ->
|
||||
LongArray(accountKeys.size) { arr1[it].takeIf { it > 0 } ?: arr2[it] }
|
||||
}, accountKeys)
|
||||
}
|
||||
|
||||
fun getStatusCount(context: Context, uri: Uri, accountId: UserKey): Int {
|
||||
@ -911,4 +959,31 @@ object DataStoreUtils {
|
||||
}
|
||||
|
||||
|
||||
private fun getIdsWhere(official: Boolean): Pair<Expression?, Array<String>?> {
|
||||
if (official) return Pair(null, null)
|
||||
return Pair(Expression.inArgs(Activities.ACTION, Activity.Action.MENTION_ACTIONS.size)
|
||||
, Activity.Action.MENTION_ACTIONS)
|
||||
}
|
||||
|
||||
private fun <T> getOfficialSeparatedIds(context: Context, getFromDatabase: (Array<UserKey?>, Boolean) -> T,
|
||||
mergeResult: (T, T) -> T, accountKeys: Array<UserKey?>): T {
|
||||
val officialKeys = Array(accountKeys.size) {
|
||||
val key = accountKeys[it]
|
||||
if (Utils.isOfficialCredentials(context, key)) {
|
||||
return@Array key
|
||||
}
|
||||
return@Array null
|
||||
}
|
||||
val notOfficialKeys = Array(accountKeys.size) {
|
||||
val key = accountKeys[it]
|
||||
if (Utils.isOfficialCredentials(context, key)) {
|
||||
return@Array null
|
||||
}
|
||||
return@Array key
|
||||
}
|
||||
|
||||
val officialMaxPositions = getFromDatabase(officialKeys, true)
|
||||
val notOfficialMaxPositions = getFromDatabase(notOfficialKeys, false)
|
||||
return mergeResult(officialMaxPositions, notOfficialMaxPositions)
|
||||
}
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ class TaskServiceRunner(
|
||||
ACTION_REFRESH_NOTIFICATIONS -> {
|
||||
val task = GetActivitiesAboutMeTask(context)
|
||||
task.params = AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
|
||||
DataStoreUtils.getNewestActivityMaxPositions(context, Activities.AboutMe.CONTENT_URI,
|
||||
accountKeys.toNulls())
|
||||
DataStoreUtils.getRefreshNewestActivityMaxPositions(context,
|
||||
Activities.AboutMe.CONTENT_URI, accountKeys.toNulls())
|
||||
}
|
||||
return task
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user