code cleanup
This commit is contained in:
parent
ea39c48d55
commit
b842520d53
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<bool name="is_debug">true</bool>
|
||||||
|
</resources>
|
|
@ -1,5 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<integer name="min_database_item_limit">10</integer>
|
<integer name="min_database_item_limit">10</integer>
|
||||||
<bool name="is_debug">true</bool>
|
|
||||||
</resources>
|
</resources>
|
|
@ -461,7 +461,14 @@
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.RefreshService"
|
android:name=".service.RefreshService"
|
||||||
|
android:enabled="@bool/use_legacy_refresh_service"
|
||||||
android:label="@string/label_refresh_service"/>
|
android:label="@string/label_refresh_service"/>
|
||||||
|
<service
|
||||||
|
android:name=".service.JobRefreshService"
|
||||||
|
android:enabled="@bool/use_job_refresh_service"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/label_refresh_service"
|
||||||
|
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||||
<service
|
<service
|
||||||
android:name=".service.StreamingService"
|
android:name=".service.StreamingService"
|
||||||
android:label="@string/label_streaming_service"/>
|
android:label="@string/label_streaming_service"/>
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Twidere - Twitter client for Android
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012-2014 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.service;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.job.JobParameters;
|
|
||||||
import android.app.job.JobService;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 14/12/12.
|
|
||||||
*/
|
|
||||||
@SuppressLint("Registered")
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public class BackgroundJobService extends JobService {
|
|
||||||
@Override
|
|
||||||
public boolean onStartJob(JobParameters params) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onStopJob(JobParameters params) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,411 +0,0 @@
|
||||||
/*
|
|
||||||
* Twidere - Twitter client for Android
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012-2014 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.service;
|
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
|
||||||
import org.mariotaku.twidere.BuildConfig;
|
|
||||||
import org.mariotaku.twidere.Constants;
|
|
||||||
import org.mariotaku.twidere.model.AccountPreferences;
|
|
||||||
import org.mariotaku.twidere.model.SimpleRefreshTaskParam;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
|
||||||
import org.mariotaku.twidere.receiver.PowerStateReceiver;
|
|
||||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
|
||||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
|
||||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
|
||||||
import org.mariotaku.twidere.util.Utils;
|
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import edu.tsinghua.hotmobi.model.BatteryRecord;
|
|
||||||
import edu.tsinghua.hotmobi.model.ScreenEvent;
|
|
||||||
|
|
||||||
public class RefreshService extends Service implements Constants {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
SharedPreferencesWrapper mPreferences;
|
|
||||||
|
|
||||||
private AlarmManager mAlarmManager;
|
|
||||||
@Inject
|
|
||||||
AsyncTwitterWrapper mTwitterWrapper;
|
|
||||||
private PendingIntent mPendingRefreshHomeTimelineIntent, mPendingRefreshMentionsIntent,
|
|
||||||
mPendingRefreshDirectMessagesIntent, mPendingRefreshTrendsIntent;
|
|
||||||
|
|
||||||
private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
|
||||||
final String action = intent.getAction();
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(LOGTAG, String.format("Refresh service received action %s", action));
|
|
||||||
}
|
|
||||||
switch (action) {
|
|
||||||
case BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING: {
|
|
||||||
rescheduleHomeTimelineRefreshing();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BROADCAST_RESCHEDULE_MENTIONS_REFRESHING: {
|
|
||||||
rescheduleMentionsRefreshing();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING: {
|
|
||||||
rescheduleDirectMessagesRefreshing();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BROADCAST_RESCHEDULE_TRENDS_REFRESHING: {
|
|
||||||
rescheduleTrendsRefreshing();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BROADCAST_REFRESH_HOME_TIMELINE: {
|
|
||||||
if (isAutoRefreshAllowed()) {
|
|
||||||
mTwitterWrapper.getHomeTimelineAsync(new SimpleRefreshTaskParam() {
|
|
||||||
private UserKey[] accountIds;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public UserKey[] getAccountKeysWorker() {
|
|
||||||
if (accountIds != null) return accountIds;
|
|
||||||
final AccountPreferences[] prefs = AccountPreferences.getAccountPreferences(context,
|
|
||||||
DataStoreUtils.getAccountKeys(context));
|
|
||||||
return accountIds = getRefreshableIds(prefs, HomeRefreshableFilter.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public String[] getSinceIds() {
|
|
||||||
return DataStoreUtils.getNewestStatusIds(context,
|
|
||||||
Statuses.CONTENT_URI, getAccountKeys());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BROADCAST_REFRESH_NOTIFICATIONS: {
|
|
||||||
if (isAutoRefreshAllowed()) {
|
|
||||||
mTwitterWrapper.getActivitiesAboutMeAsync(new SimpleRefreshTaskParam() {
|
|
||||||
private UserKey[] accountIds;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public UserKey[] getAccountKeysWorker() {
|
|
||||||
if (accountIds != null) return accountIds;
|
|
||||||
final AccountPreferences[] prefs = AccountPreferences.getAccountPreferences(context,
|
|
||||||
DataStoreUtils.getAccountKeys(context));
|
|
||||||
return accountIds = getRefreshableIds(prefs, MentionsRefreshableFilter.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public String[] getSinceIds() {
|
|
||||||
return DataStoreUtils.getNewestActivityMaxPositions(context,
|
|
||||||
Activities.AboutMe.CONTENT_URI, getAccountKeys());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BROADCAST_REFRESH_DIRECT_MESSAGES: {
|
|
||||||
if (isAutoRefreshAllowed()) {
|
|
||||||
mTwitterWrapper.getReceivedDirectMessagesAsync(new SimpleRefreshTaskParam() {
|
|
||||||
private UserKey[] accountIds;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public UserKey[] getAccountKeysWorker() {
|
|
||||||
if (accountIds != null) return accountIds;
|
|
||||||
final AccountPreferences[] prefs = AccountPreferences.getAccountPreferences(context,
|
|
||||||
DataStoreUtils.getAccountKeys(context));
|
|
||||||
return accountIds = getRefreshableIds(prefs, MessagesRefreshableFilter.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public String[] getSinceIds() {
|
|
||||||
return DataStoreUtils.getNewestMessageIds(context,
|
|
||||||
DirectMessages.Inbox.CONTENT_URI, getAccountKeys());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BROADCAST_REFRESH_TRENDS: {
|
|
||||||
if (isAutoRefreshAllowed()) {
|
|
||||||
final AccountPreferences[] prefs = AccountPreferences.getAccountPreferences(context,
|
|
||||||
DataStoreUtils.getAccountKeys(context));
|
|
||||||
final UserKey[] refreshIds = getRefreshableIds(prefs, TrendsRefreshableFilter.INSTANCE);
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(LOGTAG, String.format("Auto refreshing trends for %s", Arrays.toString(refreshIds)));
|
|
||||||
}
|
|
||||||
getLocalTrends(refreshIds);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
private final BroadcastReceiver mPowerStateReceiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
switch (intent.getAction()) {
|
|
||||||
case Intent.ACTION_BATTERY_CHANGED: {
|
|
||||||
BatteryRecord.log(context, intent);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
BatteryRecord.log(context);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
|
|
||||||
public long mPresentTime = -1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
switch (intent.getAction()) {
|
|
||||||
case Intent.ACTION_SCREEN_ON: {
|
|
||||||
ScreenEvent.log(context, ScreenEvent.Action.ON, getPresentDuration());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Intent.ACTION_SCREEN_OFF: {
|
|
||||||
ScreenEvent.log(context, ScreenEvent.Action.OFF, getPresentDuration());
|
|
||||||
mPresentTime = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Intent.ACTION_USER_PRESENT: {
|
|
||||||
mPresentTime = SystemClock.elapsedRealtime();
|
|
||||||
ScreenEvent.log(context, ScreenEvent.Action.PRESENT, -1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getPresentDuration() {
|
|
||||||
if (mPresentTime < 0) return -1;
|
|
||||||
return SystemClock.elapsedRealtime() - mPresentTime;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(final Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
GeneralComponentHelper.build(this).inject(this);
|
|
||||||
mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
|
||||||
mPendingRefreshHomeTimelineIntent = PendingIntent.getBroadcast(this, 0, new Intent(
|
|
||||||
BROADCAST_REFRESH_HOME_TIMELINE), 0);
|
|
||||||
mPendingRefreshMentionsIntent = PendingIntent.getBroadcast(this, 0, new Intent(BROADCAST_REFRESH_NOTIFICATIONS), 0);
|
|
||||||
mPendingRefreshDirectMessagesIntent = PendingIntent.getBroadcast(this, 0, new Intent(
|
|
||||||
BROADCAST_REFRESH_DIRECT_MESSAGES), 0);
|
|
||||||
mPendingRefreshTrendsIntent = PendingIntent.getBroadcast(this, 0, new Intent(BROADCAST_REFRESH_TRENDS), 0);
|
|
||||||
final IntentFilter refreshFilter = new IntentFilter(BROADCAST_NOTIFICATION_DELETED);
|
|
||||||
refreshFilter.addAction(BROADCAST_REFRESH_HOME_TIMELINE);
|
|
||||||
refreshFilter.addAction(BROADCAST_REFRESH_NOTIFICATIONS);
|
|
||||||
refreshFilter.addAction(BROADCAST_REFRESH_DIRECT_MESSAGES);
|
|
||||||
refreshFilter.addAction(BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING);
|
|
||||||
refreshFilter.addAction(BROADCAST_RESCHEDULE_MENTIONS_REFRESHING);
|
|
||||||
refreshFilter.addAction(BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING);
|
|
||||||
registerReceiver(mStateReceiver, refreshFilter);
|
|
||||||
final IntentFilter batteryFilter = new IntentFilter();
|
|
||||||
batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
|
||||||
batteryFilter.addAction(Intent.ACTION_BATTERY_OKAY);
|
|
||||||
batteryFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
|
||||||
batteryFilter.addAction(Intent.ACTION_POWER_CONNECTED);
|
|
||||||
batteryFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
|
|
||||||
final IntentFilter screenFilter = new IntentFilter();
|
|
||||||
screenFilter.addAction(Intent.ACTION_SCREEN_ON);
|
|
||||||
screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
|
||||||
screenFilter.addAction(Intent.ACTION_USER_PRESENT);
|
|
||||||
registerReceiver(mPowerStateReceiver, batteryFilter);
|
|
||||||
registerReceiver(mScreenStateReceiver, screenFilter);
|
|
||||||
PowerStateReceiver.Companion.setServiceReceiverStarted(true);
|
|
||||||
if (Utils.hasAutoRefreshAccounts(this)) {
|
|
||||||
startAutoRefresh();
|
|
||||||
} else {
|
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
PowerStateReceiver.Companion.setServiceReceiverStarted(false);
|
|
||||||
unregisterReceiver(mScreenStateReceiver);
|
|
||||||
unregisterReceiver(mPowerStateReceiver);
|
|
||||||
unregisterReceiver(mStateReceiver);
|
|
||||||
if (Utils.hasAutoRefreshAccounts(this)) {
|
|
||||||
// Auto refresh enabled, so I will try to start service after it was
|
|
||||||
// stopped.
|
|
||||||
startService(new Intent(this, getClass()));
|
|
||||||
}
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isAutoRefreshAllowed() {
|
|
||||||
return Utils.isNetworkAvailable(this) && (Utils.isBatteryOkay(this) || !Utils.shouldStopAutoRefreshOnBatteryLow(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getLocalTrends(final UserKey[] accountIds) {
|
|
||||||
final UserKey account_id = Utils.getDefaultAccountKey(this);
|
|
||||||
final int woeid = mPreferences.getInt(KEY_LOCAL_TRENDS_WOEID, 1);
|
|
||||||
mTwitterWrapper.getLocalTrendsAsync(account_id, woeid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserKey[] getRefreshableIds(final AccountPreferences[] prefs, final RefreshableAccountFilter filter) {
|
|
||||||
if (prefs == null) return null;
|
|
||||||
final UserKey[] temp = new UserKey[prefs.length];
|
|
||||||
int i = 0;
|
|
||||||
for (final AccountPreferences pref : prefs) {
|
|
||||||
if (pref.isAutoRefreshEnabled() && filter.isRefreshable(pref)) {
|
|
||||||
temp[i++] = pref.getAccountKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final UserKey[] result = new UserKey[i];
|
|
||||||
System.arraycopy(temp, 0, result, 0, i);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getRefreshInterval() {
|
|
||||||
if (mPreferences == null) return 0;
|
|
||||||
final int prefValue = NumberUtils.toInt(mPreferences.getString(KEY_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL), -1);
|
|
||||||
return Math.max(prefValue, 3) * 60 * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rescheduleDirectMessagesRefreshing() {
|
|
||||||
mAlarmManager.cancel(mPendingRefreshDirectMessagesIntent);
|
|
||||||
final long refreshInterval = getRefreshInterval();
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, mPendingRefreshDirectMessagesIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rescheduleHomeTimelineRefreshing() {
|
|
||||||
mAlarmManager.cancel(mPendingRefreshHomeTimelineIntent);
|
|
||||||
final long refreshInterval = getRefreshInterval();
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, mPendingRefreshHomeTimelineIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rescheduleMentionsRefreshing() {
|
|
||||||
mAlarmManager.cancel(mPendingRefreshMentionsIntent);
|
|
||||||
final long refreshInterval = getRefreshInterval();
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, mPendingRefreshMentionsIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rescheduleTrendsRefreshing() {
|
|
||||||
mAlarmManager.cancel(mPendingRefreshTrendsIntent);
|
|
||||||
final long refreshInterval = getRefreshInterval();
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, mPendingRefreshTrendsIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean startAutoRefresh() {
|
|
||||||
stopAutoRefresh();
|
|
||||||
final long refreshInterval = getRefreshInterval();
|
|
||||||
if (refreshInterval <= 0) return false;
|
|
||||||
rescheduleHomeTimelineRefreshing();
|
|
||||||
rescheduleMentionsRefreshing();
|
|
||||||
rescheduleDirectMessagesRefreshing();
|
|
||||||
rescheduleTrendsRefreshing();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopAutoRefresh() {
|
|
||||||
mAlarmManager.cancel(mPendingRefreshHomeTimelineIntent);
|
|
||||||
mAlarmManager.cancel(mPendingRefreshMentionsIntent);
|
|
||||||
mAlarmManager.cancel(mPendingRefreshDirectMessagesIntent);
|
|
||||||
mAlarmManager.cancel(mPendingRefreshTrendsIntent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface RefreshableAccountFilter {
|
|
||||||
boolean isRefreshable(AccountPreferences pref);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class HomeRefreshableFilter implements RefreshableAccountFilter {
|
|
||||||
public static final RefreshableAccountFilter INSTANCE = new HomeRefreshableFilter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRefreshable(final AccountPreferences pref) {
|
|
||||||
return pref.isAutoRefreshHomeTimelineEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MentionsRefreshableFilter implements RefreshableAccountFilter {
|
|
||||||
|
|
||||||
static final RefreshableAccountFilter INSTANCE = new MentionsRefreshableFilter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRefreshable(final AccountPreferences pref) {
|
|
||||||
return pref.isAutoRefreshMentionsEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MessagesRefreshableFilter implements RefreshableAccountFilter {
|
|
||||||
public static final RefreshableAccountFilter INSTANCE = new MentionsRefreshableFilter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRefreshable(final AccountPreferences pref) {
|
|
||||||
return pref.isAutoRefreshDirectMessagesEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TrendsRefreshableFilter implements RefreshableAccountFilter {
|
|
||||||
public static final RefreshableAccountFilter INSTANCE = new TrendsRefreshableFilter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRefreshable(final AccountPreferences pref) {
|
|
||||||
return pref.isAutoRefreshTrendsEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
package org.mariotaku.twidere.task;
|
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.squareup.otto.Bus;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
|
||||||
import org.mariotaku.abstask.library.AbstractTask;
|
|
||||||
import org.mariotaku.microblog.library.MicroBlog;
|
|
||||||
import org.mariotaku.microblog.library.MicroBlogException;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.DirectMessage;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.ErrorInfo;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.Paging;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.ResponseList;
|
|
||||||
import org.mariotaku.twidere.BuildConfig;
|
|
||||||
import org.mariotaku.twidere.Constants;
|
|
||||||
import org.mariotaku.twidere.TwidereConstants;
|
|
||||||
import org.mariotaku.twidere.model.RefreshTaskParam;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.model.message.GetMessagesTaskEvent;
|
|
||||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
|
||||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
|
||||||
import org.mariotaku.twidere.util.ErrorInfoStore;
|
|
||||||
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
|
|
||||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
|
||||||
import org.mariotaku.twidere.util.TwitterWrapper;
|
|
||||||
import org.mariotaku.twidere.util.UriUtils;
|
|
||||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 16/2/14.
|
|
||||||
*/
|
|
||||||
public abstract class GetDirectMessagesTask extends AbstractTask<RefreshTaskParam,
|
|
||||||
List<TwitterWrapper.MessageListResponse>, Object> implements Constants {
|
|
||||||
|
|
||||||
protected final Context context;
|
|
||||||
@Inject
|
|
||||||
protected ErrorInfoStore errorInfoStore;
|
|
||||||
@Inject
|
|
||||||
protected SharedPreferencesWrapper preferences;
|
|
||||||
@Inject
|
|
||||||
protected Bus bus;
|
|
||||||
|
|
||||||
public GetDirectMessagesTask(Context context) {
|
|
||||||
this.context = context;
|
|
||||||
GeneralComponentHelper.build(context).inject(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract ResponseList<DirectMessage> getDirectMessages(MicroBlog twitter, Paging paging)
|
|
||||||
throws MicroBlogException;
|
|
||||||
|
|
||||||
protected abstract Uri getDatabaseUri();
|
|
||||||
|
|
||||||
protected abstract boolean isOutgoing();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<TwitterWrapper.MessageListResponse> doLongOperation(final RefreshTaskParam param) {
|
|
||||||
final UserKey[] accountKeys = param.getAccountKeys();
|
|
||||||
final String[] sinceIds = param.getSinceIds(), maxIds = param.getMaxIds();
|
|
||||||
final List<TwitterWrapper.MessageListResponse> result = new ArrayList<>();
|
|
||||||
int idx = 0;
|
|
||||||
final int loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT);
|
|
||||||
for (final UserKey accountKey : accountKeys) {
|
|
||||||
final MicroBlog twitter = MicroBlogAPIFactory.getInstance(context, accountKey);
|
|
||||||
if (twitter == null) continue;
|
|
||||||
try {
|
|
||||||
final Paging paging = new Paging();
|
|
||||||
paging.setCount(loadItemLimit);
|
|
||||||
String maxId = null, sinceId = null;
|
|
||||||
if (maxIds != null && maxIds[idx] != null) {
|
|
||||||
maxId = maxIds[idx];
|
|
||||||
paging.setMaxId(maxId);
|
|
||||||
}
|
|
||||||
if (sinceIds != null && sinceIds[idx] != null) {
|
|
||||||
sinceId = sinceIds[idx];
|
|
||||||
long sinceIdLong = NumberUtils.toLong(sinceId, -1);
|
|
||||||
//TODO handle non-twitter case
|
|
||||||
if (sinceIdLong != -1) {
|
|
||||||
paging.sinceId(String.valueOf(sinceIdLong - 1));
|
|
||||||
} else {
|
|
||||||
paging.sinceId(sinceId);
|
|
||||||
}
|
|
||||||
if (maxIds == null || sinceIds[idx] == null) {
|
|
||||||
paging.setLatestResults(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final List<DirectMessage> messages = getDirectMessages(twitter, paging);
|
|
||||||
result.add(new TwitterWrapper.MessageListResponse(accountKey, maxId, sinceId, messages));
|
|
||||||
storeMessages(accountKey, messages, isOutgoing(), true);
|
|
||||||
errorInfoStore.remove(ErrorInfoStore.KEY_DIRECT_MESSAGES, accountKey);
|
|
||||||
} catch (final MicroBlogException e) {
|
|
||||||
if (e.getErrorCode() == ErrorInfo.NO_DIRECT_MESSAGE_PERMISSION) {
|
|
||||||
errorInfoStore.put(ErrorInfoStore.KEY_DIRECT_MESSAGES, accountKey,
|
|
||||||
ErrorInfoStore.CODE_NO_DM_PERMISSION);
|
|
||||||
} else if (e.isCausedByNetworkIssue()) {
|
|
||||||
errorInfoStore.put(ErrorInfoStore.KEY_DIRECT_MESSAGES, accountKey,
|
|
||||||
ErrorInfoStore.CODE_NETWORK_ERROR);
|
|
||||||
}
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.w(TwidereConstants.LOGTAG, e);
|
|
||||||
}
|
|
||||||
result.add(new TwitterWrapper.MessageListResponse(accountKey, e));
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean storeMessages(UserKey accountKey, List<DirectMessage> messages, boolean isOutgoing, boolean notify) {
|
|
||||||
if (messages == null) return true;
|
|
||||||
final Uri uri = getDatabaseUri();
|
|
||||||
final ContentValues[] valuesArray = new ContentValues[messages.size()];
|
|
||||||
|
|
||||||
for (int i = 0, j = messages.size(); i < j; i++) {
|
|
||||||
final DirectMessage message = messages.get(i);
|
|
||||||
try {
|
|
||||||
valuesArray[i] = ContentValuesCreator.createDirectMessage(message, accountKey, isOutgoing);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all rows conflicting before new data inserted.
|
|
||||||
// final Expression deleteWhere = Expression.and(Expression.equals(DirectMessages.ACCOUNT_ID, accountKey),
|
|
||||||
// Expression.in(new Column(DirectMessages.MESSAGE_ID), new RawItemArray(messageIds)));
|
|
||||||
// final Uri deleteUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, false);
|
|
||||||
// mResolver.delete(deleteUri, deleteWhere.getSQL(), null);
|
|
||||||
|
|
||||||
|
|
||||||
// Insert previously fetched items.
|
|
||||||
final Uri insertUri = UriUtils.appendQueryParameters(uri, TwidereConstants.QUERY_PARAM_NOTIFY, notify);
|
|
||||||
ContentResolverUtils.bulkInsert(context.getContentResolver(), insertUri, valuesArray);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void beforeExecute(RefreshTaskParam params) {
|
|
||||||
bus.post(new GetMessagesTaskEvent(getDatabaseUri(), true, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void afterExecute(Object handler, List<TwitterWrapper.MessageListResponse> result) {
|
|
||||||
bus.post(new GetMessagesTaskEvent(getDatabaseUri(), false, AsyncTwitterWrapper.getException(result)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package org.mariotaku.twidere.task;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.mariotaku.microblog.library.MicroBlog;
|
|
||||||
import org.mariotaku.microblog.library.MicroBlogException;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.Trends;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 16/2/24.
|
|
||||||
*/
|
|
||||||
public class GetLocalTrendsTask extends GetTrendsTask {
|
|
||||||
|
|
||||||
private final int woeid;
|
|
||||||
|
|
||||||
public GetLocalTrendsTask(final Context context, final UserKey accountKey, final int woeid) {
|
|
||||||
super(context, accountKey);
|
|
||||||
this.woeid = woeid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Trends> getTrends(@NonNull final MicroBlog twitter) throws MicroBlogException {
|
|
||||||
return twitter.getLocationTrends(woeid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Uri getContentUri() {
|
|
||||||
return CachedTrends.Local.CONTENT_URI;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package org.mariotaku.twidere.task;
|
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.mariotaku.abstask.library.AbstractTask;
|
|
||||||
import org.mariotaku.microblog.library.MicroBlog;
|
|
||||||
import org.mariotaku.microblog.library.MicroBlogException;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.ResponseList;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.SavedSearch;
|
|
||||||
import org.mariotaku.sqliteqb.library.Expression;
|
|
||||||
import org.mariotaku.twidere.BuildConfig;
|
|
||||||
import org.mariotaku.twidere.model.SingleResponse;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches;
|
|
||||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
|
||||||
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
|
|
||||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
|
||||||
|
|
||||||
import static org.mariotaku.twidere.TwidereConstants.LOGTAG;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 16/2/13.
|
|
||||||
*/
|
|
||||||
public class GetSavedSearchesTask extends AbstractTask<UserKey[], SingleResponse<Object>, Object> {
|
|
||||||
|
|
||||||
private final Context mContext;
|
|
||||||
|
|
||||||
public GetSavedSearchesTask(Context context) {
|
|
||||||
this.mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SingleResponse<Object> doLongOperation(UserKey[] params) {
|
|
||||||
final ContentResolver cr = mContext.getContentResolver();
|
|
||||||
for (UserKey accountKey : params) {
|
|
||||||
final MicroBlog twitter = MicroBlogAPIFactory.getInstance(mContext, accountKey);
|
|
||||||
if (twitter == null) continue;
|
|
||||||
try {
|
|
||||||
final ResponseList<SavedSearch> searches = twitter.getSavedSearches();
|
|
||||||
final ContentValues[] values = ContentValuesCreator.createSavedSearches(searches,
|
|
||||||
accountKey);
|
|
||||||
final Expression where = Expression.equalsArgs(SavedSearches.ACCOUNT_KEY);
|
|
||||||
final String[] whereArgs = {accountKey.toString()};
|
|
||||||
cr.delete(SavedSearches.CONTENT_URI, where.getSQL(), whereArgs);
|
|
||||||
ContentResolverUtils.bulkInsert(cr, SavedSearches.CONTENT_URI, values);
|
|
||||||
} catch (MicroBlogException e) {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.w(LOGTAG, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SingleResponse.Companion.getInstance();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
package org.mariotaku.twidere.task;
|
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.squareup.otto.Bus;
|
|
||||||
|
|
||||||
import org.mariotaku.abstask.library.AbstractTask;
|
|
||||||
import org.mariotaku.microblog.library.MicroBlog;
|
|
||||||
import org.mariotaku.microblog.library.MicroBlogException;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.Trends;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.model.message.TrendsRefreshedEvent;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
|
||||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
|
||||||
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
|
|
||||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 16/2/24.
|
|
||||||
*/
|
|
||||||
public abstract class GetTrendsTask extends AbstractTask<Object, Object, Object> {
|
|
||||||
|
|
||||||
private final Context mContext;
|
|
||||||
private final UserKey mAccountId;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected Bus mBus;
|
|
||||||
|
|
||||||
public GetTrendsTask(Context context, final UserKey accountKey) {
|
|
||||||
GeneralComponentHelper.build(context).inject(this);
|
|
||||||
this.mContext = context;
|
|
||||||
this.mAccountId = accountKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract List<Trends> getTrends(@NonNull MicroBlog twitter) throws MicroBlogException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object doLongOperation(final Object param) {
|
|
||||||
final MicroBlog twitter = MicroBlogAPIFactory.getInstance(mContext, mAccountId);
|
|
||||||
if (twitter == null) return null;
|
|
||||||
try {
|
|
||||||
final List<Trends> trends = getTrends(twitter);
|
|
||||||
storeTrends(mContext.getContentResolver(), getContentUri(), trends);
|
|
||||||
return null;
|
|
||||||
} catch (final MicroBlogException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void afterExecute(Object handler, Object result) {
|
|
||||||
mBus.post(new TrendsRefreshedEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Uri getContentUri();
|
|
||||||
|
|
||||||
private static void storeTrends(ContentResolver cr, Uri uri, List<Trends> trendsList) {
|
|
||||||
final ArrayList<String> hashtags = new ArrayList<>();
|
|
||||||
final ArrayList<ContentValues> hashtagValues = new ArrayList<>();
|
|
||||||
if (trendsList != null && trendsList.size() > 0) {
|
|
||||||
final ContentValues[] valuesArray = ContentValuesCreator.createTrends(trendsList);
|
|
||||||
for (final ContentValues values : valuesArray) {
|
|
||||||
final String hashtag = values.getAsString(TwidereDataStore.CachedTrends.NAME).replaceFirst("#", "");
|
|
||||||
if (hashtags.contains(hashtag)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
hashtags.add(hashtag);
|
|
||||||
final ContentValues hashtagValue = new ContentValues();
|
|
||||||
hashtagValue.put(TwidereDataStore.CachedHashtags.NAME, hashtag);
|
|
||||||
hashtagValues.add(hashtagValue);
|
|
||||||
}
|
|
||||||
cr.delete(uri, null, null);
|
|
||||||
ContentResolverUtils.bulkInsert(cr, uri, valuesArray);
|
|
||||||
ContentResolverUtils.bulkDelete(cr, TwidereDataStore.CachedHashtags.CONTENT_URI, TwidereDataStore.CachedHashtags.NAME, hashtags, null);
|
|
||||||
ContentResolverUtils.bulkInsert(cr, TwidereDataStore.CachedHashtags.CONTENT_URI,
|
|
||||||
hashtagValues.toArray(new ContentValues[hashtagValues.size()]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* Twidere - Twitter client for Android
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012-2015 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.task;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.media.MediaScannerConnection;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.mariotaku.twidere.R;
|
|
||||||
import org.mariotaku.twidere.provider.CacheProvider;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 15/12/28.
|
|
||||||
*/
|
|
||||||
public class SaveMediaToGalleryTask extends ProgressSaveFileTask {
|
|
||||||
|
|
||||||
public SaveMediaToGalleryTask(@NonNull Activity activity, @NonNull Uri source, @NonNull File destination, String type) {
|
|
||||||
super(activity, source, destination, new CacheProvider.CacheFileTypeCallback(activity, type));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SaveFileTask create(final Activity activity, final Uri source,
|
|
||||||
@NonNull @CacheProvider.Type final String type) {
|
|
||||||
final File pubDir;
|
|
||||||
switch (type) {
|
|
||||||
case CacheProvider.Type.VIDEO: {
|
|
||||||
pubDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CacheProvider.Type.IMAGE: {
|
|
||||||
pubDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
pubDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final File saveDir = new File(pubDir, "Twidere");
|
|
||||||
return new SaveMediaToGalleryTask(activity, source, saveDir, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onFileSaved(@NonNull File savedFile, @Nullable String mimeType) {
|
|
||||||
final Context context = getContext();
|
|
||||||
if (context == null) return;
|
|
||||||
MediaScannerConnection.scanFile(context, new String[]{savedFile.getPath()},
|
|
||||||
new String[]{mimeType}, null);
|
|
||||||
Toast.makeText(context, R.string.saved_to_gallery, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onFileSaveFailed() {
|
|
||||||
final Context context = getContext();
|
|
||||||
if (context == null) return;
|
|
||||||
Toast.makeText(context, R.string.error_occurred, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -47,9 +47,7 @@ import org.mariotaku.microblog.library.twitter.http.HttpResponseCode;
|
||||||
import org.mariotaku.microblog.library.twitter.model.DirectMessage;
|
import org.mariotaku.microblog.library.twitter.model.DirectMessage;
|
||||||
import org.mariotaku.microblog.library.twitter.model.ErrorInfo;
|
import org.mariotaku.microblog.library.twitter.model.ErrorInfo;
|
||||||
import org.mariotaku.microblog.library.twitter.model.FriendshipUpdate;
|
import org.mariotaku.microblog.library.twitter.model.FriendshipUpdate;
|
||||||
import org.mariotaku.microblog.library.twitter.model.Paging;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.Relationship;
|
import org.mariotaku.microblog.library.twitter.model.Relationship;
|
||||||
import org.mariotaku.microblog.library.twitter.model.ResponseList;
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.SavedSearch;
|
import org.mariotaku.microblog.library.twitter.model.SavedSearch;
|
||||||
import org.mariotaku.microblog.library.twitter.model.User;
|
import org.mariotaku.microblog.library.twitter.model.User;
|
||||||
import org.mariotaku.microblog.library.twitter.model.UserList;
|
import org.mariotaku.microblog.library.twitter.model.UserList;
|
||||||
|
@ -106,10 +104,11 @@ import org.mariotaku.twidere.task.DestroyStatusTask;
|
||||||
import org.mariotaku.twidere.task.DestroyUserBlockTask;
|
import org.mariotaku.twidere.task.DestroyUserBlockTask;
|
||||||
import org.mariotaku.twidere.task.DestroyUserMuteTask;
|
import org.mariotaku.twidere.task.DestroyUserMuteTask;
|
||||||
import org.mariotaku.twidere.task.GetActivitiesAboutMeTask;
|
import org.mariotaku.twidere.task.GetActivitiesAboutMeTask;
|
||||||
import org.mariotaku.twidere.task.GetDirectMessagesTask;
|
|
||||||
import org.mariotaku.twidere.task.GetHomeTimelineTask;
|
import org.mariotaku.twidere.task.GetHomeTimelineTask;
|
||||||
import org.mariotaku.twidere.task.GetLocalTrendsTask;
|
import org.mariotaku.twidere.task.GetLocalTrendsTask;
|
||||||
|
import org.mariotaku.twidere.task.GetReceivedDirectMessagesTask;
|
||||||
import org.mariotaku.twidere.task.GetSavedSearchesTask;
|
import org.mariotaku.twidere.task.GetSavedSearchesTask;
|
||||||
|
import org.mariotaku.twidere.task.GetSentDirectMessagesTask;
|
||||||
import org.mariotaku.twidere.task.ManagedAsyncTask;
|
import org.mariotaku.twidere.task.ManagedAsyncTask;
|
||||||
import org.mariotaku.twidere.task.ReportSpamAndBlockTask;
|
import org.mariotaku.twidere.task.ReportSpamAndBlockTask;
|
||||||
import org.mariotaku.twidere.task.twitter.GetActivitiesTask;
|
import org.mariotaku.twidere.task.twitter.GetActivitiesTask;
|
||||||
|
@ -1325,61 +1324,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class GetReceivedDirectMessagesTask extends GetDirectMessagesTask {
|
|
||||||
|
|
||||||
public GetReceivedDirectMessagesTask(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseList<DirectMessage> getDirectMessages(final MicroBlog twitter, final Paging paging)
|
|
||||||
throws MicroBlogException {
|
|
||||||
return twitter.getDirectMessages(paging);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Uri getDatabaseUri() {
|
|
||||||
return Inbox.CONTENT_URI;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isOutgoing() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeExecute(RefreshTaskParam params) {
|
|
||||||
final Intent intent = new Intent(BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING);
|
|
||||||
context.sendBroadcast(intent);
|
|
||||||
super.beforeExecute(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class GetSentDirectMessagesTask extends GetDirectMessagesTask {
|
|
||||||
|
|
||||||
public GetSentDirectMessagesTask(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseList<DirectMessage> getDirectMessages(final MicroBlog twitter, final Paging paging)
|
|
||||||
throws MicroBlogException {
|
|
||||||
return twitter.getSentDirectMessages(paging);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isOutgoing() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Uri getDatabaseUri() {
|
|
||||||
return Outbox.CONTENT_URI;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public SharedPreferencesWrapper getPreferences() {
|
public SharedPreferencesWrapper getPreferences() {
|
||||||
return preferences;
|
return preferences;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1187,6 +1187,7 @@ public final class Utils implements Constants {
|
||||||
public static void startRefreshServiceIfNeeded(@NonNull final Context context) {
|
public static void startRefreshServiceIfNeeded(@NonNull final Context context) {
|
||||||
final Context appContext = context.getApplicationContext();
|
final Context appContext = context.getApplicationContext();
|
||||||
if (appContext == null) return;
|
if (appContext == null) return;
|
||||||
|
if (!appContext.getResources().getBoolean(R.bool.use_legacy_refresh_service)) return;
|
||||||
final Intent refreshServiceIntent = new Intent(appContext, RefreshService.class);
|
final Intent refreshServiceIntent = new Intent(appContext, RefreshService.class);
|
||||||
AsyncTask.execute(new Runnable() {
|
AsyncTask.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -396,15 +396,11 @@ class MediaViewerActivity : BaseActivity(), IExtendedActivity, ATEToolbarCustomi
|
||||||
val viewPager = findViewPager()
|
val viewPager = findViewPager()
|
||||||
val adapter = viewPager.adapter
|
val adapter = viewPager.adapter
|
||||||
val f = adapter.instantiateItem(viewPager, saveToStoragePosition) as? CacheDownloadMediaViewerFragment ?: return
|
val f = adapter.instantiateItem(viewPager, saveToStoragePosition) as? CacheDownloadMediaViewerFragment ?: return
|
||||||
val result = f.downloadResult ?: return
|
val cacheUri = f.downloadResult?.cacheUri ?: return
|
||||||
val cacheUri = result.cacheUri
|
val task: SaveFileTask = when (f) {
|
||||||
val hasMedia = cacheUri != null
|
is ImagePageFragment -> SaveMediaToGalleryTask.create(this, cacheUri, CacheProvider.Type.IMAGE)
|
||||||
if (!hasMedia) return
|
is VideoPageFragment -> SaveMediaToGalleryTask.create(this, cacheUri, CacheProvider.Type.VIDEO)
|
||||||
val task: SaveFileTask
|
is GifPageFragment -> SaveMediaToGalleryTask.create(this, cacheUri, CacheProvider.Type.IMAGE)
|
||||||
when (f) {
|
|
||||||
is ImagePageFragment -> task = SaveMediaToGalleryTask.create(this, cacheUri, CacheProvider.Type.IMAGE)
|
|
||||||
is VideoPageFragment -> task = SaveMediaToGalleryTask.create(this, cacheUri, CacheProvider.Type.VIDEO)
|
|
||||||
is GifPageFragment -> task = SaveMediaToGalleryTask.create(this, cacheUri, CacheProvider.Type.IMAGE)
|
|
||||||
else -> throw UnsupportedOperationException()
|
else -> throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
AsyncTaskUtils.executeTask(task)
|
AsyncTaskUtils.executeTask(task)
|
||||||
|
|
|
@ -27,7 +27,6 @@ import android.database.sqlite.SQLiteDatabase
|
||||||
import android.database.sqlite.SQLiteOpenHelper
|
import android.database.sqlite.SQLiteOpenHelper
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.AsyncTask
|
import android.os.AsyncTask
|
||||||
import android.os.Handler
|
|
||||||
import android.support.design.widget.FloatingActionButton
|
import android.support.design.widget.FloatingActionButton
|
||||||
import android.support.multidex.MultiDex
|
import android.support.multidex.MultiDex
|
||||||
import android.support.v4.content.ContextCompat
|
import android.support.v4.content.ContextCompat
|
||||||
|
@ -46,6 +45,8 @@ import nl.komponents.kovenant.android.stopKovenant
|
||||||
import nl.komponents.kovenant.task
|
import nl.komponents.kovenant.task
|
||||||
import org.apache.commons.lang3.ArrayUtils
|
import org.apache.commons.lang3.ArrayUtils
|
||||||
import org.mariotaku.kpreferences.KPreferences
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
|
import org.mariotaku.kpreferences.get
|
||||||
|
import org.mariotaku.kpreferences.set
|
||||||
import org.mariotaku.ktextension.configure
|
import org.mariotaku.ktextension.configure
|
||||||
import org.mariotaku.mediaviewer.library.MediaDownloader
|
import org.mariotaku.mediaviewer.library.MediaDownloader
|
||||||
import org.mariotaku.restfu.http.RestHttpClient
|
import org.mariotaku.restfu.http.RestHttpClient
|
||||||
|
@ -56,6 +57,8 @@ import org.mariotaku.twidere.TwidereConstants.*
|
||||||
import org.mariotaku.twidere.activity.AssistLauncherActivity
|
import org.mariotaku.twidere.activity.AssistLauncherActivity
|
||||||
import org.mariotaku.twidere.activity.MainActivity
|
import org.mariotaku.twidere.activity.MainActivity
|
||||||
import org.mariotaku.twidere.activity.MainHondaJOJOActivity
|
import org.mariotaku.twidere.activity.MainHondaJOJOActivity
|
||||||
|
import org.mariotaku.twidere.constant.apiLastChangeKey
|
||||||
|
import org.mariotaku.twidere.constant.bugReportsKey
|
||||||
import org.mariotaku.twidere.constant.defaultFeatureLastUpdated
|
import org.mariotaku.twidere.constant.defaultFeatureLastUpdated
|
||||||
import org.mariotaku.twidere.model.DefaultFeatures
|
import org.mariotaku.twidere.model.DefaultFeatures
|
||||||
import org.mariotaku.twidere.service.RefreshService
|
import org.mariotaku.twidere.service.RefreshService
|
||||||
|
@ -89,25 +92,14 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
@Inject
|
@Inject
|
||||||
lateinit internal var kPreferences: KPreferences
|
lateinit internal var kPreferences: KPreferences
|
||||||
|
|
||||||
var handler: Handler? = null
|
private lateinit var profileImageViewViewProcessor: ProfileImageViewViewProcessor
|
||||||
private set
|
private lateinit var fontFamilyTagProcessor: FontFamilyTagProcessor
|
||||||
|
|
||||||
private var profileImageViewViewProcessor: ProfileImageViewViewProcessor? = null
|
|
||||||
private var fontFamilyTagProcessor: FontFamilyTagProcessor? = null
|
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
super.attachBaseContext(base)
|
super.attachBaseContext(base)
|
||||||
MultiDex.install(this)
|
MultiDex.install(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initKeyboardShortcuts() {
|
|
||||||
val preferences = sharedPreferences
|
|
||||||
if (!preferences.getBoolean(KEY_KEYBOARD_SHORTCUT_INITIALIZED, false)) {
|
|
||||||
// getApplicationModule().getKeyboardShortcutsHandler().reset();
|
|
||||||
preferences.edit().putBoolean(KEY_KEYBOARD_SHORTCUT_INITIALIZED, true).apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val sqLiteDatabase: SQLiteDatabase by lazy {
|
val sqLiteDatabase: SQLiteDatabase by lazy {
|
||||||
StrictModeUtils.checkDiskIO()
|
StrictModeUtils.checkDiskIO()
|
||||||
|
@ -131,12 +123,14 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
initializeAsyncTask()
|
initializeAsyncTask()
|
||||||
initDebugMode()
|
initDebugMode()
|
||||||
initBugReport()
|
initBugReport()
|
||||||
handler = Handler()
|
|
||||||
|
|
||||||
updateEasterEggIcon()
|
updateEasterEggIcon()
|
||||||
|
|
||||||
migrateUsageStatisticsPreferences()
|
migrateUsageStatisticsPreferences()
|
||||||
Utils.startRefreshServiceIfNeeded(this)
|
if (resources.getBoolean(R.bool.use_job_refresh_service)) {
|
||||||
|
} else {
|
||||||
|
Utils.startRefreshServiceIfNeeded(this)
|
||||||
|
}
|
||||||
|
|
||||||
GeneralComponentHelper.build(this).inject(this)
|
GeneralComponentHelper.build(this).inject(this)
|
||||||
|
|
||||||
|
@ -225,9 +219,9 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
ATE.registerViewProcessor(ImageView::class.java, ImageViewViewProcessor())
|
ATE.registerViewProcessor(ImageView::class.java, ImageViewViewProcessor())
|
||||||
ATE.registerViewProcessor(MaterialEditText::class.java, MaterialEditTextViewProcessor())
|
ATE.registerViewProcessor(MaterialEditText::class.java, MaterialEditTextViewProcessor())
|
||||||
ATE.registerViewProcessor(ProgressWheel::class.java, ProgressWheelViewProcessor())
|
ATE.registerViewProcessor(ProgressWheel::class.java, ProgressWheelViewProcessor())
|
||||||
ATE.registerViewProcessor(ProfileImageView::class.java, profileImageViewViewProcessor!!)
|
ATE.registerViewProcessor(ProfileImageView::class.java, profileImageViewViewProcessor)
|
||||||
ATE.registerTagProcessor(OptimalLinkColorTagProcessor.TAG, OptimalLinkColorTagProcessor())
|
ATE.registerTagProcessor(OptimalLinkColorTagProcessor.TAG, OptimalLinkColorTagProcessor())
|
||||||
ATE.registerTagProcessor(FontFamilyTagProcessor.TAG, fontFamilyTagProcessor!!)
|
ATE.registerTagProcessor(FontFamilyTagProcessor.TAG, fontFamilyTagProcessor)
|
||||||
ATE.registerTagProcessor(IconActionButtonTagProcessor.PREFIX_COLOR,
|
ATE.registerTagProcessor(IconActionButtonTagProcessor.PREFIX_COLOR,
|
||||||
IconActionButtonTagProcessor(IconActionButtonTagProcessor.PREFIX_COLOR))
|
IconActionButtonTagProcessor(IconActionButtonTagProcessor.PREFIX_COLOR))
|
||||||
ATE.registerTagProcessor(IconActionButtonTagProcessor.PREFIX_COLOR_ACTIVATED,
|
ATE.registerTagProcessor(IconActionButtonTagProcessor.PREFIX_COLOR_ACTIVATED,
|
||||||
|
@ -256,8 +250,7 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initBugReport() {
|
private fun initBugReport() {
|
||||||
val preferences = sharedPreferences
|
if (!sharedPreferences[bugReportsKey]) return
|
||||||
if (!preferences.getBoolean(KEY_BUG_REPORTS, BuildConfig.DEBUG)) return
|
|
||||||
BugReporter.setImplementation(TwidereBugReporter())
|
BugReporter.setImplementation(TwidereBugReporter())
|
||||||
BugReporter.init(this)
|
BugReporter.init(this)
|
||||||
}
|
}
|
||||||
|
@ -305,9 +298,7 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
}
|
}
|
||||||
KEY_CONSUMER_KEY, KEY_CONSUMER_SECRET, KEY_API_URL_FORMAT, KEY_CREDENTIALS_TYPE,
|
KEY_CONSUMER_KEY, KEY_CONSUMER_SECRET, KEY_API_URL_FORMAT, KEY_CREDENTIALS_TYPE,
|
||||||
KEY_SAME_OAUTH_SIGNING_URL, KEY_THUMBOR_ENABLED, KEY_THUMBOR_ADDRESS, KEY_THUMBOR_SECURITY_KEY -> {
|
KEY_SAME_OAUTH_SIGNING_URL, KEY_THUMBOR_ENABLED, KEY_THUMBOR_ADDRESS, KEY_THUMBOR_SECURITY_KEY -> {
|
||||||
val editor = preferences.edit()
|
preferences[apiLastChangeKey] = System.currentTimeMillis()
|
||||||
editor.putLong(KEY_API_LAST_CHANGE, System.currentTimeMillis())
|
|
||||||
editor.apply()
|
|
||||||
}
|
}
|
||||||
KEY_EMOJI_SUPPORT -> {
|
KEY_EMOJI_SUPPORT -> {
|
||||||
externalThemeManager.reloadEmojiPreferences()
|
externalThemeManager.reloadEmojiPreferences()
|
||||||
|
@ -321,11 +312,11 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
}
|
}
|
||||||
KEY_PROFILE_IMAGE_STYLE -> {
|
KEY_PROFILE_IMAGE_STYLE -> {
|
||||||
Config.markChanged(this, VALUE_THEME_NAME_LIGHT, VALUE_THEME_NAME_DARK)
|
Config.markChanged(this, VALUE_THEME_NAME_LIGHT, VALUE_THEME_NAME_DARK)
|
||||||
profileImageViewViewProcessor!!.setStyle(Utils.getProfileImageStyle(preferences.getString(key, null)))
|
profileImageViewViewProcessor.setStyle(Utils.getProfileImageStyle(preferences.getString(key, null)))
|
||||||
}
|
}
|
||||||
KEY_THEME_FONT_FAMILY -> {
|
KEY_THEME_FONT_FAMILY -> {
|
||||||
Config.markChanged(this, VALUE_THEME_NAME_LIGHT, VALUE_THEME_NAME_DARK)
|
Config.markChanged(this, VALUE_THEME_NAME_LIGHT, VALUE_THEME_NAME_DARK)
|
||||||
fontFamilyTagProcessor!!.setFontFamily(ThemeUtils.getThemeFontFamily(preferences))
|
fontFamilyTagProcessor.setFontFamily(ThemeUtils.getThemeFontFamily(preferences))
|
||||||
}
|
}
|
||||||
KEY_THEME_COLOR -> {
|
KEY_THEME_COLOR -> {
|
||||||
val themeColor = preferences.getInt(key, ContextCompat.getColor(this,
|
val themeColor = preferences.getInt(key, ContextCompat.getColor(this,
|
||||||
|
|
|
@ -4,10 +4,9 @@ import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import org.mariotaku.kpreferences.*
|
import org.mariotaku.kpreferences.*
|
||||||
|
import org.mariotaku.twidere.BuildConfig
|
||||||
import org.mariotaku.twidere.Constants.KEY_NO_CLOSE_AFTER_TWEET_SENT
|
import org.mariotaku.twidere.Constants.KEY_NO_CLOSE_AFTER_TWEET_SENT
|
||||||
import org.mariotaku.twidere.TwidereConstants.*
|
import org.mariotaku.twidere.TwidereConstants.*
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_ATTACH_PRECISE_LOCATION
|
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_SETTINGS_WIZARD_COMPLETED
|
|
||||||
import org.mariotaku.twidere.extension.getNonEmptyString
|
import org.mariotaku.twidere.extension.getNonEmptyString
|
||||||
import org.mariotaku.twidere.model.CustomAPIConfig
|
import org.mariotaku.twidere.model.CustomAPIConfig
|
||||||
import org.mariotaku.twidere.model.account.cred.Credentials
|
import org.mariotaku.twidere.model.account.cred.Credentials
|
||||||
|
@ -37,6 +36,9 @@ val noCloseAfterTweetSentKey = KBooleanKey(KEY_NO_CLOSE_AFTER_TWEET_SENT, false)
|
||||||
val loadItemLimitKey = KIntKey(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT)
|
val loadItemLimitKey = KIntKey(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT)
|
||||||
val defaultFeatureLastUpdated = KLongKey("default_feature_last_updated", -1)
|
val defaultFeatureLastUpdated = KLongKey("default_feature_last_updated", -1)
|
||||||
val drawerTutorialCompleted = KBooleanKey(KEY_SETTINGS_WIZARD_COMPLETED, false)
|
val drawerTutorialCompleted = KBooleanKey(KEY_SETTINGS_WIZARD_COMPLETED, false)
|
||||||
|
val stopAutoRefreshWhenBatteryLowKey = KBooleanKey(KEY_STOP_AUTO_REFRESH_WHEN_BATTERY_LOW, true)
|
||||||
|
val apiLastChangeKey = KLongKey(KEY_API_LAST_CHANGE, -1)
|
||||||
|
val bugReportsKey = KBooleanKey(KEY_BUG_REPORTS, BuildConfig.DEBUG)
|
||||||
|
|
||||||
object defaultAPIConfigKey : KPreferenceKey<CustomAPIConfig> {
|
object defaultAPIConfigKey : KPreferenceKey<CustomAPIConfig> {
|
||||||
override fun contains(preferences: SharedPreferences): Boolean {
|
override fun contains(preferences: SharedPreferences): Boolean {
|
||||||
|
|
|
@ -41,9 +41,7 @@ import android.os.Looper
|
||||||
import android.support.design.widget.NavigationView
|
import android.support.design.widget.NavigationView
|
||||||
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
||||||
import android.support.v4.content.AsyncTaskLoader
|
import android.support.v4.content.AsyncTaskLoader
|
||||||
import android.support.v4.content.ContextCompat
|
|
||||||
import android.support.v4.content.Loader
|
import android.support.v4.content.Loader
|
||||||
import android.support.v4.graphics.drawable.DrawableCompat
|
|
||||||
import android.support.v4.view.MenuItemCompat
|
import android.support.v4.view.MenuItemCompat
|
||||||
import android.support.v4.view.ViewPager
|
import android.support.v4.view.ViewPager
|
||||||
import android.support.v7.view.SupportMenuInflater
|
import android.support.v7.view.SupportMenuInflater
|
||||||
|
@ -55,7 +53,10 @@ import android.view.View.OnClickListener
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import kotlinx.android.synthetic.main.header_drawer_account_selector.view.*
|
import kotlinx.android.synthetic.main.header_drawer_account_selector.view.*
|
||||||
import org.mariotaku.ktextension.*
|
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
|
||||||
|
import org.mariotaku.ktextension.convert
|
||||||
|
import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe
|
||||||
|
import org.mariotaku.ktextension.setItemAvailability
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.TwidereConstants.*
|
import org.mariotaku.twidere.TwidereConstants.*
|
||||||
import org.mariotaku.twidere.activity.*
|
import org.mariotaku.twidere.activity.*
|
||||||
|
@ -79,9 +80,9 @@ import java.util.*
|
||||||
|
|
||||||
class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<AccountsInfo>, OnSharedPreferenceChangeListener, OnClickListener, KeyboardShortcutCallback, NavigationView.OnNavigationItemSelectedListener {
|
class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<AccountsInfo>, OnSharedPreferenceChangeListener, OnClickListener, KeyboardShortcutCallback, NavigationView.OnNavigationItemSelectedListener {
|
||||||
|
|
||||||
private val mSystemWindowsInsets = Rect()
|
private val systemWindowsInsets = Rect()
|
||||||
|
|
||||||
private var accountsAdapter: AccountSelectorAdapter? = null
|
private lateinit var accountsAdapter: AccountSelectorAdapter
|
||||||
|
|
||||||
private val hasNextAccountIndicator by lazy { accountsHeader.hasNextAccountIndicator }
|
private val hasNextAccountIndicator by lazy { accountsHeader.hasNextAccountIndicator }
|
||||||
private val hasPrevAccountIndicator by lazy { accountsHeader.hasPrevAccountIndicator }
|
private val hasPrevAccountIndicator by lazy { accountsHeader.hasPrevAccountIndicator }
|
||||||
|
@ -113,7 +114,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
accountsSelector.adapter = accountsAdapter
|
accountsSelector.adapter = accountsAdapter
|
||||||
accountsSelector.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
accountsSelector.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||||
val adapter = accountsAdapter ?: return
|
val adapter = accountsAdapter
|
||||||
val pagePosition = position + positionOffset
|
val pagePosition = position + positionOffset
|
||||||
val pageCount = adapter.count
|
val pageCount = adapter.count
|
||||||
val visiblePages = 1 / adapter.getPageWidth(position)
|
val visiblePages = 1 / adapter.getPageWidth(position)
|
||||||
|
@ -145,7 +146,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
} else {
|
} else {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.compose -> {
|
R.id.compose -> {
|
||||||
val account = accountsAdapter!!.selectedAccount ?: return@OnMenuItemClickListener true
|
val account = accountsAdapter.selectedAccount ?: return@OnMenuItemClickListener true
|
||||||
val composeIntent = Intent(INTENT_ACTION_COMPOSE)
|
val composeIntent = Intent(INTENT_ACTION_COMPOSE)
|
||||||
composeIntent.setClass(activity, ComposeActivity::class.java)
|
composeIntent.setClass(activity, ComposeActivity::class.java)
|
||||||
composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
||||||
|
@ -225,7 +226,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.profileContainer -> {
|
R.id.profileContainer -> {
|
||||||
val account = accountsAdapter!!.selectedAccount ?: return
|
val account = accountsAdapter.selectedAccount ?: return
|
||||||
val activity = activity
|
val activity = activity
|
||||||
if (account.user != null) {
|
if (account.user != null) {
|
||||||
IntentUtils.openUserProfile(activity, account.user!!, null,
|
IntentUtils.openUserProfile(activity, account.user!!, null,
|
||||||
|
@ -262,18 +263,18 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
profileContainer.visibility = View.INVISIBLE
|
profileContainer.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
useStarsForLikes = preferences.getBoolean(KEY_I_WANT_MY_STARS_BACK)
|
useStarsForLikes = preferences.getBoolean(KEY_I_WANT_MY_STARS_BACK)
|
||||||
accountsAdapter!!.accounts = accounts
|
accountsAdapter.accounts = accounts
|
||||||
val defaultKey = preferences.getString(KEY_DEFAULT_ACCOUNT_KEY, null)?.convert(UserKey::valueOf)
|
val defaultKey = preferences.getString(KEY_DEFAULT_ACCOUNT_KEY, null)?.convert(UserKey::valueOf)
|
||||||
?: accounts.firstOrNull { it.activated }?.key
|
?: accounts.firstOrNull { it.activated }?.key
|
||||||
val defaultAccount = accounts.firstOrNull { it.key.maybeEquals(defaultKey) }
|
val defaultAccount = accounts.firstOrNull { it.key.maybeEquals(defaultKey) }
|
||||||
accountsAdapter!!.selectedAccount = defaultAccount
|
accountsAdapter.selectedAccount = defaultAccount
|
||||||
|
|
||||||
if (accountActionProvider != null) {
|
if (accountActionProvider != null) {
|
||||||
accountActionProvider!!.isExclusive = false
|
accountActionProvider!!.isExclusive = false
|
||||||
accountActionProvider!!.accounts = accounts
|
accountActionProvider!!.accounts = accounts
|
||||||
}
|
}
|
||||||
updateAccountActions()
|
updateAccountActions()
|
||||||
val currentAccount = accountsAdapter!!.selectedAccount
|
val currentAccount = accountsAdapter.selectedAccount
|
||||||
if (currentAccount != null) {
|
if (currentAccount != null) {
|
||||||
displayAccountBanner(currentAccount)
|
displayAccountBanner(currentAccount)
|
||||||
displayCurrentAccount(null)
|
displayCurrentAccount(null)
|
||||||
|
@ -297,7 +298,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fitSystemWindows(insets: Rect) {
|
override fun fitSystemWindows(insets: Rect) {
|
||||||
mSystemWindowsInsets.set(insets)
|
systemWindowsInsets.set(insets)
|
||||||
updateSystemWindowsInsets()
|
updateSystemWindowsInsets()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,11 +317,10 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
internal fun updateAccountActions() {
|
internal fun updateAccountActions() {
|
||||||
val activity = activity as HomeActivity
|
val activity = activity as HomeActivity
|
||||||
val tabs = activity.tabs
|
val tabs = activity.tabs
|
||||||
val account = accountsAdapter!!.selectedAccount ?: return
|
val account = accountsAdapter.selectedAccount ?: return
|
||||||
var hasDmTab = false
|
var hasDmTab = false
|
||||||
var hasInteractionsTab = false
|
var hasInteractionsTab = false
|
||||||
for (tab in tabs) {
|
for (tab in tabs) {
|
||||||
if (tab.type == null) continue
|
|
||||||
when (tab.type) {
|
when (tab.type) {
|
||||||
CustomTabType.DIRECT_MESSAGES -> {
|
CustomTabType.DIRECT_MESSAGES -> {
|
||||||
if (!hasDmTab) {
|
if (!hasDmTab) {
|
||||||
|
@ -338,17 +338,8 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
menu.setItemAvailability(R.id.interactions, !hasInteractionsTab)
|
menu.setItemAvailability(R.id.interactions, !hasInteractionsTab)
|
||||||
menu.setItemAvailability(R.id.messages, !hasDmTab)
|
menu.setItemAvailability(R.id.messages, !hasDmTab)
|
||||||
|
|
||||||
if (useStarsForLikes) {
|
menu.setItemAvailability(R.id.favorites, useStarsForLikes)
|
||||||
menu.setMenuItemTitle(R.id.favorites, R.string.favorites)
|
menu.setItemAvailability(R.id.likes, !useStarsForLikes)
|
||||||
val icon = ContextCompat.getDrawable(context, R.drawable.ic_action_star)
|
|
||||||
DrawableCompat.setTintList(icon, navigationView.itemIconTintList)
|
|
||||||
menu.setMenuItemIcon(R.id.favorites, icon)
|
|
||||||
} else {
|
|
||||||
menu.setMenuItemTitle(R.id.favorites, R.string.likes)
|
|
||||||
val icon = ContextCompat.getDrawable(context, R.drawable.ic_action_heart)
|
|
||||||
DrawableCompat.setTintList(icon, navigationView.itemIconTintList)
|
|
||||||
menu.setMenuItemIcon(R.id.favorites, icon)
|
|
||||||
}
|
|
||||||
var hasLists = false
|
var hasLists = false
|
||||||
var hasGroups = false
|
var hasGroups = false
|
||||||
var hasPublicTimeline = false
|
var hasPublicTimeline = false
|
||||||
|
@ -434,7 +425,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
val profileDrawable = profileImageView.drawable
|
val profileDrawable = profileImageView.drawable
|
||||||
clickedDrawable = clickedImageView.drawable
|
clickedDrawable = clickedImageView.drawable
|
||||||
clickedColors = clickedImageView.borderColors
|
clickedColors = clickedImageView.borderColors
|
||||||
val oldSelectedAccount = accountsAdapter!!.selectedAccount ?: return
|
val oldSelectedAccount = accountsAdapter.selectedAccount ?: return
|
||||||
mediaLoader.displayDashboardProfileImage(clickedImageView,
|
mediaLoader.displayDashboardProfileImage(clickedImageView,
|
||||||
oldSelectedAccount, profileDrawable)
|
oldSelectedAccount, profileDrawable)
|
||||||
clickedImageView.setBorderColors(*profileImageView.borderColors)
|
clickedImageView.setBorderColors(*profileImageView.borderColors)
|
||||||
|
@ -460,7 +451,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putString(KEY_DEFAULT_ACCOUNT_KEY, account.key.toString())
|
.putString(KEY_DEFAULT_ACCOUNT_KEY, account.key.toString())
|
||||||
.apply()
|
.apply()
|
||||||
accountsAdapter!!.selectedAccount = account
|
accountsAdapter.selectedAccount = account
|
||||||
updateAccountActions()
|
updateAccountActions()
|
||||||
displayCurrentAccount(clickedDrawable)
|
displayCurrentAccount(clickedDrawable)
|
||||||
snapshotView.visibility = View.INVISIBLE
|
snapshotView.visibility = View.INVISIBLE
|
||||||
|
@ -493,7 +484,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun displayCurrentAccount(profileImageSnapshot: Drawable?) {
|
private fun displayCurrentAccount(profileImageSnapshot: Drawable?) {
|
||||||
val account = accountsAdapter!!.selectedAccount ?: return
|
val account = accountsAdapter.selectedAccount ?: return
|
||||||
accountProfileNameView.text = account.user.name
|
accountProfileNameView.text = account.user.name
|
||||||
accountProfileScreenNameView.text = String.format("@%s", account.user.screen_name)
|
accountProfileScreenNameView.text = String.format("@%s", account.user.screen_name)
|
||||||
mediaLoader.displayDashboardProfileImage(accountProfileImageView, account,
|
mediaLoader.displayDashboardProfileImage(accountProfileImageView, account,
|
||||||
|
@ -506,7 +497,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
||||||
val account = accountsAdapter!!.selectedAccount ?: return false
|
val account = accountsAdapter.selectedAccount ?: return false
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.search -> {
|
R.id.search -> {
|
||||||
val intent = Intent(activity, QuickSearchBarActivity::class.java)
|
val intent = Intent(activity, QuickSearchBarActivity::class.java)
|
||||||
|
@ -520,9 +511,9 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
||||||
startActivity(composeIntent)
|
startActivity(composeIntent)
|
||||||
}
|
}
|
||||||
R.id.favorites -> {
|
R.id.likes, R.id.favorites -> {
|
||||||
IntentUtils.openUserFavorites(activity, account.key,
|
IntentUtils.openUserFavorites(activity, account.key, account.key,
|
||||||
account.key, account.user.screen_name)
|
account.user.screen_name)
|
||||||
}
|
}
|
||||||
R.id.lists -> {
|
R.id.lists -> {
|
||||||
IntentUtils.openUserLists(activity, account.key,
|
IntentUtils.openUserLists(activity, account.key,
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2014 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.service
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.annotation.TargetApi
|
||||||
|
import android.app.job.JobParameters
|
||||||
|
import android.app.job.JobService
|
||||||
|
import android.os.Build
|
||||||
|
import org.mariotaku.abstask.library.AbstractTask
|
||||||
|
import org.mariotaku.abstask.library.TaskStarter
|
||||||
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
|
import org.mariotaku.twidere.constant.stopAutoRefreshWhenBatteryLowKey
|
||||||
|
import org.mariotaku.twidere.model.AccountPreferences
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||||
|
import org.mariotaku.twidere.task.GetActivitiesAboutMeTask
|
||||||
|
import org.mariotaku.twidere.task.GetHomeTimelineTask
|
||||||
|
import org.mariotaku.twidere.task.GetReceivedDirectMessagesTask
|
||||||
|
import org.mariotaku.twidere.util.DataStoreUtils
|
||||||
|
import org.mariotaku.twidere.util.Utils
|
||||||
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 14/12/12.
|
||||||
|
*/
|
||||||
|
@SuppressLint("Registered")
|
||||||
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
class JobRefreshService : JobService() {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
internal lateinit var preferences: KPreferences
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
GeneralComponentHelper.build(this).inject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartJob(params: JobParameters): Boolean {
|
||||||
|
if (!Utils.isBatteryOkay(this) && preferences[stopAutoRefreshWhenBatteryLowKey]) {
|
||||||
|
// Low battery, don't refresh
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val task = createJobTask(params) ?: return false
|
||||||
|
task.callback = {
|
||||||
|
this.jobFinished(params, true)
|
||||||
|
}
|
||||||
|
TaskStarter.execute(task)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopJob(params: JobParameters): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun createJobTask(params: JobParameters): AbstractTask<*, *, () -> Unit>? {
|
||||||
|
when (params.extras?.getString(EXTRA_ACTION)) {
|
||||||
|
BROADCAST_REFRESH_HOME_TIMELINE -> {
|
||||||
|
val task = GetHomeTimelineTask(this)
|
||||||
|
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshHomeTimelineEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestStatusIds(this, Statuses.CONTENT_URI, accountKeys)
|
||||||
|
}
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
BROADCAST_REFRESH_NOTIFICATIONS -> {
|
||||||
|
val task = GetActivitiesAboutMeTask(this)
|
||||||
|
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestActivityMaxPositions(this, Activities.AboutMe.CONTENT_URI, accountKeys)
|
||||||
|
}
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
BROADCAST_REFRESH_DIRECT_MESSAGES -> {
|
||||||
|
val task = GetReceivedDirectMessagesTask(this)
|
||||||
|
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestMessageIds(this, DirectMessages.Inbox.CONTENT_URI, accountKeys)
|
||||||
|
}
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,304 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2014 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.service
|
||||||
|
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.app.Service
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.os.SystemClock
|
||||||
|
import android.util.Log
|
||||||
|
import edu.tsinghua.hotmobi.model.BatteryRecord
|
||||||
|
import edu.tsinghua.hotmobi.model.ScreenEvent
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils
|
||||||
|
import org.mariotaku.twidere.BuildConfig
|
||||||
|
import org.mariotaku.twidere.Constants
|
||||||
|
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||||
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants.*
|
||||||
|
import org.mariotaku.twidere.model.AccountPreferences
|
||||||
|
import org.mariotaku.twidere.model.SimpleRefreshTaskParam
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||||
|
import org.mariotaku.twidere.receiver.PowerStateReceiver
|
||||||
|
import org.mariotaku.twidere.util.AsyncTwitterWrapper
|
||||||
|
import org.mariotaku.twidere.util.DataStoreUtils
|
||||||
|
import org.mariotaku.twidere.util.SharedPreferencesWrapper
|
||||||
|
import org.mariotaku.twidere.util.Utils
|
||||||
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class RefreshService : Service(), Constants {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
internal lateinit var preferences: SharedPreferencesWrapper
|
||||||
|
@Inject
|
||||||
|
internal lateinit var twitterWrapper: AsyncTwitterWrapper
|
||||||
|
|
||||||
|
private lateinit var alarmManager: AlarmManager
|
||||||
|
private var pendingRefreshHomeTimelineIntent: PendingIntent? = null
|
||||||
|
private var pendingRefreshMentionsIntent: PendingIntent? = null
|
||||||
|
private var pendingRefreshDirectMessagesIntent: PendingIntent? = null
|
||||||
|
private var pendingRefreshTrendsIntent: PendingIntent? = null
|
||||||
|
|
||||||
|
private val mStateReceiver = object : BroadcastReceiver() {
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
val action = intent.action
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.d(LOGTAG, String.format("Refresh service received action %s", action))
|
||||||
|
}
|
||||||
|
when (action) {
|
||||||
|
BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING -> {
|
||||||
|
rescheduleHomeTimelineRefreshing()
|
||||||
|
}
|
||||||
|
BROADCAST_RESCHEDULE_MENTIONS_REFRESHING -> {
|
||||||
|
rescheduleMentionsRefreshing()
|
||||||
|
}
|
||||||
|
BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING -> {
|
||||||
|
rescheduleDirectMessagesRefreshing()
|
||||||
|
}
|
||||||
|
BROADCAST_RESCHEDULE_TRENDS_REFRESHING -> {
|
||||||
|
rescheduleTrendsRefreshing()
|
||||||
|
}
|
||||||
|
BROADCAST_REFRESH_HOME_TIMELINE -> {
|
||||||
|
if (isAutoRefreshAllowed) {
|
||||||
|
twitterWrapper.getHomeTimelineAsync(AutoRefreshTaskParam(context,
|
||||||
|
AccountPreferences::isAutoRefreshHomeTimelineEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestStatusIds(context, Statuses.CONTENT_URI, accountKeys)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BROADCAST_REFRESH_NOTIFICATIONS -> {
|
||||||
|
if (isAutoRefreshAllowed) {
|
||||||
|
twitterWrapper.getActivitiesAboutMeAsync(AutoRefreshTaskParam(context,
|
||||||
|
AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestActivityMaxPositions(context,
|
||||||
|
Activities.AboutMe.CONTENT_URI, accountKeys)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BROADCAST_REFRESH_DIRECT_MESSAGES -> {
|
||||||
|
if (isAutoRefreshAllowed) {
|
||||||
|
twitterWrapper.getReceivedDirectMessagesAsync(AutoRefreshTaskParam(context,
|
||||||
|
AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestMessageIds(context,
|
||||||
|
DirectMessages.Inbox.CONTENT_URI, accountKeys)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BROADCAST_REFRESH_TRENDS -> {
|
||||||
|
if (isAutoRefreshAllowed) {
|
||||||
|
val prefs = AccountPreferences.getAccountPreferences(context,
|
||||||
|
DataStoreUtils.getAccountKeys(context)).filter(AccountPreferences::isAutoRefreshEnabled)
|
||||||
|
getLocalTrends(prefs.filter(AccountPreferences::isAutoRefreshTrendsEnabled)
|
||||||
|
.map(AccountPreferences::getAccountKey).toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mPowerStateReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
when (intent.action) {
|
||||||
|
Intent.ACTION_BATTERY_CHANGED -> {
|
||||||
|
BatteryRecord.log(context, intent)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
BatteryRecord.log(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mScreenStateReceiver = object : BroadcastReceiver() {
|
||||||
|
var mPresentTime: Long = -1
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
when (intent.action) {
|
||||||
|
Intent.ACTION_SCREEN_ON -> {
|
||||||
|
ScreenEvent.log(context, ScreenEvent.Action.ON, presentDuration)
|
||||||
|
}
|
||||||
|
Intent.ACTION_SCREEN_OFF -> {
|
||||||
|
ScreenEvent.log(context, ScreenEvent.Action.OFF, presentDuration)
|
||||||
|
mPresentTime = -1
|
||||||
|
}
|
||||||
|
Intent.ACTION_USER_PRESENT -> {
|
||||||
|
mPresentTime = SystemClock.elapsedRealtime()
|
||||||
|
ScreenEvent.log(context, ScreenEvent.Action.PRESENT, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val presentDuration: Long
|
||||||
|
get() {
|
||||||
|
if (mPresentTime < 0) return -1
|
||||||
|
return SystemClock.elapsedRealtime() - mPresentTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
GeneralComponentHelper.build(this).inject(this)
|
||||||
|
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
|
pendingRefreshHomeTimelineIntent = PendingIntent.getBroadcast(this, 0, Intent(
|
||||||
|
BROADCAST_REFRESH_HOME_TIMELINE), 0)
|
||||||
|
pendingRefreshMentionsIntent = PendingIntent.getBroadcast(this, 0, Intent(BROADCAST_REFRESH_NOTIFICATIONS), 0)
|
||||||
|
pendingRefreshDirectMessagesIntent = PendingIntent.getBroadcast(this, 0, Intent(
|
||||||
|
BROADCAST_REFRESH_DIRECT_MESSAGES), 0)
|
||||||
|
pendingRefreshTrendsIntent = PendingIntent.getBroadcast(this, 0, Intent(BROADCAST_REFRESH_TRENDS), 0)
|
||||||
|
val refreshFilter = IntentFilter(BROADCAST_NOTIFICATION_DELETED)
|
||||||
|
refreshFilter.addAction(BROADCAST_REFRESH_HOME_TIMELINE)
|
||||||
|
refreshFilter.addAction(BROADCAST_REFRESH_NOTIFICATIONS)
|
||||||
|
refreshFilter.addAction(BROADCAST_REFRESH_DIRECT_MESSAGES)
|
||||||
|
refreshFilter.addAction(BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING)
|
||||||
|
refreshFilter.addAction(BROADCAST_RESCHEDULE_MENTIONS_REFRESHING)
|
||||||
|
refreshFilter.addAction(BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING)
|
||||||
|
registerReceiver(mStateReceiver, refreshFilter)
|
||||||
|
val batteryFilter = IntentFilter()
|
||||||
|
batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED)
|
||||||
|
batteryFilter.addAction(Intent.ACTION_BATTERY_OKAY)
|
||||||
|
batteryFilter.addAction(Intent.ACTION_BATTERY_LOW)
|
||||||
|
batteryFilter.addAction(Intent.ACTION_POWER_CONNECTED)
|
||||||
|
batteryFilter.addAction(Intent.ACTION_POWER_DISCONNECTED)
|
||||||
|
val screenFilter = IntentFilter()
|
||||||
|
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
|
||||||
|
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
||||||
|
screenFilter.addAction(Intent.ACTION_USER_PRESENT)
|
||||||
|
registerReceiver(mPowerStateReceiver, batteryFilter)
|
||||||
|
registerReceiver(mScreenStateReceiver, screenFilter)
|
||||||
|
PowerStateReceiver.serviceReceiverStarted = true
|
||||||
|
if (Utils.hasAutoRefreshAccounts(this)) {
|
||||||
|
startAutoRefresh()
|
||||||
|
} else {
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
PowerStateReceiver.serviceReceiverStarted = false
|
||||||
|
unregisterReceiver(mScreenStateReceiver)
|
||||||
|
unregisterReceiver(mPowerStateReceiver)
|
||||||
|
unregisterReceiver(mStateReceiver)
|
||||||
|
if (Utils.hasAutoRefreshAccounts(this)) {
|
||||||
|
// Auto refresh enabled, so I will try to start service after it was
|
||||||
|
// stopped.
|
||||||
|
startService(Intent(this, javaClass))
|
||||||
|
}
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val isAutoRefreshAllowed: Boolean
|
||||||
|
get() = Utils.isNetworkAvailable(this) && (Utils.isBatteryOkay(this) || !Utils.shouldStopAutoRefreshOnBatteryLow(this))
|
||||||
|
|
||||||
|
private fun getLocalTrends(accountIds: Array<UserKey>) {
|
||||||
|
val account_id = Utils.getDefaultAccountKey(this)
|
||||||
|
val woeid = preferences.getInt(KEY_LOCAL_TRENDS_WOEID, 1)
|
||||||
|
twitterWrapper.getLocalTrendsAsync(account_id, woeid)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val refreshInterval: Long
|
||||||
|
get() {
|
||||||
|
val prefValue = NumberUtils.toInt(preferences.getString(KEY_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL), -1)
|
||||||
|
return (Math.max(prefValue, 3) * 60 * 1000).toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rescheduleDirectMessagesRefreshing() {
|
||||||
|
alarmManager.cancel(pendingRefreshDirectMessagesIntent)
|
||||||
|
val refreshInterval = refreshInterval
|
||||||
|
if (refreshInterval > 0) {
|
||||||
|
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||||
|
refreshInterval, pendingRefreshDirectMessagesIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rescheduleHomeTimelineRefreshing() {
|
||||||
|
alarmManager.cancel(pendingRefreshHomeTimelineIntent)
|
||||||
|
val refreshInterval = refreshInterval
|
||||||
|
if (refreshInterval > 0) {
|
||||||
|
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||||
|
refreshInterval, pendingRefreshHomeTimelineIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rescheduleMentionsRefreshing() {
|
||||||
|
alarmManager.cancel(pendingRefreshMentionsIntent)
|
||||||
|
val refreshInterval = refreshInterval
|
||||||
|
if (refreshInterval > 0) {
|
||||||
|
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||||
|
refreshInterval, pendingRefreshMentionsIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rescheduleTrendsRefreshing() {
|
||||||
|
alarmManager.cancel(pendingRefreshTrendsIntent)
|
||||||
|
val refreshInterval = refreshInterval
|
||||||
|
if (refreshInterval > 0) {
|
||||||
|
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||||
|
refreshInterval, pendingRefreshTrendsIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startAutoRefresh(): Boolean {
|
||||||
|
stopAutoRefresh()
|
||||||
|
val refreshInterval = refreshInterval
|
||||||
|
if (refreshInterval <= 0) return false
|
||||||
|
rescheduleHomeTimelineRefreshing()
|
||||||
|
rescheduleMentionsRefreshing()
|
||||||
|
rescheduleDirectMessagesRefreshing()
|
||||||
|
rescheduleTrendsRefreshing()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopAutoRefresh() {
|
||||||
|
alarmManager.cancel(pendingRefreshHomeTimelineIntent)
|
||||||
|
alarmManager.cancel(pendingRefreshMentionsIntent)
|
||||||
|
alarmManager.cancel(pendingRefreshDirectMessagesIntent)
|
||||||
|
alarmManager.cancel(pendingRefreshTrendsIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
class AutoRefreshTaskParam(
|
||||||
|
val context: Context,
|
||||||
|
val refreshable: (AccountPreferences) -> Boolean,
|
||||||
|
val getSinceIds: (Array<UserKey>) -> Array<String?>?
|
||||||
|
) : SimpleRefreshTaskParam() {
|
||||||
|
|
||||||
|
override fun getAccountKeysWorker(): Array<UserKey> {
|
||||||
|
val prefs = AccountPreferences.getAccountPreferences(context,
|
||||||
|
DataStoreUtils.getAccountKeys(context)).filter(AccountPreferences::isAutoRefreshEnabled)
|
||||||
|
return prefs.filter(refreshable)
|
||||||
|
.map(AccountPreferences::getAccountKey).toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val sinceIds: Array<String?>?
|
||||||
|
get() = getSinceIds(accountKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -40,9 +40,7 @@ class GetActivitiesAboutMeTask(context: Context) : GetActivitiesTask(context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
override fun getActivities(twitter: MicroBlog,
|
override fun getActivities(twitter: MicroBlog, details: AccountDetails, paging: Paging): ResponseList<Activity> {
|
||||||
details: AccountDetails,
|
|
||||||
paging: Paging): ResponseList<Activity> {
|
|
||||||
if (details.isOfficial(context)) {
|
if (details.isOfficial(context)) {
|
||||||
return twitter.getActivitiesAboutMe(paging)
|
return twitter.getActivitiesAboutMe(paging)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package org.mariotaku.twidere.task
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
|
import com.squareup.otto.Bus
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils
|
||||||
|
import org.mariotaku.abstask.library.AbstractTask
|
||||||
|
import org.mariotaku.kpreferences.get
|
||||||
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.DirectMessage
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.ErrorInfo
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Paging
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.ResponseList
|
||||||
|
import org.mariotaku.twidere.BuildConfig
|
||||||
|
import org.mariotaku.twidere.Constants
|
||||||
|
import org.mariotaku.twidere.TwidereConstants
|
||||||
|
import org.mariotaku.twidere.constant.loadItemLimitKey
|
||||||
|
import org.mariotaku.twidere.model.RefreshTaskParam
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.model.message.GetMessagesTaskEvent
|
||||||
|
import org.mariotaku.twidere.util.*
|
||||||
|
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||||
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 16/2/14.
|
||||||
|
*/
|
||||||
|
abstract class GetDirectMessagesTask(protected val context: Context) : AbstractTask<RefreshTaskParam,
|
||||||
|
List<TwitterWrapper.MessageListResponse>, () -> Unit>(), Constants {
|
||||||
|
@Inject
|
||||||
|
protected lateinit var errorInfoStore: ErrorInfoStore
|
||||||
|
@Inject
|
||||||
|
protected lateinit var preferences: SharedPreferencesWrapper
|
||||||
|
@Inject
|
||||||
|
protected lateinit var bus: Bus
|
||||||
|
|
||||||
|
init {
|
||||||
|
GeneralComponentHelper.build(context).inject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(MicroBlogException::class)
|
||||||
|
abstract fun getDirectMessages(twitter: MicroBlog, paging: Paging): ResponseList<DirectMessage>
|
||||||
|
|
||||||
|
protected abstract val databaseUri: Uri
|
||||||
|
|
||||||
|
protected abstract val isOutgoing: Boolean
|
||||||
|
|
||||||
|
public override fun doLongOperation(param: RefreshTaskParam): List<TwitterWrapper.MessageListResponse> {
|
||||||
|
val accountKeys = param.accountKeys
|
||||||
|
val sinceIds = param.sinceIds
|
||||||
|
val maxIds = param.maxIds
|
||||||
|
val result = ArrayList<TwitterWrapper.MessageListResponse>()
|
||||||
|
var idx = 0
|
||||||
|
val loadItemLimit = preferences[loadItemLimitKey]
|
||||||
|
for (accountKey in accountKeys) {
|
||||||
|
val twitter = MicroBlogAPIFactory.getInstance(context, accountKey) ?: continue
|
||||||
|
try {
|
||||||
|
val paging = Paging()
|
||||||
|
paging.setCount(loadItemLimit)
|
||||||
|
var maxId: String? = null
|
||||||
|
var sinceId: String? = null
|
||||||
|
if (maxIds != null && maxIds[idx] != null) {
|
||||||
|
maxId = maxIds[idx]
|
||||||
|
paging.setMaxId(maxId)
|
||||||
|
}
|
||||||
|
if (sinceIds != null && sinceIds[idx] != null) {
|
||||||
|
sinceId = sinceIds[idx]
|
||||||
|
val sinceIdLong = NumberUtils.toLong(sinceId, -1)
|
||||||
|
//TODO handle non-twitter case
|
||||||
|
if (sinceIdLong != -1L) {
|
||||||
|
paging.sinceId((sinceIdLong - 1).toString())
|
||||||
|
} else {
|
||||||
|
paging.sinceId(sinceId)
|
||||||
|
}
|
||||||
|
if (maxIds == null || sinceIds[idx] == null) {
|
||||||
|
paging.setLatestResults(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val messages = getDirectMessages(twitter, paging)
|
||||||
|
result.add(TwitterWrapper.MessageListResponse(accountKey, maxId, sinceId, messages))
|
||||||
|
storeMessages(accountKey, messages, isOutgoing, true)
|
||||||
|
errorInfoStore.remove(ErrorInfoStore.KEY_DIRECT_MESSAGES, accountKey)
|
||||||
|
} catch (e: MicroBlogException) {
|
||||||
|
if (e.errorCode == ErrorInfo.NO_DIRECT_MESSAGE_PERMISSION) {
|
||||||
|
errorInfoStore.put(ErrorInfoStore.KEY_DIRECT_MESSAGES, accountKey,
|
||||||
|
ErrorInfoStore.CODE_NO_DM_PERMISSION)
|
||||||
|
} else if (e.isCausedByNetworkIssue) {
|
||||||
|
errorInfoStore.put(ErrorInfoStore.KEY_DIRECT_MESSAGES, accountKey,
|
||||||
|
ErrorInfoStore.CODE_NETWORK_ERROR)
|
||||||
|
}
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.w(TwidereConstants.LOGTAG, e)
|
||||||
|
}
|
||||||
|
result.add(TwitterWrapper.MessageListResponse(accountKey, e))
|
||||||
|
}
|
||||||
|
|
||||||
|
idx++
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun storeMessages(accountKey: UserKey, messages: List<DirectMessage>?, isOutgoing: Boolean, notify: Boolean): Boolean {
|
||||||
|
if (messages == null) return true
|
||||||
|
val uri = databaseUri
|
||||||
|
val valuesArray = messages.map { ContentValuesCreator.createDirectMessage(it, accountKey, isOutgoing) }
|
||||||
|
|
||||||
|
// Delete all rows conflicting before new data inserted.
|
||||||
|
// final Expression deleteWhere = Expression.and(Expression.equals(DirectMessages.ACCOUNT_ID, accountKey),
|
||||||
|
// Expression.in(new Column(DirectMessages.MESSAGE_ID), new RawItemArray(messageIds)));
|
||||||
|
// final Uri deleteUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, false);
|
||||||
|
// mResolver.delete(deleteUri, deleteWhere.getSQL(), null);
|
||||||
|
|
||||||
|
|
||||||
|
// Insert previously fetched items.
|
||||||
|
val insertUri = UriUtils.appendQueryParameters(uri, TwidereConstants.QUERY_PARAM_NOTIFY, notify)
|
||||||
|
ContentResolverUtils.bulkInsert(context.contentResolver, insertUri, valuesArray)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeExecute() {
|
||||||
|
bus.post(GetMessagesTaskEvent(databaseUri, true, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterExecute(handler: (() -> Unit)?, result: List<TwitterWrapper.MessageListResponse>?) {
|
||||||
|
bus.post(GetMessagesTaskEvent(databaseUri, false, AsyncTwitterWrapper.getException(result)))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.mariotaku.twidere.task
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
|
||||||
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Trends
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 16/2/24.
|
||||||
|
*/
|
||||||
|
class GetLocalTrendsTask(context: Context, accountKey: UserKey, private val woeid: Int) : GetTrendsTask(context, accountKey) {
|
||||||
|
|
||||||
|
@Throws(MicroBlogException::class)
|
||||||
|
override fun getTrends(twitter: MicroBlog): List<Trends> {
|
||||||
|
return twitter.getLocationTrends(woeid)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val contentUri: Uri = CachedTrends.Local.CONTENT_URI
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.mariotaku.twidere.task
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.DirectMessage
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Paging
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.ResponseList
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2016/12/14.
|
||||||
|
*/
|
||||||
|
class GetReceivedDirectMessagesTask(context: Context) : GetDirectMessagesTask(context) {
|
||||||
|
|
||||||
|
@Throws(MicroBlogException::class)
|
||||||
|
override fun getDirectMessages(twitter: MicroBlog, paging: Paging): ResponseList<DirectMessage> {
|
||||||
|
return twitter.getDirectMessages(paging)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isOutgoing: Boolean = false
|
||||||
|
|
||||||
|
|
||||||
|
override val databaseUri: Uri = DirectMessages.Inbox.CONTENT_URI
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package org.mariotaku.twidere.task
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import org.mariotaku.abstask.library.AbstractTask
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.sqliteqb.library.Expression
|
||||||
|
import org.mariotaku.twidere.BuildConfig
|
||||||
|
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||||
|
import org.mariotaku.twidere.model.SingleResponse
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches
|
||||||
|
import org.mariotaku.twidere.util.ContentValuesCreator
|
||||||
|
import org.mariotaku.twidere.util.MicroBlogAPIFactory
|
||||||
|
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 16/2/13.
|
||||||
|
*/
|
||||||
|
class GetSavedSearchesTask(private val context: Context) : AbstractTask<Array<UserKey>, SingleResponse<Any>, Any>() {
|
||||||
|
|
||||||
|
public override fun doLongOperation(params: Array<UserKey>): SingleResponse<Any> {
|
||||||
|
val cr = context.contentResolver
|
||||||
|
for (accountKey in params) {
|
||||||
|
val twitter = MicroBlogAPIFactory.getInstance(context, accountKey) ?: continue
|
||||||
|
try {
|
||||||
|
val searches = twitter.savedSearches
|
||||||
|
val values = ContentValuesCreator.createSavedSearches(searches,
|
||||||
|
accountKey)
|
||||||
|
val where = Expression.equalsArgs(SavedSearches.ACCOUNT_KEY)
|
||||||
|
val whereArgs = arrayOf(accountKey.toString())
|
||||||
|
cr.delete(SavedSearches.CONTENT_URI, where.sql, whereArgs)
|
||||||
|
ContentResolverUtils.bulkInsert(cr, SavedSearches.CONTENT_URI, values)
|
||||||
|
} catch (e: MicroBlogException) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.w(LOGTAG, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return SingleResponse.getInstance()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.mariotaku.twidere.task
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.DirectMessage
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Paging
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.ResponseList
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2016/12/14.
|
||||||
|
*/
|
||||||
|
class GetSentDirectMessagesTask(context: Context) : GetDirectMessagesTask(context) {
|
||||||
|
|
||||||
|
@Throws(MicroBlogException::class)
|
||||||
|
override fun getDirectMessages(twitter: MicroBlog, paging: Paging): ResponseList<DirectMessage> {
|
||||||
|
return twitter.getSentDirectMessages(paging)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isOutgoing: Boolean = true
|
||||||
|
|
||||||
|
override val databaseUri: Uri = DirectMessages.Outbox.CONTENT_URI
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package org.mariotaku.twidere.task
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import com.squareup.otto.Bus
|
||||||
|
import org.mariotaku.abstask.library.AbstractTask
|
||||||
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Trends
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.model.message.TrendsRefreshedEvent
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore
|
||||||
|
import org.mariotaku.twidere.util.ContentValuesCreator
|
||||||
|
import org.mariotaku.twidere.util.MicroBlogAPIFactory
|
||||||
|
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||||
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 16/2/24.
|
||||||
|
*/
|
||||||
|
abstract class GetTrendsTask(private val context: Context, private val accountId: UserKey) : AbstractTask<Any, Any, Any>() {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var bus: Bus
|
||||||
|
|
||||||
|
init {
|
||||||
|
GeneralComponentHelper.build(context).inject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(MicroBlogException::class)
|
||||||
|
abstract fun getTrends(twitter: MicroBlog): List<Trends>
|
||||||
|
|
||||||
|
public override fun doLongOperation(param: Any): Any? {
|
||||||
|
val twitter = MicroBlogAPIFactory.getInstance(context, accountId) ?: return null
|
||||||
|
try {
|
||||||
|
val trends = getTrends(twitter)
|
||||||
|
storeTrends(context.contentResolver, contentUri, trends)
|
||||||
|
return null
|
||||||
|
} catch (e: MicroBlogException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterExecute(handler: Any?, result: Any?) {
|
||||||
|
bus.post(TrendsRefreshedEvent())
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract val contentUri: Uri
|
||||||
|
|
||||||
|
private fun storeTrends(cr: ContentResolver, uri: Uri, trendsList: List<Trends>) {
|
||||||
|
val hashtags = ArrayList<String>()
|
||||||
|
val hashtagValues = ArrayList<ContentValues>()
|
||||||
|
if (trendsList.isNotEmpty()) {
|
||||||
|
val valuesArray = ContentValuesCreator.createTrends(trendsList)
|
||||||
|
for (values in valuesArray) {
|
||||||
|
val hashtag = values.getAsString(TwidereDataStore.CachedTrends.NAME).replaceFirst("#".toRegex(), "")
|
||||||
|
if (hashtags.contains(hashtag)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hashtags.add(hashtag)
|
||||||
|
val hashtagValue = ContentValues()
|
||||||
|
hashtagValue.put(TwidereDataStore.CachedHashtags.NAME, hashtag)
|
||||||
|
hashtagValues.add(hashtagValue)
|
||||||
|
}
|
||||||
|
cr.delete(uri, null, null)
|
||||||
|
ContentResolverUtils.bulkInsert(cr, uri, valuesArray)
|
||||||
|
ContentResolverUtils.bulkDelete(cr, TwidereDataStore.CachedHashtags.CONTENT_URI, TwidereDataStore.CachedHashtags.NAME, hashtags, null)
|
||||||
|
ContentResolverUtils.bulkInsert(cr, TwidereDataStore.CachedHashtags.CONTENT_URI,
|
||||||
|
hashtagValues.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2015 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.task
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.media.MediaScannerConnection
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Environment
|
||||||
|
import android.widget.Toast
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
|
import org.mariotaku.twidere.provider.CacheProvider
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 15/12/28.
|
||||||
|
*/
|
||||||
|
class SaveMediaToGalleryTask(activity: Activity, source: Uri, destination: File, type: String) : ProgressSaveFileTask(activity, source, destination, CacheProvider.CacheFileTypeCallback(activity, type)) {
|
||||||
|
|
||||||
|
override fun onFileSaved(savedFile: File, mimeType: String?) {
|
||||||
|
val context = context ?: return
|
||||||
|
MediaScannerConnection.scanFile(context, arrayOf(savedFile.path),
|
||||||
|
arrayOf(mimeType), null)
|
||||||
|
Toast.makeText(context, R.string.saved_to_gallery, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFileSaveFailed() {
|
||||||
|
val context = context ?: return
|
||||||
|
Toast.makeText(context, R.string.error_occurred, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun create(activity: Activity, source: Uri,
|
||||||
|
@CacheProvider.Type type: String): SaveFileTask {
|
||||||
|
val pubDir: File
|
||||||
|
when (type) {
|
||||||
|
CacheProvider.Type.VIDEO -> {
|
||||||
|
pubDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
||||||
|
}
|
||||||
|
CacheProvider.Type.IMAGE -> {
|
||||||
|
pubDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
pubDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val saveDir = File(pubDir, "Twidere")
|
||||||
|
return SaveMediaToGalleryTask(activity, source, saveDir, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import android.support.annotation.UiThread
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.squareup.otto.Bus
|
import com.squareup.otto.Bus
|
||||||
import org.mariotaku.abstask.library.AbstractTask
|
import org.mariotaku.abstask.library.AbstractTask
|
||||||
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
import org.mariotaku.microblog.library.MicroBlog
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
import org.mariotaku.microblog.library.MicroBlogException
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
import org.mariotaku.microblog.library.twitter.model.Activity
|
import org.mariotaku.microblog.library.twitter.model.Activity
|
||||||
|
@ -19,7 +20,7 @@ import org.mariotaku.twidere.BuildConfig
|
||||||
import org.mariotaku.twidere.Constants
|
import org.mariotaku.twidere.Constants
|
||||||
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||||
import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_NOTIFY
|
import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_NOTIFY
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_LOAD_ITEM_LIMIT
|
import org.mariotaku.twidere.constant.loadItemLimitKey
|
||||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
import org.mariotaku.twidere.model.RefreshTaskParam
|
import org.mariotaku.twidere.model.RefreshTaskParam
|
||||||
|
@ -37,9 +38,9 @@ import javax.inject.Inject
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 16/1/4.
|
* Created by mariotaku on 16/1/4.
|
||||||
*/
|
*/
|
||||||
abstract class GetActivitiesTask(protected val context: Context) : AbstractTask<RefreshTaskParam, Any, Any>(), Constants {
|
abstract class GetActivitiesTask(protected val context: Context) : AbstractTask<RefreshTaskParam, Any, () -> Unit>(), Constants {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var preferences: SharedPreferencesWrapper
|
lateinit var preferences: KPreferences
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var bus: Bus
|
lateinit var bus: Bus
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -60,12 +61,11 @@ abstract class GetActivitiesTask(protected val context: Context) : AbstractTask<
|
||||||
val maxSortIds = param.maxSortIds
|
val maxSortIds = param.maxSortIds
|
||||||
val sinceIds = param.sinceIds
|
val sinceIds = param.sinceIds
|
||||||
val cr = context.contentResolver
|
val cr = context.contentResolver
|
||||||
val loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT)
|
val loadItemLimit = preferences[loadItemLimitKey]
|
||||||
var saveReadPosition = false
|
var saveReadPosition = false
|
||||||
for (i in accountIds.indices) {
|
for (i in accountIds.indices) {
|
||||||
val accountKey = accountIds[i]
|
val accountKey = accountIds[i]
|
||||||
val noItemsBefore = DataStoreUtils.getActivitiesCount(context, contentUri,
|
val noItemsBefore = DataStoreUtils.getActivitiesCount(context, contentUri, accountKey) <= 0
|
||||||
accountKey) <= 0
|
|
||||||
val credentials = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) ?: continue
|
val credentials = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) ?: continue
|
||||||
val microBlog = credentials.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
|
val microBlog = credentials.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
|
||||||
val paging = Paging()
|
val paging = Paging()
|
||||||
|
@ -123,7 +123,7 @@ abstract class GetActivitiesTask(protected val context: Context) : AbstractTask<
|
||||||
private fun storeActivities(cr: ContentResolver, loadItemLimit: Int, details: AccountDetails,
|
private fun storeActivities(cr: ContentResolver, loadItemLimit: Int, details: AccountDetails,
|
||||||
noItemsBefore: Boolean, activities: ResponseList<Activity>,
|
noItemsBefore: Boolean, activities: ResponseList<Activity>,
|
||||||
sinceId: String?, maxId: String?, notify: Boolean) {
|
sinceId: String?, maxId: String?, notify: Boolean) {
|
||||||
val deleteBound = LongArray(2, { return@LongArray -1 })
|
val deleteBound = LongArray(2) { -1 }
|
||||||
val valuesList = ArrayList<ContentValues>()
|
val valuesList = ArrayList<ContentValues>()
|
||||||
var minIdx = -1
|
var minIdx = -1
|
||||||
var minPositionKey: Long = -1
|
var minPositionKey: Long = -1
|
||||||
|
@ -190,15 +190,12 @@ abstract class GetActivitiesTask(protected val context: Context) : AbstractTask<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun saveReadPosition(accountKey: UserKey,
|
protected abstract fun saveReadPosition(accountKey: UserKey, details: AccountDetails, twitter: MicroBlog)
|
||||||
details: AccountDetails, twitter: MicroBlog)
|
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
protected abstract fun getActivities(twitter: MicroBlog,
|
protected abstract fun getActivities(twitter: MicroBlog, details: AccountDetails, paging: Paging): ResponseList<Activity>
|
||||||
details: AccountDetails,
|
|
||||||
paging: Paging): ResponseList<Activity>
|
|
||||||
|
|
||||||
public override fun afterExecute(handler: Any?, result: Any?) {
|
public override fun afterExecute(handler: (() -> Unit)?, result: Any?) {
|
||||||
context.contentResolver.notifyChange(contentUri, null)
|
context.contentResolver.notifyChange(contentUri, null)
|
||||||
bus.post(GetActivitiesTaskEvent(contentUri, false, null))
|
bus.post(GetActivitiesTaskEvent(contentUri, false, null))
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,8 @@ import javax.inject.Inject
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 16/1/2.
|
* Created by mariotaku on 16/1/2.
|
||||||
*/
|
*/
|
||||||
abstract class GetStatusesTask(protected val context: Context) : AbstractTask<RefreshTaskParam, List<TwitterWrapper.StatusListResponse>, Any>(), Constants {
|
abstract class GetStatusesTask(protected val context: Context) :
|
||||||
|
AbstractTask<RefreshTaskParam, List<TwitterWrapper.StatusListResponse>, () -> Unit>(), Constants {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var preferences: KPreferences
|
lateinit var preferences: KPreferences
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -68,9 +69,10 @@ abstract class GetStatusesTask(protected val context: Context) : AbstractTask<Re
|
||||||
|
|
||||||
protected abstract val timelineType: String
|
protected abstract val timelineType: String
|
||||||
|
|
||||||
public override fun afterExecute(handler: Any?, result: List<TwitterWrapper.StatusListResponse>?) {
|
public override fun afterExecute(handler: (() -> Unit)?, result: List<TwitterWrapper.StatusListResponse>?) {
|
||||||
context.contentResolver.notifyChange(contentUri, null)
|
context.contentResolver.notifyChange(contentUri, null)
|
||||||
bus.post(GetStatusesTaskEvent(contentUri, false, AsyncTwitterWrapper.getException(result)))
|
bus.post(GetStatusesTaskEvent(contentUri, false, AsyncTwitterWrapper.getException(result)))
|
||||||
|
handler?.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeExecute() {
|
override fun beforeExecute() {
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.mariotaku.twidere.preference.KeyboardShortcutPreference
|
||||||
import org.mariotaku.twidere.provider.CacheProvider
|
import org.mariotaku.twidere.provider.CacheProvider
|
||||||
import org.mariotaku.twidere.provider.TwidereDataProvider
|
import org.mariotaku.twidere.provider.TwidereDataProvider
|
||||||
import org.mariotaku.twidere.service.BackgroundOperationService
|
import org.mariotaku.twidere.service.BackgroundOperationService
|
||||||
|
import org.mariotaku.twidere.service.JobRefreshService
|
||||||
import org.mariotaku.twidere.service.RefreshService
|
import org.mariotaku.twidere.service.RefreshService
|
||||||
import org.mariotaku.twidere.task.*
|
import org.mariotaku.twidere.task.*
|
||||||
import org.mariotaku.twidere.task.twitter.GetActivitiesTask
|
import org.mariotaku.twidere.task.twitter.GetActivitiesTask
|
||||||
|
@ -110,6 +111,8 @@ interface GeneralComponent {
|
||||||
|
|
||||||
fun inject(task: GetStatusesTask)
|
fun inject(task: GetStatusesTask)
|
||||||
|
|
||||||
|
fun inject(service: JobRefreshService)
|
||||||
|
|
||||||
fun inject(task: GetActivitiesTask)
|
fun inject(task: GetActivitiesTask)
|
||||||
|
|
||||||
fun inject(task: GetDirectMessagesTask)
|
fun inject(task: GetDirectMessagesTask)
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
android:title="@string/direct_messages"/>
|
android:title="@string/direct_messages"/>
|
||||||
<item
|
<item
|
||||||
android:id="@id/favorites"
|
android:id="@id/favorites"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@drawable/ic_action_star"
|
||||||
|
android:title="@string/favorites"
|
||||||
|
android:visible="false"/>
|
||||||
|
<item
|
||||||
|
android:id="@id/likes"
|
||||||
android:icon="@drawable/ic_action_heart"
|
android:icon="@drawable/ic_action_heart"
|
||||||
android:title="@string/likes"/>
|
android:title="@string/likes"/>
|
||||||
<item
|
<item
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<bool name="use_job_refresh_service">true</bool>
|
||||||
|
<bool name="use_legacy_refresh_service">false</bool>
|
||||||
|
</resources>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<bool name="is_debug">false</bool>
|
||||||
|
<bool name="use_job_refresh_service">false</bool>
|
||||||
|
<bool name="use_legacy_refresh_service">true</bool>
|
||||||
|
</resources>
|
|
@ -6,6 +6,5 @@
|
||||||
<string name="default_profile_image_style">round</string>
|
<string name="default_profile_image_style">round</string>
|
||||||
<integer name="default_tab_columns">1</integer>
|
<integer name="default_tab_columns">1</integer>
|
||||||
<integer name="min_database_item_limit">50</integer>
|
<integer name="min_database_item_limit">50</integer>
|
||||||
<bool name="is_debug">false</bool>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -57,6 +57,7 @@
|
||||||
<item name="delete_from_list" type="id"/>
|
<item name="delete_from_list" type="id"/>
|
||||||
<item name="statuses" type="id"/>
|
<item name="statuses" type="id"/>
|
||||||
<item name="favorites" type="id"/>
|
<item name="favorites" type="id"/>
|
||||||
|
<item name="likes" type="id"/>
|
||||||
<item name="lists" type="id"/>
|
<item name="lists" type="id"/>
|
||||||
<item name="groups" type="id"/>
|
<item name="groups" type="id"/>
|
||||||
<item name="public_timeline" type="id"/>
|
<item name="public_timeline" type="id"/>
|
||||||
|
|
Loading…
Reference in New Issue