mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-17 04:00:48 +01:00
fixed action mode position
added notice for loaded replies
This commit is contained in:
parent
3e9e91e871
commit
c245c05c56
@ -136,6 +136,7 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
||||
String QUERY_PARAM_EXTRA_ID = "extra_id";
|
||||
String QUERY_PARAM_TIMESTAMP = "timestamp";
|
||||
String QUERY_PARAM_FROM_NOTIFICATION = "from_notification";
|
||||
String QUERY_PARAM_NOTIFICATION_TYPE = "notification_type";
|
||||
|
||||
String DEFAULT_PROTOCOL = PROTOCOL_HTTPS;
|
||||
|
||||
|
@ -220,5 +220,6 @@ public interface IntentConstants {
|
||||
String EXTRA_ACTIVITY_OPTIONS = "activity_options";
|
||||
String EXTRA_MAKE_GAP = "make_gap";
|
||||
String EXTRA_QUOTE_ORIGINAL_STATUS = "quote_original_status";
|
||||
String EXTRA_KEY = "key";
|
||||
|
||||
}
|
||||
|
@ -64,6 +64,8 @@
|
||||
android:name=".app.TwidereApplication"
|
||||
android:allowBackup="true"
|
||||
android:backupAgent=".backup.TwidereBackupAgentHelper"
|
||||
android:description="@string/app_description"
|
||||
android:fullBackupContent="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
|
@ -30,6 +30,8 @@ import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.mariotaku.twidere.activity.iface.IAppCompatActivity;
|
||||
|
||||
/**
|
||||
* A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
|
||||
* to be used with AppCompat.
|
||||
@ -37,9 +39,11 @@ import android.view.ViewGroup;
|
||||
* This technique can be used with an {@link android.app.Activity} class, not just
|
||||
* {@link android.preference.PreferenceActivity}.
|
||||
*/
|
||||
public abstract class AppCompatPreferenceActivity extends PreferenceActivity implements AppCompatCallback {
|
||||
public abstract class AppCompatPreferenceActivity extends PreferenceActivity
|
||||
implements AppCompatCallback, IAppCompatActivity {
|
||||
private AppCompatDelegate mDelegate;
|
||||
|
||||
@Override
|
||||
public ActionBar getSupportActionBar() {
|
||||
return getDelegate().getSupportActionBar();
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ public class SettingsActivity extends BasePreferenceActivity {
|
||||
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
|
||||
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
|
||||
if (ACTION_NAVIGATION_BACK.equals(action)) {
|
||||
navigateUp();
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
|
||||
@ -286,7 +286,7 @@ public class SettingsActivity extends BasePreferenceActivity {
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
navigateUp();
|
||||
onBackPressed();
|
||||
}
|
||||
});
|
||||
|
||||
@ -332,15 +332,11 @@ public class SettingsActivity extends BasePreferenceActivity {
|
||||
return mShouldNotifyChange;
|
||||
}
|
||||
|
||||
private void navigateUp() {
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mTwidereActionModeForChildListener.finishExisting()) {
|
||||
return;
|
||||
}
|
||||
onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (isTopSettings() && shouldNotifyChange()) {
|
||||
final RestartConfirmDialogFragment df = new RestartConfirmDialogFragment();
|
||||
df.show(getFragmentManager().beginTransaction(), "restart_confirm");
|
||||
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.activity.iface;
|
||||
|
||||
import android.support.v7.app.ActionBar;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/10/12.
|
||||
*/
|
||||
public interface IAppCompatActivity {
|
||||
ActionBar getSupportActionBar();
|
||||
}
|
@ -288,7 +288,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
|
||||
super.onStart();
|
||||
mImageUploaderUsed = !ServicePickerPreference.isNoneValue(mPreferences.getString(KEY_MEDIA_UPLOADER, null));
|
||||
mStatusShortenerUsed = !ServicePickerPreference.isNoneValue(mPreferences.getString(KEY_STATUS_SHORTENER, null));
|
||||
startLocationUpdateIfEnabled();
|
||||
requestOrUpdateLocation();
|
||||
setMenu();
|
||||
updateTextCount();
|
||||
final int textSize = mPreferences.getInt(KEY_TEXT_SIZE, Utils.getDefaultTextSize(this));
|
||||
@ -351,6 +351,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
|
||||
contentView.getPaddingRight(), contentView.getPaddingBottom());
|
||||
return true;
|
||||
}
|
||||
// Offset content view
|
||||
final int statusBarHeight = rect.top;
|
||||
contentView.getWindowVisibleDisplayFrame(rect);
|
||||
final int paddingTop = statusBarHeight + actionBarHeight - rect.top;
|
||||
@ -580,6 +581,13 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionModeStarted(ActionMode mode) {
|
||||
super.onActionModeStarted(mode);
|
||||
ThemeUtils.applyColorFilterToMenuIcon(mode.getMenu(), ThemeUtils.getContrastActionBarItemColor(this),
|
||||
0, 0, Mode.MULTIPLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -28,7 +28,9 @@ import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.fragment.support.FileSelectorDialogFragment;
|
||||
import org.mariotaku.twidere.util.PermissionUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
@ -125,6 +127,7 @@ public class FileSelectorActivity extends BaseSupportDialogActivity implements F
|
||||
|
||||
private void finishWithDeniedMessage() {
|
||||
if (isFinishing()) return;
|
||||
Toast.makeText(this, R.string.select_file_no_storage_permission_message, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
|
@ -30,13 +30,15 @@ import android.view.View;
|
||||
|
||||
import org.mariotaku.twidere.BuildConfig;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.activity.iface.IAppCompatActivity;
|
||||
import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
||||
import org.mariotaku.twidere.util.StrictModeUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.ShapedImageView.ShapeStyle;
|
||||
|
||||
public abstract class ThemedAppCompatActivity extends AppCompatActivity implements Constants, IThemedActivity {
|
||||
public abstract class ThemedAppCompatActivity extends AppCompatActivity implements Constants,
|
||||
IThemedActivity, IAppCompatActivity {
|
||||
|
||||
private int mCurrentThemeResource, mCurrentThemeColor, mCurrentThemeBackgroundAlpha;
|
||||
@ShapeStyle
|
||||
|
@ -36,6 +36,7 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.dagger.ApplicationModule;
|
||||
import org.mariotaku.twidere.util.dagger.DaggerGeneralComponent;
|
||||
@ -44,11 +45,19 @@ import javax.inject.Inject;
|
||||
|
||||
public class BaseListFragment extends ListFragment implements Constants, OnScrollListener, RefreshScrollTopInterface {
|
||||
|
||||
@Inject
|
||||
protected AsyncTwitterWrapper mTwitterWrapper;
|
||||
@Inject
|
||||
protected SharedPreferencesWrapper mPreferences;
|
||||
private boolean mActivityFirstCreated;
|
||||
private boolean mIsInstanceStateSaved;
|
||||
|
||||
private boolean mReachedBottom, mNotReachedBottomBefore = true;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
DaggerGeneralComponent.builder().applicationModule(ApplicationModule.get(activity)).build().inject(this);
|
||||
}
|
||||
|
||||
public final TwidereApplication getApplication() {
|
||||
return TwidereApplication.getInstance(getActivity());
|
||||
@ -103,15 +112,6 @@ public class BaseListFragment extends ListFragment implements Constants, OnScrol
|
||||
lv.setOnScrollListener(this);
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected AsyncTwitterWrapper mTwitterWrapper;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
DaggerGeneralComponent.builder().applicationModule(ApplicationModule.get(context)).build().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -50,6 +50,7 @@ import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.ArrayAdapter;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
@ -62,15 +63,18 @@ import static android.text.TextUtils.isEmpty;
|
||||
public class HostMappingsListFragment extends BaseListFragment implements MultiChoiceModeListener,
|
||||
OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final String EXTRA_EDIT_MODE = "edit_mode";
|
||||
private static final String EXTRA_HOST = "host";
|
||||
private static final String EXTRA_ADDRESS = "address";
|
||||
private static final String EXTRA_EXCLUDED = "excluded";
|
||||
|
||||
private ListView mListView;
|
||||
private HostMappingAdapter mAdapter;
|
||||
private SharedPreferences mPreferences;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
mPreferences = getSharedPreferences(HOST_MAPPING_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mPreferences.registerOnSharedPreferenceChangeListener(this);
|
||||
mAdapter = new HostMappingAdapter(getActivity());
|
||||
setListAdapter(mAdapter);
|
||||
@ -126,13 +130,28 @@ public class HostMappingsListFragment extends BaseListFragment implements MultiC
|
||||
inflater.inflate(R.menu.menu_host_mapping, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
final String host = mAdapter.getItem(position);
|
||||
final String address = mAdapter.getAddress(host);
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(EXTRA_HOST, host);
|
||||
args.putString(EXTRA_ADDRESS, address);
|
||||
args.putBoolean(EXTRA_EXCLUDED, StringUtils.equals(host, address));
|
||||
args.putBoolean(EXTRA_EDIT_MODE, true);
|
||||
final DialogFragment df = new AddMappingDialogFragment();
|
||||
df.setArguments(args);
|
||||
df.show(getFragmentManager(), "add_mapping");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.add:
|
||||
case R.id.add: {
|
||||
final DialogFragment df = new AddMappingDialogFragment();
|
||||
df.show(getFragmentManager(), "add_mapping");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@ -162,9 +181,6 @@ public class HostMappingsListFragment extends BaseListFragment implements MultiC
|
||||
public static class AddMappingDialogFragment extends BaseDialogFragment implements OnClickListener,
|
||||
OnShowListener, TextWatcher, OnCheckedChangeListener {
|
||||
|
||||
private static final String EXTRA_HOST = "host";
|
||||
private static final String EXTRA_ADDRESS = "address";
|
||||
private static final String EXTRA_EXCLUDED = "excluded";
|
||||
|
||||
private EditText mEditHost, mEditAddress;
|
||||
private CheckBox mCheckExclude;
|
||||
@ -222,7 +238,8 @@ public class HostMappingsListFragment extends BaseListFragment implements MultiC
|
||||
mEditAddress.addTextChangedListener(this);
|
||||
mCheckExclude.setOnCheckedChangeListener(this);
|
||||
final Bundle args = getArguments();
|
||||
if (savedInstanceState == null && args != null) {
|
||||
mEditHost.setEnabled(!args.getBoolean(EXTRA_EDIT_MODE, false));
|
||||
if (savedInstanceState == null) {
|
||||
mEditHost.setText(args.getCharSequence(EXTRA_HOST));
|
||||
mEditAddress.setText(args.getCharSequence(EXTRA_ADDRESS));
|
||||
mCheckExclude.setChecked(args.getBoolean(EXTRA_EXCLUDED));
|
||||
@ -264,11 +281,11 @@ public class HostMappingsListFragment extends BaseListFragment implements MultiC
|
||||
|
||||
static class HostMappingAdapter extends ArrayAdapter<String> {
|
||||
|
||||
private final SharedPreferences mPreferences;
|
||||
private final SharedPreferences mHostMapping;
|
||||
|
||||
public HostMappingAdapter(final Context context) {
|
||||
super(context, android.R.layout.simple_list_item_activated_2);
|
||||
mPreferences = context.getSharedPreferences(HOST_MAPPING_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mHostMapping = context.getSharedPreferences(HOST_MAPPING_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -278,8 +295,8 @@ public class HostMappingsListFragment extends BaseListFragment implements MultiC
|
||||
final TextView text2 = (TextView) view.findViewById(android.R.id.text2);
|
||||
final String key = getItem(position);
|
||||
text1.setText(key);
|
||||
final String value = mPreferences.getString(key, null);
|
||||
if (key.equals(value)) {
|
||||
final String value = getAddress(key);
|
||||
if (StringUtils.equals(key, value)) {
|
||||
text2.setText(R.string.excluded);
|
||||
} else {
|
||||
text2.setText(value);
|
||||
@ -289,10 +306,13 @@ public class HostMappingsListFragment extends BaseListFragment implements MultiC
|
||||
|
||||
public void reload() {
|
||||
clear();
|
||||
final Map<String, ?> all = mPreferences.getAll();
|
||||
final Map<String, ?> all = mHostMapping.getAll();
|
||||
addAll(all.keySet());
|
||||
}
|
||||
|
||||
public String getAddress(String key) {
|
||||
return mHostMapping.getString(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ public abstract class AbsContentListViewFragment<A extends ListAdapter> extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
setRefreshEnabled(false);
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ public abstract class AbsContentRecyclerViewFragment<A extends LoadMoreSupportAd
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
setLoadMoreIndicatorVisible(true);
|
||||
setRefreshEnabled(false);
|
||||
}
|
||||
|
@ -217,8 +217,10 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment<List<Pa
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
super.onLoadMoreContents();
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
if (fromStart) return;
|
||||
//noinspection ConstantConditions
|
||||
super.onLoadMoreContents(fromStart);
|
||||
AsyncManager.runBackgroundTask(new TaskRunnable<Object, long[][], CursorStatusesFragment>() {
|
||||
@Override
|
||||
public long[][] doLongOperation(Object o) throws InterruptedException {
|
||||
|
@ -67,8 +67,10 @@ public abstract class CursorSupportUsersListFragment extends ParcelableUsersFrag
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
super.onLoadMoreContents();
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
if (fromStart) return;
|
||||
//noinspection ConstantConditions
|
||||
super.onLoadMoreContents(fromStart);
|
||||
final Bundle loaderArgs = new Bundle(getArguments());
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||
loaderArgs.putLong(EXTRA_NEXT_CURSOR, mNextCursor);
|
||||
|
@ -59,7 +59,6 @@ import org.mariotaku.twidere.util.AsyncTaskUtils;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
import org.mariotaku.twidere.util.RecyclerViewNavigationHelper;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
|
||||
@ -69,8 +68,6 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.openMessageConversation;
|
||||
|
||||
public class DirectMessagesFragment extends AbsContentRecyclerViewFragment<MessageEntriesAdapter>
|
||||
@ -95,7 +92,7 @@ public class DirectMessagesFragment extends AbsContentRecyclerViewFragment<Messa
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
loadMoreMessages();
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public abstract class ParcelableActivitiesFragment extends AbsActivitiesFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
final IActivitiesAdapter<List<ParcelableActivity>> adapter = getAdapter();
|
||||
final long[] maxIds = new long[]{adapter.getActivity(adapter.getActivityCount() - 1).min_position};
|
||||
getActivities(getAccountIds(), maxIds, null);
|
||||
|
@ -47,19 +47,19 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
|
||||
private long mLastId;
|
||||
|
||||
public final void deleteStatus(final long statusId) {
|
||||
final List<ParcelableStatus> data = getAdapterData();
|
||||
if (statusId <= 0 || data == null) return;
|
||||
final List<ParcelableStatus> list = getAdapterData();
|
||||
if (statusId <= 0 || list == null) return;
|
||||
final Set<ParcelableStatus> dataToRemove = new HashSet<>();
|
||||
for (int i = 0, j = data.size(); i < j; i++) {
|
||||
final ParcelableStatus status = data.get(i);
|
||||
for (int i = 0, j = list.size(); i < j; i++) {
|
||||
final ParcelableStatus status = list.get(i);
|
||||
if (status.id == statusId || status.retweet_id > 0 && status.retweet_id == statusId) {
|
||||
dataToRemove.add(status);
|
||||
} else if (status.my_retweet_id == statusId) {
|
||||
data.set(i, new ParcelableStatus(status, -1, status.retweet_count - 1));
|
||||
list.set(i, new ParcelableStatus(status, -1, status.retweet_count - 1));
|
||||
}
|
||||
}
|
||||
data.removeAll(dataToRemove);
|
||||
setAdapterData(data);
|
||||
list.removeAll(dataToRemove);
|
||||
setAdapterData(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,9 +90,9 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasMoreData(List<ParcelableStatus> data) {
|
||||
if (data == null || data.isEmpty()) return false;
|
||||
return (mLastId != (mLastId = data.get(data.size() - 1).id));
|
||||
protected boolean hasMoreData(List<ParcelableStatus> list) {
|
||||
if (list == null || list.isEmpty()) return false;
|
||||
return (mLastId != (mLastId = list.get(list.size() - 1).id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -121,8 +121,10 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
|
||||
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
super.onLoadMoreContents();
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
if (fromStart) return;
|
||||
//noinspection ConstantConditions
|
||||
super.onLoadMoreContents(fromStart);
|
||||
final IStatusesAdapter<List<ParcelableStatus>> adapter = getAdapter();
|
||||
final long[] maxIds = new long[]{adapter.getStatusId(adapter.getStatusesCount() - 1)};
|
||||
getStatuses(null, maxIds, null);
|
||||
@ -130,7 +132,7 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
|
||||
|
||||
public final void replaceStatus(final ParcelableStatus status) {
|
||||
final List<ParcelableStatus> data = getAdapterData();
|
||||
if (status == null || data == null) return;
|
||||
if (status == null || data == null || data.isEmpty()) return;
|
||||
for (int i = 0, j = data.size(); i < j; i++) {
|
||||
if (status.equals(data.get(i))) {
|
||||
data.set(i, status);
|
||||
|
@ -63,8 +63,10 @@ public abstract class ParcelableUserListsFragment extends AbsUserListsFragment<L
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
super.onLoadMoreContents();
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
if (fromStart) return;
|
||||
//noinspection ConstantConditions
|
||||
super.onLoadMoreContents(fromStart);
|
||||
final Bundle loaderArgs = new Bundle(getArguments());
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||
loaderArgs.putLong(EXTRA_NEXT_CURSOR, getNextCursor());
|
||||
|
@ -58,8 +58,10 @@ public class SearchUsersFragment extends ParcelableUsersFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
super.onLoadMoreContents();
|
||||
public void onLoadMoreContents(boolean fromStart) {
|
||||
if (fromStart) return;
|
||||
//noinspection ConstantConditions
|
||||
super.onLoadMoreContents(fromStart);
|
||||
final Bundle loaderArgs = new Bundle(getArguments());
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||
loaderArgs.putInt(EXTRA_PAGE, mPage + 1);
|
||||
|
@ -54,9 +54,13 @@ import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.RecyclerView.LayoutParams;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.ArrowKeyMovementMethod;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
@ -180,11 +184,37 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<ParcelableStatus>> loader, List<ParcelableStatus> data) {
|
||||
mStatusAdapter.setRepliesLoading(false);
|
||||
mStatusAdapter.updateItemDecoration();
|
||||
final Pair<Long, Integer> readPosition = saveReadPosition();
|
||||
setReplies(data);
|
||||
restoreReadPosition(readPosition);
|
||||
final ParcelableCredentials account = mStatusAdapter.getStatusAccount();
|
||||
if (Utils.hasOfficialAPIAccess(loader.getContext(), mPreferences, account)) {
|
||||
mStatusAdapter.setReplyError(null);
|
||||
} else {
|
||||
final SpannableStringBuilder error = SpannableStringBuilder.valueOf(Html.fromHtml(getString(R.string.cant_load_all_replies_message)));
|
||||
ClickableSpan dialogSpan = null;
|
||||
for (URLSpan span : error.getSpans(0, error.length(), URLSpan.class)) {
|
||||
if ("#dialog".equals(span.getURL())) {
|
||||
dialogSpan = span;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dialogSpan != null) {
|
||||
final int spanStart = error.getSpanStart(dialogSpan), spanEnd = error.getSpanEnd(dialogSpan);
|
||||
error.removeSpan(dialogSpan);
|
||||
error.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity == null) return;
|
||||
SupportMessageDialogFragment.show(activity,
|
||||
getString(R.string.cant_load_all_replies_explanation),
|
||||
"cant_load_all_replies_explanation");
|
||||
}
|
||||
}, spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
}
|
||||
mStatusAdapter.setReplyError(error);
|
||||
}
|
||||
mStatusAdapter.setRepliesLoading(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -492,21 +522,25 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
|
||||
private void restoreReadPosition(@Nullable Pair<Long, Integer> position) {
|
||||
if (position == null) return;
|
||||
final int adapterPosition = mStatusAdapter.findPositionById(position.first);
|
||||
if (adapterPosition == RecyclerView.NO_POSITION) return;
|
||||
// FIXME We don't know why we need to -1 here, but only -1 works.
|
||||
final int adapterPosition = mStatusAdapter.findPositionById(position.first) - 1;
|
||||
if (adapterPosition < 0) return;
|
||||
//TODO maintain read position
|
||||
mLayoutManager.scrollToPositionWithOffset(adapterPosition, position.second);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Pair<Long, Integer> saveReadPosition() {
|
||||
final int position = mLayoutManager.findFirstVisibleItemPosition();
|
||||
if (position == RecyclerView.NO_POSITION) return null;
|
||||
if (position < 0) return null;
|
||||
final int itemType = mStatusAdapter.getItemType(position);
|
||||
long itemId = mStatusAdapter.getItemId(position);
|
||||
final View positionView;
|
||||
if (itemId == StatusAdapter.VIEW_TYPE_CONVERSATION_LOAD_INDICATOR) {
|
||||
if (itemType == StatusAdapter.ITEM_IDX_CONVERSATION_LOAD_MORE) {
|
||||
// Should be next item
|
||||
positionView = mLayoutManager.findViewByPosition(position + 1);
|
||||
itemId = mStatusAdapter.getItemId(position + 1);
|
||||
final int statusPosition = mStatusAdapter.getFirstPositionOfItem(StatusAdapter.ITEM_IDX_STATUS);
|
||||
positionView = mLayoutManager.findViewByPosition(statusPosition);
|
||||
itemId = mStatusAdapter.getItemId(statusPosition);
|
||||
} else {
|
||||
positionView = mLayoutManager.findViewByPosition(position);
|
||||
}
|
||||
@ -517,25 +551,26 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
public void onLoadFinished(final Loader<SingleResponse<ParcelableStatus>> loader,
|
||||
final SingleResponse<ParcelableStatus> data) {
|
||||
if (data.hasData()) {
|
||||
final int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
|
||||
final Pair<Long, Integer> readPosition = saveReadPosition();
|
||||
final ParcelableStatus status = data.getData();
|
||||
final Bundle dataExtra = data.getExtras();
|
||||
final ParcelableCredentials credentials = dataExtra.getParcelable(EXTRA_ACCOUNT);
|
||||
if (mStatusAdapter.setStatus(status, credentials)) {
|
||||
mLayoutManager.scrollToPositionWithOffset(1, 0);
|
||||
mStatusAdapter.setConversation(null);
|
||||
mStatusAdapter.setReplies(null);
|
||||
loadReplies(status);
|
||||
loadConversation(status);
|
||||
loadReplies(status);
|
||||
|
||||
final int position = mStatusAdapter.getFirstPositionOfItem(StatusAdapter.ITEM_IDX_STATUS);
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
mLayoutManager.scrollToPositionWithOffset(position, 0);
|
||||
}
|
||||
|
||||
final TweetEvent event = TweetEvent.create(getActivity(), status, TimelineType.OTHER);
|
||||
event.setAction(TweetEvent.Action.OPEN);
|
||||
mStatusEvent = event;
|
||||
} else if (firstVisibleItemPosition >= 0) {
|
||||
final long itemId = mStatusAdapter.getItemId(firstVisibleItemPosition);
|
||||
final View firstChild = mLayoutManager.getChildAt(0);
|
||||
final int top = firstChild != null ? firstChild.getTop() : 0;
|
||||
final int position = mStatusAdapter.findPositionById(itemId);
|
||||
mLayoutManager.scrollToPositionWithOffset(position, top);
|
||||
} else if (readPosition != null) {
|
||||
restoreReadPosition(readPosition);
|
||||
}
|
||||
setState(STATE_LOADED);
|
||||
} else {
|
||||
@ -551,15 +586,10 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
}
|
||||
|
||||
private void setReplies(List<ParcelableStatus> data) {
|
||||
if (mLayoutManager.getChildCount() != 0) {
|
||||
final long itemId = mStatusAdapter.getItemId(mLayoutManager.findFirstVisibleItemPosition());
|
||||
final int top = mLayoutManager.getChildAt(0).getTop();
|
||||
mStatusAdapter.setReplies(data);
|
||||
final int position = mStatusAdapter.findPositionById(itemId);
|
||||
mLayoutManager.scrollToPositionWithOffset(position, top);
|
||||
} else {
|
||||
mStatusAdapter.setReplies(data);
|
||||
}
|
||||
final Pair<Long, Integer> readPosition = saveReadPosition();
|
||||
mStatusAdapter.setReplies(data);
|
||||
//TODO maintain read position
|
||||
restoreReadPosition(readPosition);
|
||||
}
|
||||
|
||||
private void setState(int state) {
|
||||
@ -576,6 +606,10 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
HotMobiLogger.getInstance(getActivity()).log(event.getAccountId(), event);
|
||||
}
|
||||
|
||||
private void showConversationError(Exception exception) {
|
||||
|
||||
}
|
||||
|
||||
private static class DetailStatusViewHolder extends ViewHolder implements OnClickListener,
|
||||
ActionMenuView.OnMenuItemClickListener {
|
||||
|
||||
@ -977,12 +1011,15 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final ListResponse<ParcelableStatus> data) {
|
||||
fragment.getAdapter().setConversationsLoading(false);
|
||||
final StatusAdapter adapter = fragment.getAdapter();
|
||||
if (data.hasData()) {
|
||||
fragment.setConversation(data.getData());
|
||||
} else if (data.hasException()) {
|
||||
fragment.showConversationError(data.getException());
|
||||
} else {
|
||||
Utils.showErrorMessage(context, context.getString(R.string.action_getting_status), data.getException(), true);
|
||||
}
|
||||
adapter.setConversationsLoading(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1042,14 +1079,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
private static final int VIEW_TYPE_DETAIL_STATUS = 1;
|
||||
private static final int VIEW_TYPE_CONVERSATION_LOAD_INDICATOR = 2;
|
||||
private static final int VIEW_TYPE_REPLIES_LOAD_INDICATOR = 3;
|
||||
private static final int VIEW_TYPE_SPACE = 4;
|
||||
|
||||
private final Context mContext;
|
||||
private final StatusFragment mFragment;
|
||||
private final LayoutInflater mInflater;
|
||||
private final MediaLoadingHandler mMediaLoadingHandler;
|
||||
private final TwidereLinkify mTwidereLinkify;
|
||||
|
||||
private static final int VIEW_TYPE_REPLY_ERROR = 4;
|
||||
private static final int VIEW_TYPE_SPACE = 5;
|
||||
private static final int ITEM_IDX_CONVERSATION_ERROR = 0;
|
||||
private static final int ITEM_IDX_CONVERSATION_LOAD_MORE = 1;
|
||||
private static final int ITEM_IDX_CONVERSATION = 2;
|
||||
@ -1059,7 +1090,11 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
private static final int ITEM_IDX_REPLY_ERROR = 6;
|
||||
private static final int ITEM_IDX_SPACE = 7;
|
||||
private static final int ITEM_TYPES_SUM = 8;
|
||||
|
||||
private final Context mContext;
|
||||
private final StatusFragment mFragment;
|
||||
private final LayoutInflater mInflater;
|
||||
private final MediaLoadingHandler mMediaLoadingHandler;
|
||||
private final TwidereLinkify mTwidereLinkify;
|
||||
private final int[] mItemCounts;
|
||||
|
||||
private final boolean mNameFirst;
|
||||
@ -1083,6 +1118,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
private StatusAdapterListener mStatusAdapterListener;
|
||||
private RecyclerView mRecyclerView;
|
||||
private DetailStatusViewHolder mStatusViewHolder;
|
||||
private CharSequence mReplyError;
|
||||
|
||||
public StatusAdapter(StatusFragment fragment, boolean compact) {
|
||||
super(fragment.getContext());
|
||||
@ -1334,6 +1370,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
mLoadMoreIndicatorVisible = false;
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
updateItemDecoration();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1375,6 +1412,11 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
case VIEW_TYPE_SPACE: {
|
||||
return new SpaceViewHolder(new Space(mContext));
|
||||
}
|
||||
case VIEW_TYPE_REPLY_ERROR: {
|
||||
final View view = mInflater.inflate(R.layout.adapter_item_status_error, parent,
|
||||
false);
|
||||
return new StatusErrorItemViewHolder(view);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -1400,6 +1442,11 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
&& (position - getItemTypeStart(position)) == 0);
|
||||
break;
|
||||
}
|
||||
case VIEW_TYPE_REPLY_ERROR: {
|
||||
final StatusErrorItemViewHolder errorHolder = (StatusErrorItemViewHolder) holder;
|
||||
errorHolder.showError(mReplyError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1421,6 +1468,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
return VIEW_TYPE_DETAIL_STATUS;
|
||||
case ITEM_IDX_SPACE:
|
||||
return VIEW_TYPE_SPACE;
|
||||
case ITEM_IDX_REPLY_ERROR:
|
||||
return VIEW_TYPE_REPLY_ERROR;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@ -1433,7 +1482,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
if (position >= typeStart && position < typeEnd) return type;
|
||||
typeStart = typeEnd;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unknown position " + position);
|
||||
}
|
||||
|
||||
private int getItemTypeStart(int position) {
|
||||
@ -1531,6 +1580,13 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
mStatusAdapterListener = listener;
|
||||
}
|
||||
|
||||
public void setReplyError(CharSequence error) {
|
||||
mReplyError = error;
|
||||
mItemCounts[ITEM_IDX_REPLY_ERROR] = error != null ? 1 : 0;
|
||||
notifyDataSetChanged();
|
||||
updateItemDecoration();
|
||||
}
|
||||
|
||||
public void setReplies(List<ParcelableStatus> replies) {
|
||||
mReplies = replies;
|
||||
mItemCounts[ITEM_IDX_REPLY] = replies != null ? replies.size() : 0;
|
||||
@ -1548,18 +1604,6 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
return !CompareUtils.objectEquals(old, status);
|
||||
}
|
||||
|
||||
private int getConversationCount() {
|
||||
return mConversation != null ? mConversation.size() : 1;
|
||||
}
|
||||
|
||||
private int getRepliesCount() {
|
||||
return mReplies != null ? mReplies.size() : 1;
|
||||
}
|
||||
|
||||
private int getStatusPosition() {
|
||||
return getConversationCount();
|
||||
}
|
||||
|
||||
private void updateItemDecoration() {
|
||||
if (mRecyclerView == null) return;
|
||||
final DividerItemDecoration decoration = mFragment.getItemDecoration();
|
||||
@ -1575,11 +1619,37 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
public void setRepliesLoading(boolean loading) {
|
||||
mItemCounts[ITEM_IDX_REPLY_LOAD_MORE] = loading ? 1 : 0;
|
||||
notifyDataSetChanged();
|
||||
updateItemDecoration();
|
||||
}
|
||||
|
||||
public void setConversationsLoading(boolean loading) {
|
||||
mItemCounts[ITEM_IDX_CONVERSATION_LOAD_MORE] = loading ? 1 : 0;
|
||||
notifyDataSetChanged();
|
||||
updateItemDecoration();
|
||||
}
|
||||
|
||||
public int getFirstPositionOfItem(int itemIdx) {
|
||||
int position = 0;
|
||||
for (int i = 0; i < ITEM_TYPES_SUM; i++) {
|
||||
if (itemIdx == i) return position;
|
||||
position += mItemCounts[i];
|
||||
}
|
||||
return RecyclerView.NO_POSITION;
|
||||
}
|
||||
|
||||
public static class StatusErrorItemViewHolder extends ViewHolder {
|
||||
private final TextView textView;
|
||||
|
||||
public StatusErrorItemViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
textView = (TextView) itemView.findViewById(android.R.id.text1);
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
textView.setLinksClickable(true);
|
||||
}
|
||||
|
||||
public void showError(CharSequence text) {
|
||||
textView.setText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1602,13 +1672,13 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
final View childToMeasure = getChildAt(i);
|
||||
final LayoutParams paramsToMeasure = (LayoutParams) childToMeasure.getLayoutParams();
|
||||
final int typeToMeasure = getItemViewType(childToMeasure);
|
||||
if (typeToMeasure == StatusAdapter.VIEW_TYPE_SPACE) {
|
||||
break;
|
||||
}
|
||||
if (typeToMeasure == StatusAdapter.VIEW_TYPE_DETAIL_STATUS || heightBeforeSpace != 0) {
|
||||
heightBeforeSpace += super.getDecoratedMeasuredHeight(childToMeasure)
|
||||
+ paramsToMeasure.topMargin + paramsToMeasure.bottomMargin;
|
||||
}
|
||||
if (typeToMeasure == StatusAdapter.VIEW_TYPE_REPLIES_LOAD_INDICATOR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (heightBeforeSpace != 0) {
|
||||
final int spaceHeight = recyclerView.getMeasuredHeight() - heightBeforeSpace;
|
||||
@ -1627,5 +1697,4 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -32,8 +32,8 @@ public class StatusRepliesListFragment extends StatusesSearchFragment {
|
||||
|
||||
@Override
|
||||
protected Loader<List<ParcelableStatus>> onCreateStatusesLoader(final Context context,
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
||||
final long statusId = args.getLong(EXTRA_STATUS_ID, -1);
|
||||
|
@ -32,8 +32,8 @@ public class StatusesListFragment extends ParcelableStatusesFragment {
|
||||
|
||||
@Override
|
||||
protected Loader<List<ParcelableStatus>> onCreateStatusesLoader(final Context context,
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
return new IntentExtrasStatusesLoader(context, getArguments(), getAdapterData(), fromUser);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.fragment.support;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14-6-24.
|
||||
*/
|
||||
public class SupportMessageDialogFragment extends DialogFragment {
|
||||
private static final String EXTRA_MESSAGE = "message";
|
||||
|
||||
public static SupportMessageDialogFragment show(FragmentActivity activity, String message, String tag) {
|
||||
SupportMessageDialogFragment df = new SupportMessageDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(EXTRA_MESSAGE, message);
|
||||
df.setArguments(args);
|
||||
df.show(activity.getSupportFragmentManager(), tag);
|
||||
return df;
|
||||
}
|
||||
|
||||
public static SupportMessageDialogFragment create(String message) {
|
||||
SupportMessageDialogFragment df = new SupportMessageDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(EXTRA_MESSAGE, message);
|
||||
df.setArguments(args);
|
||||
return df;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
FragmentActivity activity = getActivity();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
final Bundle args = getArguments();
|
||||
builder.setMessage(args.getString(EXTRA_MESSAGE));
|
||||
builder.setPositiveButton(android.R.string.ok, null);
|
||||
return builder.create();
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import android.os.Bundle;
|
||||
import android.support.v4.content.Loader;
|
||||
|
||||
import org.mariotaku.twidere.loader.support.UserFavoritesLoader;
|
||||
import org.mariotaku.twidere.model.ListResponse;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
import java.util.List;
|
||||
@ -35,8 +36,8 @@ public class UserFavoritesFragment extends ParcelableStatusesFragment {
|
||||
|
||||
@Override
|
||||
protected Loader<List<ParcelableStatus>> onCreateStatusesLoader(final Context context,
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
setRefreshing(true);
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final long maxId = args.getLong(EXTRA_MAX_ID, -1);
|
||||
|
@ -35,8 +35,8 @@ public class UserListTimelineFragment extends ParcelableStatusesFragment {
|
||||
|
||||
@Override
|
||||
protected Loader<List<ParcelableStatus>> onCreateStatusesLoader(final Context context,
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
setRefreshing(true);
|
||||
if (args == null) return null;
|
||||
final long listId = args.getLong(EXTRA_LIST_ID, -1);
|
||||
|
@ -24,6 +24,7 @@ import android.os.Bundle;
|
||||
import android.support.v4.content.Loader;
|
||||
|
||||
import org.mariotaku.twidere.loader.support.UserTimelineLoader;
|
||||
import org.mariotaku.twidere.model.ListResponse;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
import java.util.List;
|
||||
@ -35,8 +36,8 @@ public class UserTimelineFragment extends ParcelableStatusesFragment {
|
||||
|
||||
@Override
|
||||
protected Loader<List<ParcelableStatus>> onCreateStatusesLoader(final Context context,
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
final Bundle args,
|
||||
final boolean fromUser) {
|
||||
setRefreshing(true);
|
||||
final List<ParcelableStatus> data = getAdapterData();
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
|
@ -21,9 +21,9 @@ package org.mariotaku.twidere.loader.support;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.mariotaku.twidere.model.ListResponse;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class DummyParcelableStatusesLoader extends ParcelableStatusesLoader {
|
||||
@ -37,10 +37,10 @@ public final class DummyParcelableStatusesLoader extends ParcelableStatusesLoade
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParcelableStatus> loadInBackground() {
|
||||
public ListResponse<ParcelableStatus> loadInBackground() {
|
||||
final List<ParcelableStatus> data = getData();
|
||||
if (data != null) return data;
|
||||
return Collections.emptyList();
|
||||
if (data != null) return ListResponse.getListInstance(data);
|
||||
return ListResponse.emptyListInstance();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ package org.mariotaku.twidere.loader.support;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.mariotaku.twidere.model.ListResponse;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -38,14 +39,16 @@ public class IntentExtrasStatusesLoader extends ParcelableStatusesLoader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParcelableStatus> loadInBackground() {
|
||||
public ListResponse<ParcelableStatus> loadInBackground() {
|
||||
final List<ParcelableStatus> data = getData();
|
||||
if (mExtras != null && mExtras.containsKey(EXTRA_STATUSES)) {
|
||||
final List<ParcelableStatus> users = mExtras.getParcelableArrayList(EXTRA_STATUSES);
|
||||
data.addAll(users);
|
||||
Collections.sort(data);
|
||||
if (data != null && users != null) {
|
||||
data.addAll(users);
|
||||
Collections.sort(data);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
return ListResponse.getListInstance(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.LoaderTrojan;
|
||||
|
||||
import org.mariotaku.twidere.model.ListResponse;
|
||||
import org.mariotaku.twidere.model.ObjectCursor;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
|
@ -23,45 +23,29 @@ import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.isFiltered;
|
||||
|
||||
public class RetweetsOfMeLoader extends TwitterAPIStatusesLoader {
|
||||
|
||||
private long mTotalItemsCount;
|
||||
|
||||
public RetweetsOfMeLoader(final Context context, final long accountId, final long sinceId, final long maxId,
|
||||
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
|
||||
final int tabPosition, boolean fromUser) {
|
||||
super(context, accountId, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
|
||||
}
|
||||
|
||||
public long getTotalItemsCount() {
|
||||
return mTotalItemsCount;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected ResponseList<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
|
||||
if (twitter == null) return null;
|
||||
final ResponseList<Status> statuses = twitter.getRetweetsOfMe(paging);
|
||||
if (mTotalItemsCount == -1 && !statuses.isEmpty()) {
|
||||
final User user = statuses.get(0).getUser();
|
||||
if (user != null) {
|
||||
mTotalItemsCount = user.getStatusesCount();
|
||||
}
|
||||
}
|
||||
return statuses;
|
||||
return twitter.getRetweetsOfMe(paging);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,6 +34,7 @@ import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.model.ListResponse;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.LoganSquareWrapper;
|
||||
import org.mariotaku.twidere.util.TwitterAPIFactory;
|
||||
@ -70,7 +71,7 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final List<ParcelableStatus> loadInBackground() {
|
||||
public final ListResponse<ParcelableStatus> loadInBackground() {
|
||||
final File serializationFile = getSerializationFile();
|
||||
List<ParcelableStatus> data = getData();
|
||||
if (data == null) {
|
||||
@ -85,10 +86,10 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
||||
} else {
|
||||
Collections.sort(data);
|
||||
}
|
||||
return new CopyOnWriteArrayList<>(data);
|
||||
return ListResponse.getListInstance(new CopyOnWriteArrayList<>(data));
|
||||
}
|
||||
}
|
||||
if (!isFromUser()) return data;
|
||||
if (!isFromUser()) return ListResponse.getListInstance(data);
|
||||
final Twitter twitter = getTwitter();
|
||||
if (twitter == null) return null;
|
||||
final List<Status> statuses;
|
||||
@ -114,7 +115,7 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
||||
} catch (final TwitterException e) {
|
||||
// mHandler.post(new ShowErrorRunnable(e));
|
||||
Log.w(LOGTAG, e);
|
||||
return new CopyOnWriteArrayList<>(data);
|
||||
return ListResponse.getListInstance(new CopyOnWriteArrayList<>(data), e);
|
||||
}
|
||||
|
||||
final long[] statusIds = new long[statuses.size()];
|
||||
@ -159,7 +160,7 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
||||
Collections.sort(data);
|
||||
}
|
||||
saveCachedData(serializationFile, data);
|
||||
return new CopyOnWriteArrayList<>(data);
|
||||
return ListResponse.getListInstance(new CopyOnWriteArrayList<>(data));
|
||||
}
|
||||
|
||||
public final void setComparator(Comparator<ParcelableStatus> comparator) {
|
||||
|
@ -50,7 +50,6 @@ public class UserFavoritesLoader extends TwitterAPIStatusesLoader {
|
||||
@NonNull
|
||||
@Override
|
||||
public ResponseList<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
|
||||
if (twitter == null) return null;
|
||||
if (mUserId != -1)
|
||||
return twitter.getFavorites(mUserId, paging);
|
||||
else if (mUserScreenName != null) return twitter.getFavorites(mUserScreenName, paging);
|
||||
|
@ -20,21 +20,28 @@
|
||||
package org.mariotaku.twidere.model;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ListResponse<Data> extends SingleResponse<List<Data>> {
|
||||
public class ListResponse<Data> extends AbstractList<Data> implements Response<List<Data>>, List<Data> {
|
||||
|
||||
public final List<Data> list;
|
||||
@Nullable
|
||||
private final List<Data> list;
|
||||
private final Exception exception;
|
||||
private final Bundle extras;
|
||||
|
||||
public ListResponse(final List<Data> list, final Exception exception) {
|
||||
super(list, exception);
|
||||
this.list = list;
|
||||
this(list, exception, new Bundle());
|
||||
}
|
||||
|
||||
public ListResponse(final List<Data> list, final Exception exception, final Bundle extras) {
|
||||
super(list, exception, extras);
|
||||
public ListResponse(@Nullable final List<Data> list, final Exception exception, @NonNull final Bundle extras) {
|
||||
this.list = list;
|
||||
this.exception = exception;
|
||||
this.extras = extras;
|
||||
}
|
||||
|
||||
public static <Data> ListResponse<Data> getListInstance(Exception exception) {
|
||||
@ -45,4 +52,72 @@ public class ListResponse<Data> extends SingleResponse<List<Data>> {
|
||||
return new ListResponse<>(data, null);
|
||||
}
|
||||
|
||||
public static <Data> ListResponse<Data> emptyListInstance() {
|
||||
return new ListResponse<>(Collections.<Data>emptyList(), null);
|
||||
}
|
||||
|
||||
public static <Data> ListResponse<Data> getListInstance(List<Data> list, Exception e) {
|
||||
return new ListResponse<>(list, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (list == null) throw new NullPointerException();
|
||||
return list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return list != null && list.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Data remove(int location) {
|
||||
if (list == null) throw new NullPointerException();
|
||||
return list.remove(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Data set(int location, Data object) {
|
||||
if (list == null) throw new NullPointerException();
|
||||
return list.set(location, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int location, Data object) {
|
||||
if (list == null) throw new NullPointerException();
|
||||
list.add(location, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Data get(int location) {
|
||||
if (list == null) throw new NullPointerException();
|
||||
return list.get(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Data> getData() {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Bundle getExtras() {
|
||||
return extras;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasData() {
|
||||
return list != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasException() {
|
||||
return exception != null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/10/11.
|
||||
*/
|
||||
public interface Response<Data> {
|
||||
Data getData();
|
||||
|
||||
Exception getException();
|
||||
|
||||
@NonNull
|
||||
Bundle getExtras();
|
||||
|
||||
boolean hasData();
|
||||
|
||||
boolean hasException();
|
||||
}
|
@ -22,81 +22,86 @@ package org.mariotaku.twidere.model;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class SingleResponse<Data> {
|
||||
private final Exception exception;
|
||||
private final Data data;
|
||||
private final Bundle extras;
|
||||
public class SingleResponse<Data> implements Response<Data> {
|
||||
protected final Exception exception;
|
||||
protected final Data data;
|
||||
protected final Bundle extras;
|
||||
|
||||
public SingleResponse(final Data data, final Exception exception) {
|
||||
this(data, exception, null);
|
||||
}
|
||||
public SingleResponse(final Data data, final Exception exception) {
|
||||
this(data, exception, null);
|
||||
}
|
||||
|
||||
public SingleResponse(final Data data, final Exception exception, final Bundle extras) {
|
||||
this.data = data;
|
||||
this.exception = exception;
|
||||
this.extras = extras != null ? extras : new Bundle();
|
||||
}
|
||||
public SingleResponse(final Data data, final Exception exception, final Bundle extras) {
|
||||
this.data = data;
|
||||
this.exception = exception;
|
||||
this.extras = extras != null ? extras : new Bundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof SingleResponse)) return false;
|
||||
final SingleResponse<?> other = (SingleResponse<?>) obj;
|
||||
if (getData() == null) {
|
||||
if (other.getData() != null) return false;
|
||||
} else if (!getData().equals(other.getData())) return false;
|
||||
if (exception == null) {
|
||||
if (other.exception != null) return false;
|
||||
} else if (!exception.equals(other.exception)) return false;
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof SingleResponse)) return false;
|
||||
final SingleResponse<?> other = (SingleResponse<?>) obj;
|
||||
if (getData() == null) {
|
||||
if (other.getData() != null) return false;
|
||||
} else if (!getData().equals(other.getData())) return false;
|
||||
if (exception == null) {
|
||||
if (other.exception != null) return false;
|
||||
} else if (!exception.equals(other.exception)) return false;
|
||||
if (!getExtras().equals(other.getExtras())) return false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Data getData() {
|
||||
return data;
|
||||
}
|
||||
@Override
|
||||
public Data getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
@Override
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Bundle getExtras() {
|
||||
return extras;
|
||||
}
|
||||
public Bundle getExtras() {
|
||||
return extras;
|
||||
}
|
||||
|
||||
public boolean hasData() {
|
||||
return getData() != null;
|
||||
}
|
||||
@Override
|
||||
public boolean hasData() {
|
||||
return getData() != null;
|
||||
}
|
||||
|
||||
public boolean hasException() {
|
||||
return exception != null;
|
||||
}
|
||||
@Override
|
||||
public boolean hasException() {
|
||||
return exception != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (getData() == null ? 0 : getData().hashCode());
|
||||
result = prime * result + (exception == null ? 0 : exception.hashCode());
|
||||
result = prime * result + (getExtras().hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (getData() == null ? 0 : getData().hashCode());
|
||||
result = prime * result + (exception == null ? 0 : exception.hashCode());
|
||||
result = prime * result + (getExtras().hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> SingleResponse<T> getInstance() {
|
||||
return new SingleResponse<>(null, null);
|
||||
}
|
||||
public static <T> SingleResponse<T> getInstance() {
|
||||
return new SingleResponse<>(null, null);
|
||||
}
|
||||
|
||||
public static <T> SingleResponse<T> getInstance(final Exception exception) {
|
||||
return new SingleResponse<>(null, exception);
|
||||
}
|
||||
public static <T> SingleResponse<T> getInstance(final Exception exception) {
|
||||
return new SingleResponse<>(null, exception);
|
||||
}
|
||||
|
||||
public static <T> SingleResponse<T> getInstance(final T data) {
|
||||
return new SingleResponse<>(data, null);
|
||||
}
|
||||
public static <T> SingleResponse<T> getInstance(final T data) {
|
||||
return new SingleResponse<>(data, null);
|
||||
}
|
||||
|
||||
public static <T> SingleResponse<T> getInstance(final T data, final Exception exception) {
|
||||
return new SingleResponse<>(data, exception);
|
||||
}
|
||||
public static <T> SingleResponse<T> getInstance(final T data, final Exception exception) {
|
||||
return new SingleResponse<>(data, exception);
|
||||
}
|
||||
}
|
||||
|
@ -186,32 +186,34 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
|
||||
private static PendingIntent getMarkReadDeleteIntent(Context context, String type, long accountId, long position, long extraId) {
|
||||
// Setup delete intent
|
||||
final Intent recvIntent = new Intent(context, NotificationReceiver.class);
|
||||
recvIntent.setAction(BROADCAST_NOTIFICATION_DELETED);
|
||||
final Uri.Builder recvLinkBuilder = new Uri.Builder();
|
||||
recvLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
recvLinkBuilder.authority(AUTHORITY_NOTIFICATIONS);
|
||||
recvLinkBuilder.appendPath(type);
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITION, String.valueOf(position));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_EXTRA_ID, String.valueOf(extraId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
recvIntent.setData(recvLinkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, recvIntent, 0);
|
||||
final Intent intent = new Intent(context, NotificationReceiver.class);
|
||||
intent.setAction(BROADCAST_NOTIFICATION_DELETED);
|
||||
final Uri.Builder linkBuilder = new Uri.Builder();
|
||||
linkBuilder.scheme(SCHEME_TWIDERE);
|
||||
linkBuilder.authority(AUTHORITY_NOTIFICATIONS);
|
||||
linkBuilder.appendPath(type);
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITION, String.valueOf(position));
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_EXTRA_ID, String.valueOf(extraId));
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_NOTIFICATION_TYPE, type);
|
||||
intent.setData(linkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, intent, 0);
|
||||
}
|
||||
|
||||
private static PendingIntent getMarkReadDeleteIntent(Context context, String type, long accountId, StringLongPair[] positions) {
|
||||
// Setup delete intent
|
||||
final Intent recvIntent = new Intent(context, NotificationReceiver.class);
|
||||
final Uri.Builder recvLinkBuilder = new Uri.Builder();
|
||||
recvLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
recvLinkBuilder.authority(AUTHORITY_NOTIFICATIONS);
|
||||
recvLinkBuilder.appendPath(type);
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITIONS, StringLongPair.toString(positions));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
recvIntent.setData(recvLinkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, recvIntent, 0);
|
||||
final Intent intent = new Intent(context, NotificationReceiver.class);
|
||||
final Uri.Builder linkBuilder = new Uri.Builder();
|
||||
linkBuilder.scheme(SCHEME_TWIDERE);
|
||||
linkBuilder.authority(AUTHORITY_NOTIFICATIONS);
|
||||
linkBuilder.appendPath(type);
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITIONS, StringLongPair.toString(positions));
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
linkBuilder.appendQueryParameter(QUERY_PARAM_NOTIFICATION_TYPE, type);
|
||||
intent.setData(linkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, intent, 0);
|
||||
}
|
||||
|
||||
private static Cursor getPreferencesCursor(final SharedPreferencesWrapper preferences, final String key) {
|
||||
@ -1238,7 +1240,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
mNameFirst, false)));
|
||||
builder.setContentText(text);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(getStatusContentIntent(context, accountId, statusId));
|
||||
builder.setContentIntent(getStatusContentIntent(context, AUTHORITY_MENTIONS, accountId,
|
||||
statusId));
|
||||
builder.setDeleteIntent(getMarkReadDeleteIntent(context, AUTHORITY_MENTIONS, accountId,
|
||||
statusId, statusId));
|
||||
builder.setWhen(statusCursor.getLong(indices.status_timestamp));
|
||||
@ -1355,11 +1358,12 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_FROM_NOTIFICATION, String.valueOf(true));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_NOTIFICATION_TYPE, type);
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
return PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
}
|
||||
|
||||
private PendingIntent getStatusContentIntent(Context context, long accountId, long statusId) {
|
||||
private PendingIntent getStatusContentIntent(Context context, String type, long accountId, long statusId) {
|
||||
// Setup click intent
|
||||
final Intent homeIntent = new Intent(Intent.ACTION_VIEW);
|
||||
homeIntent.setPackage(BuildConfig.APPLICATION_ID);
|
||||
@ -1371,6 +1375,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_EXTRA_ID, String.valueOf(statusId));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_FROM_NOTIFICATION, String.valueOf(true));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_NOTIFICATION_TYPE, type);
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
return PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class NotificationReceiver extends BroadcastReceiver implements Constants
|
||||
case BROADCAST_NOTIFICATION_DELETED: {
|
||||
final Uri uri = intent.getData();
|
||||
if (uri == null) return;
|
||||
final String type = uri.getLastPathSegment();
|
||||
final String type = uri.getQueryParameter(QUERY_PARAM_NOTIFICATION_TYPE);
|
||||
final long accountId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID), -1);
|
||||
final long extraId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_EXTRA_ID), -1);
|
||||
final long timestamp = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_TIMESTAMP), -1);
|
||||
|
@ -59,10 +59,10 @@ public class CacheUsersStatusesTask extends AsyncTask<TwitterListResponse<Status
|
||||
final Extractor extractor = new Extractor();
|
||||
|
||||
for (final TwitterListResponse<org.mariotaku.twidere.api.twitter.model.Status> response : args) {
|
||||
if (response == null || response.list == null) {
|
||||
if (response == null || !response.hasData()) {
|
||||
continue;
|
||||
}
|
||||
final List<org.mariotaku.twidere.api.twitter.model.Status> list = response.list;
|
||||
final List<org.mariotaku.twidere.api.twitter.model.Status> list = response.getData();
|
||||
for (int bulkIdx = 0, totalSize = list.size(); bulkIdx < totalSize; bulkIdx += 100) {
|
||||
for (int idx = bulkIdx, end = Math.min(totalSize, bulkIdx + ContentResolverUtils.MAX_BULK_COUNT); idx < end; idx++) {
|
||||
final org.mariotaku.twidere.api.twitter.model.Status status = list.get(idx);
|
||||
|
@ -69,6 +69,7 @@ import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.model.ParcelableUserList;
|
||||
import org.mariotaku.twidere.model.Response;
|
||||
import org.mariotaku.twidere.model.SingleResponse;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags;
|
||||
@ -500,7 +501,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
private static <T extends SingleResponse<?>> Exception getException(List<T> responses) {
|
||||
private static <T extends Response<?>> Exception getException(List<T> responses) {
|
||||
for (T response : responses) {
|
||||
if (response.hasException()) return response.getException();
|
||||
}
|
||||
@ -1036,7 +1037,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final ListResponse<Long> result) {
|
||||
if (result.list != null) {
|
||||
if (result.hasData()) {
|
||||
Utils.showInfoMessage(mContext, R.string.users_blocked, false);
|
||||
} else {
|
||||
Utils.showErrorMessage(mContext, R.string.action_blocking, result.getException(), true);
|
||||
@ -2496,7 +2497,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
@Override
|
||||
protected void onPostExecute(final ListResponse<Long> result) {
|
||||
if (result != null) {
|
||||
final String user_id_where = ListUtils.toString(result.list, ',', false);
|
||||
final String user_id_where = ListUtils.toString(result.getData(), ',', false);
|
||||
for (final Uri uri : TwidereDataStore.STATUSES_URIS) {
|
||||
final Expression where = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, account_id),
|
||||
new Expression(String.format(Locale.ROOT, "%s IN (%s)", Statuses.USER_ID, user_id_where)));
|
||||
@ -2652,7 +2653,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
@Override
|
||||
protected SingleResponse<Boolean> doInBackground(final Object... args) {
|
||||
if (response == null) return SingleResponse.getInstance(false);
|
||||
final List<Trends> messages = response.list;
|
||||
final List<Trends> messages = response.getData();
|
||||
final ArrayList<String> hashtags = new ArrayList<>();
|
||||
final ArrayList<ContentValues> hashtagValues = new ArrayList<>();
|
||||
if (messages != null && messages.size() > 0) {
|
||||
|
@ -75,9 +75,12 @@ public class ContentListScrollListener extends OnScrollListener {
|
||||
final ILoadMoreSupportAdapter loadMoreAdapter = (ILoadMoreSupportAdapter) adapter;
|
||||
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (!mContentListSupport.isRefreshing() && loadMoreAdapter.isLoadMoreSupported()
|
||||
&& !loadMoreAdapter.isLoadMoreIndicatorVisible()
|
||||
&& layoutManager.findLastVisibleItemPosition() == layoutManager.getItemCount() - 1) {
|
||||
mContentListSupport.onLoadMoreContents();
|
||||
&& !loadMoreAdapter.isLoadMoreIndicatorVisible()) {
|
||||
if (layoutManager.findLastVisibleItemPosition() == layoutManager.getItemCount() - 1) {
|
||||
mContentListSupport.onLoadMoreContents(false);
|
||||
} else if (layoutManager.findFirstVisibleItemPosition() == 0) {
|
||||
mContentListSupport.onLoadMoreContents(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +90,7 @@ public class ContentListScrollListener extends OnScrollListener {
|
||||
|
||||
boolean isRefreshing();
|
||||
|
||||
void onLoadMoreContents();
|
||||
void onLoadMoreContents(boolean fromStart);
|
||||
|
||||
void setControlVisible(boolean visible);
|
||||
|
||||
|
@ -124,9 +124,11 @@ public class ThemeUtils implements Constants {
|
||||
icon.mutate();
|
||||
if (info instanceof TwidereMenuInfo) {
|
||||
final TwidereMenuInfo sInfo = (TwidereMenuInfo) info;
|
||||
icon.setColorFilter(sInfo.isHighlight() ?
|
||||
sInfo.getHighlightColor(highlightColor) : color, mode);
|
||||
} else {
|
||||
final int stateColor = sInfo.isHighlight() ? sInfo.getHighlightColor(highlightColor) : color;
|
||||
if (stateColor != 0) {
|
||||
icon.setColorFilter(stateColor, mode);
|
||||
}
|
||||
} else if (color != 0) {
|
||||
icon.setColorFilter(color, mode);
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,13 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatCallback;
|
||||
import android.support.v7.internal.view.StandaloneActionMode;
|
||||
import android.support.v7.internal.view.SupportActionModeWrapper;
|
||||
import android.support.v7.internal.widget.ActionBarContextView;
|
||||
import android.support.v7.view.ActionMode;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.Menu;
|
||||
@ -38,8 +40,9 @@ import android.view.Window;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.PopupWindow;
|
||||
|
||||
import org.mariotaku.twidere.activity.iface.IAppCompatActivity;
|
||||
import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment;
|
||||
import org.mariotaku.twidere.view.AppCompatUtils;
|
||||
import org.mariotaku.twidere.view.TintedStatusNativeActionModeAwareLayout;
|
||||
|
||||
/**
|
||||
@ -110,7 +113,6 @@ public class TwidereActionModeForChildListener implements TintedStatusNativeActi
|
||||
mActionModePopup = new PopupWindow(actionBarContext, null,
|
||||
android.support.v7.appcompat.R.attr.actionModePopupWindowStyle);
|
||||
mActionModePopup.setContentView(mActionModeView);
|
||||
mActionModePopup.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
|
||||
final TypedValue outValue = new TypedValue();
|
||||
actionBarContext.getTheme().resolveAttribute(
|
||||
@ -122,13 +124,21 @@ public class TwidereActionModeForChildListener implements TintedStatusNativeActi
|
||||
mThemed.getCurrentThemeResourceId(), mThemed.getCurrentThemeColor(),
|
||||
mThemed.getCurrentThemeBackgroundOption(), false);
|
||||
mActionModePopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
final int actionModeOffset = getActionModeOffset();
|
||||
final Rect actionModeBounds = getActionModeBounds();
|
||||
if (actionModeBounds != null) {
|
||||
mActionModePopup.setWidth(actionModeBounds.width());
|
||||
} else {
|
||||
mActionModePopup.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
mShowActionModePopup = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mActionModePopup.showAtLocation(
|
||||
mWindow.getDecorView(),
|
||||
Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, actionModeOffset);
|
||||
if (actionModeBounds != null) {
|
||||
mActionModePopup.showAtLocation(mWindow.getDecorView(), Gravity.TOP | Gravity.LEFT,
|
||||
actionModeBounds.left, actionModeBounds.top);
|
||||
} else {
|
||||
mActionModePopup.showAtLocation(mWindow.getDecorView(), Gravity.TOP | Gravity.LEFT, 0, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -162,14 +172,22 @@ public class TwidereActionModeForChildListener implements TintedStatusNativeActi
|
||||
return mActionMode;
|
||||
}
|
||||
|
||||
private int getActionModeOffset() {
|
||||
if (mActivity instanceof IBaseFragment.SystemWindowsInsetsCallback) {
|
||||
final Rect insets = new Rect();
|
||||
if (((IBaseFragment.SystemWindowsInsetsCallback) mActivity).getSystemWindowsInsets(insets)) {
|
||||
return Utils.getInsetsTopWithoutActionBarHeight(mActivity, insets.top);
|
||||
private Rect getActionModeBounds() {
|
||||
if (mActivity instanceof IAppCompatActivity) {
|
||||
final Rect bounds = new Rect();
|
||||
final int[] location = new int[2];
|
||||
final ActionBar actionBar = ((IAppCompatActivity) mActivity).getSupportActionBar();
|
||||
final Toolbar toolbar = AppCompatUtils.findToolbarForActionBar(actionBar);
|
||||
if (toolbar != null) {
|
||||
toolbar.getLocationInWindow(location);
|
||||
bounds.left = location[0];
|
||||
bounds.top = location[1];
|
||||
bounds.right = bounds.left + toolbar.getWidth();
|
||||
bounds.bottom = bounds.top + toolbar.getHeight();
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean finishExisting() {
|
||||
|
@ -3948,10 +3948,7 @@ public final class Utils implements Constants {
|
||||
|
||||
public static void logOpenNotificationFromUri(Context context, Uri uri) {
|
||||
if (!uri.getBooleanQueryParameter(QUERY_PARAM_FROM_NOTIFICATION, false)) return;
|
||||
String type = uri.getLastPathSegment();
|
||||
if (type == null) {
|
||||
type = uri.getAuthority();
|
||||
}
|
||||
final String type = uri.getQueryParameter(QUERY_PARAM_NOTIFICATION_TYPE);
|
||||
final long accountId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID), -1);
|
||||
final long extraId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_EXTRA_ID), -1);
|
||||
final long timestamp = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_TIMESTAMP), -1);
|
||||
@ -3961,6 +3958,11 @@ public final class Utils implements Constants {
|
||||
logger.log(accountId, NotificationEvent.open(context, timestamp, type, accountId, extraId));
|
||||
}
|
||||
|
||||
public static boolean hasOfficialAPIAccess(Context context, SharedPreferences preferences, ParcelableCredentials account) {
|
||||
if (preferences.getBoolean(KEY_FORCE_USING_PRIVATE_APIS, false)) return true;
|
||||
return isOfficialCredentials(context, account);
|
||||
}
|
||||
|
||||
static class UtilsL {
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.view;
|
||||
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.internal.app.ToolbarActionBar;
|
||||
import android.support.v7.internal.widget.DecorToolbar;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/10/12.
|
||||
*/
|
||||
public class AppCompatUtils {
|
||||
|
||||
public static Toolbar findToolbarForActionBar(ActionBar actionBar) {
|
||||
if (actionBar instanceof ToolbarActionBar) {
|
||||
final Object decorToolbar = Utils.findFieldOfTypes(actionBar, ToolbarActionBar.class, DecorToolbar.class);
|
||||
if (decorToolbar instanceof DecorToolbar) {
|
||||
return (Toolbar) ((DecorToolbar) decorToolbar).getViewGroup();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -42,20 +42,20 @@ public class SquareShapedImageView extends ShapedImageView {
|
||||
final int width = MeasureSpec.getSize(widthMeasureSpec), height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
final ViewGroup.LayoutParams lp = getLayoutParams();
|
||||
if (lp.height == ViewGroup.LayoutParams.MATCH_PARENT && lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
|
||||
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(height, height);
|
||||
super.onMeasure(makeSpec(heightMeasureSpec, MeasureSpec.EXACTLY), makeSpec(heightMeasureSpec, MeasureSpec.EXACTLY));
|
||||
} else if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT && lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
setMeasuredDimension(width, width);
|
||||
super.onMeasure(makeSpec(widthMeasureSpec, MeasureSpec.EXACTLY), makeSpec(widthMeasureSpec, MeasureSpec.EXACTLY));
|
||||
} else {
|
||||
if (width > height) {
|
||||
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(height, height);
|
||||
super.onMeasure(makeSpec(heightMeasureSpec, MeasureSpec.EXACTLY), makeSpec(heightMeasureSpec, MeasureSpec.EXACTLY));
|
||||
} else {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
setMeasuredDimension(width, width);
|
||||
super.onMeasure(makeSpec(widthMeasureSpec, MeasureSpec.EXACTLY), makeSpec(widthMeasureSpec, MeasureSpec.EXACTLY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int makeSpec(int spec, int mode) {
|
||||
return MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(spec), mode);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,7 @@
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
@ -41,28 +40,34 @@
|
||||
android:paddingStart="@dimen/element_spacing_msmall"
|
||||
android:paddingTop="@dimen/element_spacing_msmall">
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
android:id="@+id/account_profile_image"
|
||||
style="?profileImageStyle"
|
||||
<org.mariotaku.twidere.view.SquareFrameLayout
|
||||
android:id="@+id/account_profile_image_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
app:sivBackgroundColor="?android:colorBackground"
|
||||
app:sivBorder="true"
|
||||
app:sivBorderWidth="@dimen/line_width_compose_account_profile_image"/>
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/account_profile_image"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
app:sivBackgroundColor="?android:colorBackground"
|
||||
app:sivBorder="true"
|
||||
app:sivBorderWidth="@dimen/line_width_compose_account_profile_image" />
|
||||
</org.mariotaku.twidere.view.SquareFrameLayout>
|
||||
|
||||
<org.mariotaku.twidere.view.BadgeView
|
||||
android:id="@+id/accounts_count"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignBottom="@id/account_profile_image"
|
||||
android:layout_alignEnd="@id/account_profile_image"
|
||||
android:layout_alignLeft="@id/account_profile_image"
|
||||
android:layout_alignRight="@id/account_profile_image"
|
||||
android:layout_alignStart="@id/account_profile_image"
|
||||
android:layout_alignTop="@id/account_profile_image"
|
||||
android:layout_alignBottom="@id/account_profile_image_frame"
|
||||
android:layout_alignEnd="@id/account_profile_image_frame"
|
||||
android:layout_alignLeft="@id/account_profile_image_frame"
|
||||
android:layout_alignRight="@id/account_profile_image_frame"
|
||||
android:layout_alignStart="@id/account_profile_image_frame"
|
||||
android:layout_alignTop="@id/account_profile_image_frame"
|
||||
android:layout_gravity="center"
|
||||
android:textColor="?android:colorForeground"/>
|
||||
android:textColor="?android:colorForeground" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -80,7 +85,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:background="@null"/>
|
||||
android:background="@null" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
@ -107,7 +112,7 @@
|
||||
android:gravity="center"
|
||||
android:minWidth="@dimen/element_size_small"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
tools:text="140"/>
|
||||
tools:text="140" />
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconView
|
||||
android:layout_width="wrap_content"
|
||||
@ -117,7 +122,7 @@
|
||||
android:cropToPadding="false"
|
||||
android:padding="@dimen/element_spacing_xsmall"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_action_send"/>
|
||||
android:src="@drawable/ic_action_send" />
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
@ -18,19 +17,18 @@
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<org.mariotaku.twidere.view.SquareFrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.mariotaku.twidere.view.SquareFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="@dimen/element_spacing_msmall">
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@android:id/icon"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:sivBorder="true"
|
||||
app:sivBorderWidth="1.5dp"/>
|
||||
app:sivBorderWidth="1.5dp" />
|
||||
|
||||
</org.mariotaku.twidere.view.SquareFrameLayout>
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Twidere - Twitter client for Android
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
~
|
||||
@ -18,18 +17,16 @@
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="?android:actionBarSize"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:activatedBackgroundIndicator"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_normal">
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
android:id="@android:id/icon"
|
||||
style="?profileImageStyle"
|
||||
<TextView
|
||||
android:id="@android:id/text1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/element_spacing_normal"/>
|
||||
android:gravity="center" />
|
||||
|
||||
</LinearLayout>
|
@ -62,7 +62,7 @@
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/activity_profile_image_0"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/profile_image_size_activity_small"
|
||||
@ -70,7 +70,7 @@
|
||||
android:layout_margin="2dp"
|
||||
android:contentDescription="@string/profile_image" />
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/activity_profile_image_1"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/profile_image_size_activity_small"
|
||||
@ -78,7 +78,7 @@
|
||||
android:layout_margin="2dp"
|
||||
android:contentDescription="@string/profile_image" />
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/activity_profile_image_2"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/profile_image_size_activity_small"
|
||||
@ -86,7 +86,7 @@
|
||||
android:layout_margin="2dp"
|
||||
android:contentDescription="@string/profile_image" />
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/activity_profile_image_3"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/profile_image_size_activity_small"
|
||||
@ -94,7 +94,7 @@
|
||||
android:layout_margin="2dp"
|
||||
android:contentDescription="@string/profile_image" />
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/activity_profile_image_4"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/profile_image_size_activity_small"
|
||||
|
@ -32,7 +32,7 @@
|
||||
app:ignorePadding="true"
|
||||
tools:context=".adapter.DirectMessagesEntryAdapter">
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/profile_image"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/icon_size_card_list_item"
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
@ -18,13 +17,13 @@
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<org.mariotaku.twidere.view.SquareShapedImageView
|
||||
android:id="@+id/color"
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/color"
|
||||
android:layout_width="@dimen/element_size_small"
|
||||
android:layout_height="@dimen/element_size_small"
|
||||
android:layout_gravity="center"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop"
|
||||
app:sivShape="circle"/>
|
||||
app:sivShape="circle" />
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<string name="app_description">Your own Twitter app</string>
|
||||
<string name="compose">Compose</string>
|
||||
<string name="add_account">Add account</string>
|
||||
<string name="settings">Settings</string>
|
||||
@ -386,7 +387,7 @@
|
||||
<string name="preview_images">Preview images</string>
|
||||
<string name="preload_wifi_only">Preload using Wi-Fi only</string>
|
||||
<string name="sign_in_method_introduction_title">How does it work?</string>
|
||||
<string name="sign_in_method_introduction">Most clients opens a webpage to authorize to Twitter, this could be inconvenient when using custom API, or on slow network. Twidere simulates a normal browser to help sign in to Twitter. Don\'t worry, your password will never be stored nor leaked.</string>
|
||||
<string name="sign_in_method_introduction">Most Twitter apps opens a webpage to authorize to Twitter, this could be inconvenient when using custom API, or on slow network. Twidere simulates a normal browser to help sign in to Twitter. Don\'t worry, your password will never be stored nor leaked.</string>
|
||||
<string name="quote_protected_status_notice">It\'s not recommended to quote protected tweets.</string>
|
||||
<string name="edit_draft">Edit draft</string>
|
||||
<string name="profile_image">Profile image</string>
|
||||
@ -791,5 +792,8 @@
|
||||
<string name="combined_notifications_summary_on">Notifications will be grouped</string>
|
||||
<string name="combined_notifications_summary_off">Notifications will be displayed separately</string>
|
||||
<string name="save_media_no_storage_permission_message">Storage permission is needed to save media.</string>
|
||||
<string name="select_file_no_storage_permission_message">Storage permission is needed to select file.</string>
|
||||
<string name="user_mentioned_you"><xliff:g id="name">%s</xliff:g> mentioned you</string>
|
||||
<string name="cant_load_all_replies_message">Can\'t load all replies. <a href=\"#dialog\";>Why?</a></string>
|
||||
<string name="cant_load_all_replies_explanation">Due to Twitter\'s limitation to third party twitter apps, Twidere has no access to replies to a tweet, there\'s no guarantee that Twidere can load all replies to a tweet.</string>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user