parent
46aea213ee
commit
5d7765b6d3
|
@ -11,4 +11,5 @@ include ':twidere.donate.nyanwp.wear'
|
||||||
include ':twidere.component.nyan'
|
include ':twidere.component.nyan'
|
||||||
include ':twidere.extension.streaming'
|
include ':twidere.extension.streaming'
|
||||||
include ':twidere.extension.twitlonger'
|
include ':twidere.extension.twitlonger'
|
||||||
include ':twidere.extension.push.xiaomi'
|
include ':twidere.extension.push.xiaomi'
|
||||||
|
include ':twidere.extension.launcher.compose'
|
|
@ -29,12 +29,12 @@ import org.mariotaku.twidere.constant.SharedPreferenceConstants;
|
||||||
*/
|
*/
|
||||||
public interface TwidereConstants extends SharedPreferenceConstants, IntentConstants {
|
public interface TwidereConstants extends SharedPreferenceConstants, IntentConstants {
|
||||||
|
|
||||||
public static final String APP_NAME = "Twidere";
|
public static final String TWIDERE_APP_NAME = "Twidere";
|
||||||
public static final String APP_PACKAGE_NAME = "org.mariotaku.twidere";
|
public static final String TWIDERE_PACKAGE_NAME = "org.mariotaku.twidere";
|
||||||
public static final String APP_PROJECT_URL = "https://github.com/mariotaku/twidere";
|
public static final String TWIDERE_PROJECT_URL = "https://github.com/mariotaku/twidere";
|
||||||
public static final String APP_PROJECT_EMAIL = "twidere.project@gmail.com";
|
public static final String TWIDERE_PROJECT_EMAIL = "twidere.project@gmail.com";
|
||||||
|
|
||||||
public static final String LOGTAG = APP_NAME;
|
public static final String LOGTAG = TWIDERE_APP_NAME;
|
||||||
|
|
||||||
public static final String USER_NICKNAME_PREFERENCES_NAME = "user_nicknames";
|
public static final String USER_NICKNAME_PREFERENCES_NAME = "user_nicknames";
|
||||||
public static final String USER_COLOR_PREFERENCES_NAME = "user_colors";
|
public static final String USER_COLOR_PREFERENCES_NAME = "user_colors";
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply from: rootProject.file('global.gradle')
|
||||||
|
|
||||||
|
android {
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "org.mariotaku.twidere.extension.launcher.compose"
|
||||||
|
minSdkVersion 14
|
||||||
|
targetSdkVersion 22
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':twidere.library.extension')
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /Users/mariotaku/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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.extension.launcher.compose;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.test.ApplicationTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||||
|
*/
|
||||||
|
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||||
|
public ApplicationTest() {
|
||||||
|
super(Application.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!--
|
||||||
|
~ 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest package="org.mariotaku.twidere.extension.launcher.compose"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
|
<activity android:name=".MainActivity"
|
||||||
|
android:clearTaskOnLaunch="true"
|
||||||
|
android:noHistory="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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.extension.launcher.compose;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.mariotaku.twidere.TwidereConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 15/4/21.
|
||||||
|
*/
|
||||||
|
public class MainActivity extends Activity implements TwidereConstants {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
final Intent intent = new Intent(INTENT_ACTION_COMPOSE);
|
||||||
|
intent.setPackage(TWIDERE_PACKAGE_NAME);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||||
|
try {
|
||||||
|
startActivity(intent);
|
||||||
|
} catch (ActivityNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!--
|
||||||
|
~ 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Twidere Compose Launcher</string>
|
||||||
|
</resources>
|
|
@ -32,7 +32,7 @@ import org.mariotaku.twidere.activity.iface.IControlBarActivity;
|
||||||
import org.mariotaku.twidere.app.TwidereApplication;
|
import org.mariotaku.twidere.app.TwidereApplication;
|
||||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||||
import org.mariotaku.twidere.util.ThemeUtils;
|
import org.mariotaku.twidere.util.ThemeUtils;
|
||||||
import org.mariotaku.twidere.view.iface.IExtendedView.OnFitSystemWindowsListener;
|
import org.mariotaku.twidere.view.iface.IExtendedView.OnFitSystemWindowsListener;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import java.util.ArrayList;
|
||||||
@SuppressLint("Registered")
|
@SuppressLint("Registered")
|
||||||
public class BaseActionBarActivity extends ThemedActionBarActivity implements Constants,
|
public class BaseActionBarActivity extends ThemedActionBarActivity implements Constants,
|
||||||
OnFitSystemWindowsListener, SystemWindowsInsetsCallback, IControlBarActivity,
|
OnFitSystemWindowsListener, SystemWindowsInsetsCallback, IControlBarActivity,
|
||||||
ShortcutCallback {
|
KeyboardShortcutCallback {
|
||||||
|
|
||||||
private boolean mInstanceStateSaved;
|
private boolean mInstanceStateSaved;
|
||||||
private boolean mIsVisible;
|
private boolean mIsVisible;
|
||||||
|
|
|
@ -91,7 +91,7 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||||
import org.mariotaku.twidere.util.ColorUtils;
|
import org.mariotaku.twidere.util.ColorUtils;
|
||||||
import org.mariotaku.twidere.util.CustomTabUtils;
|
import org.mariotaku.twidere.util.CustomTabUtils;
|
||||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||||
import org.mariotaku.twidere.util.MathUtils;
|
import org.mariotaku.twidere.util.MathUtils;
|
||||||
import org.mariotaku.twidere.util.MultiSelectEventHandler;
|
import org.mariotaku.twidere.util.MultiSelectEventHandler;
|
||||||
import org.mariotaku.twidere.util.ParseUtils;
|
import org.mariotaku.twidere.util.ParseUtils;
|
||||||
|
@ -287,6 +287,7 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||||
mSlidingMenu.showContent(true);
|
mSlidingMenu.showContent(true);
|
||||||
} else {
|
} else {
|
||||||
mSlidingMenu.showMenu(true);
|
mSlidingMenu.showMenu(true);
|
||||||
|
setControlBarVisibleAnimate(true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -684,16 +685,16 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||||
|
|
||||||
private boolean handleFragmentKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
private boolean handleFragmentKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||||
final Fragment fragment = getCurrentVisibleFragment();
|
final Fragment fragment = getCurrentVisibleFragment();
|
||||||
if (fragment instanceof ShortcutCallback) {
|
if (fragment instanceof KeyboardShortcutCallback) {
|
||||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleFragmentKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
private boolean handleFragmentKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||||
final Fragment fragment = getCurrentVisibleFragment();
|
final Fragment fragment = getCurrentVisibleFragment();
|
||||||
if (fragment instanceof ShortcutCallback) {
|
if (fragment instanceof KeyboardShortcutCallback) {
|
||||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
|
||||||
import org.mariotaku.twidere.fragment.support.SearchFragment;
|
import org.mariotaku.twidere.fragment.support.SearchFragment;
|
||||||
import org.mariotaku.twidere.fragment.support.UserFragment;
|
import org.mariotaku.twidere.fragment.support.UserFragment;
|
||||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||||
import org.mariotaku.twidere.util.MultiSelectEventHandler;
|
import org.mariotaku.twidere.util.MultiSelectEventHandler;
|
||||||
import org.mariotaku.twidere.util.ThemeUtils;
|
import org.mariotaku.twidere.util.ThemeUtils;
|
||||||
import org.mariotaku.twidere.util.Utils;
|
import org.mariotaku.twidere.util.Utils;
|
||||||
|
@ -221,16 +221,16 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements System
|
||||||
|
|
||||||
private boolean handleFragmentKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
private boolean handleFragmentKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||||
final Fragment fragment = getCurrentVisibleFragment();
|
final Fragment fragment = getCurrentVisibleFragment();
|
||||||
if (fragment instanceof ShortcutCallback) {
|
if (fragment instanceof KeyboardShortcutCallback) {
|
||||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleFragmentKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
private boolean handleFragmentKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||||
final Fragment fragment = getCurrentVisibleFragment();
|
final Fragment fragment = getCurrentVisibleFragment();
|
||||||
if (fragment instanceof ShortcutCallback) {
|
if (fragment instanceof KeyboardShortcutCallback) {
|
||||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
super.onBaseViewCreated(view, savedInstanceState);
|
super.onBaseViewCreated(view, savedInstanceState);
|
||||||
mImageView = (SubsamplingScaleImageView) view.findViewById(R.id.image_view);
|
mImageView = (SubsamplingScaleImageView) view.findViewById(R.id.image_view);
|
||||||
mGifImageView = (GifTextureView) view.findViewById(R.id.gif_image_view);
|
mGifImageView = (GifTextureView) view.findViewById(R.id.gif_image_view);
|
||||||
mProgressBar = (ProgressWheel) view.findViewById(R.id.progress);
|
mProgressBar = (ProgressWheel) view.findViewById(R.id.load_progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -324,6 +324,11 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
activity.setBarVisibility(false);
|
activity.setBarVisibility(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onZoomOut() {
|
||||||
|
final MediaViewerActivity activity = (MediaViewerActivity) getActivity();
|
||||||
|
activity.setBarVisibility(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
super.onPrepareOptionsMenu(menu);
|
super.onPrepareOptionsMenu(menu);
|
||||||
|
@ -349,21 +354,11 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
shareProvider.setShareIntent(intent);
|
shareProvider.setShareIntent(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onZoomOut() {
|
|
||||||
final MediaViewerActivity activity = (MediaViewerActivity) getActivity();
|
|
||||||
activity.setBarVisibility(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParcelableMedia getMedia() {
|
private ParcelableMedia getMedia() {
|
||||||
final Bundle args = getArguments();
|
final Bundle args = getArguments();
|
||||||
return args.getParcelable(EXTRA_MEDIA);
|
return args.getParcelable(EXTRA_MEDIA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
||||||
inflater.inflate(R.menu.menu_media_viewer_image_page, menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadImage() {
|
private void loadImage() {
|
||||||
getLoaderManager().destroyLoader(0);
|
getLoaderManager().destroyLoader(0);
|
||||||
if (!mLoaderInitialized) {
|
if (!mLoaderInitialized) {
|
||||||
|
@ -387,22 +382,8 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
switch (item.getItemId()) {
|
inflater.inflate(R.menu.menu_media_viewer_image_page, menu);
|
||||||
case MENU_OPEN_IN_BROWSER: {
|
|
||||||
openInBrowser();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case MENU_SAVE: {
|
|
||||||
saveToGallery();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case MENU_REFRESH: {
|
|
||||||
loadImage();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveToGallery() {
|
private void saveToGallery() {
|
||||||
|
@ -427,6 +408,25 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
// mImageView.resetScale();
|
// mImageView.resetScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case MENU_OPEN_IN_BROWSER: {
|
||||||
|
openInBrowser();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case MENU_SAVE: {
|
||||||
|
saveToGallery();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case MENU_REFRESH: {
|
||||||
|
loadImage();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||||
|
@ -526,6 +526,7 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
private SaveFileTask mSaveFileTask;
|
private SaveFileTask mSaveFileTask;
|
||||||
private File mVideoFile;
|
private File mVideoFile;
|
||||||
private Pair<String, String> mVideoUrlAndType;
|
private Pair<String, String> mVideoUrlAndType;
|
||||||
|
private ProgressWheel mProgressBar;
|
||||||
|
|
||||||
public boolean isLoopEnabled() {
|
public boolean isLoopEnabled() {
|
||||||
return getArguments().getBoolean(EXTRA_LOOP, false);
|
return getArguments().getBoolean(EXTRA_LOOP, false);
|
||||||
|
@ -544,13 +545,6 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
// mVideoViewProgress.setVisibility(View.GONE);
|
// mVideoViewProgress.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBaseViewCreated(View view, Bundle savedInstanceState) {
|
|
||||||
super.onBaseViewCreated(view, savedInstanceState);
|
|
||||||
mVideoView = (TextureVideoView) view.findViewById(R.id.video_view);
|
|
||||||
mVideoViewProgress = (ProgressBar) view.findViewById(R.id.video_view_progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||||
mVideoViewProgress.removeCallbacks(mVideoProgressRunnable);
|
mVideoViewProgress.removeCallbacks(mVideoProgressRunnable);
|
||||||
|
@ -558,6 +552,14 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBaseViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
super.onBaseViewCreated(view, savedInstanceState);
|
||||||
|
mVideoView = (TextureVideoView) view.findViewById(R.id.video_view);
|
||||||
|
mVideoViewProgress = (ProgressBar) view.findViewById(R.id.video_view_progress);
|
||||||
|
mProgressBar = (ProgressWheel) view.findViewById(R.id.load_progress);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepared(MediaPlayer mp) {
|
public void onPrepared(MediaPlayer mp) {
|
||||||
if (getUserVisibleHint()) {
|
if (getUserVisibleHint()) {
|
||||||
|
@ -574,6 +576,22 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVideoLoadingCancelled(String uri, VideoLoadingListener listener) {
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
mProgressBar.setProgress(0);
|
||||||
|
invalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVideoLoadingComplete(String uri, VideoLoadingListener listener, File file) {
|
||||||
|
mVideoView.setVideoURI(Uri.fromFile(file));
|
||||||
|
mVideoFile = file;
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
mProgressBar.setProgress(0);
|
||||||
|
invalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
@ -590,60 +608,32 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoLoadingCancelled(String uri, VideoLoadingListener listener) {
|
public void onVideoLoadingFailed(String uri, VideoLoadingListener listener, Exception e) {
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
mProgressBar.setProgress(0);
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVideoLoadingProgressUpdate(String uri, VideoLoadingListener listener, int current, int total) {
|
||||||
|
if (total <= 0) {
|
||||||
|
if (!mProgressBar.isSpinning()) {
|
||||||
|
mProgressBar.spin();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mProgressBar.setProgress(current / (float) total);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
return inflater.inflate(R.layout.fragment_media_page_video, container, false);
|
return inflater.inflate(R.layout.fragment_media_page_video, container, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoLoadingComplete(String uri, VideoLoadingListener listener, File file) {
|
|
||||||
mVideoView.setVideoURI(Uri.fromFile(file));
|
|
||||||
mVideoFile = file;
|
|
||||||
invalidateOptionsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoLoadingFailed(String uri, VideoLoadingListener listener, Exception e) {
|
|
||||||
invalidateOptionsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoLoadingProgressUpdate(String uri, VideoLoadingListener listener, int current, int total) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
|
||||||
super.onPrepareOptionsMenu(menu);
|
|
||||||
final File file = mVideoFile;
|
|
||||||
final Pair<String, String> linkAndType = mVideoUrlAndType;
|
|
||||||
final boolean isLoading = getLoaderManager().hasRunningLoaders();
|
|
||||||
final boolean hasVideo = file != null && file.exists() && linkAndType != null;
|
|
||||||
MenuUtils.setMenuItemAvailability(menu, R.id.refresh, !hasVideo && !isLoading);
|
|
||||||
MenuUtils.setMenuItemAvailability(menu, R.id.share, hasVideo && !isLoading);
|
|
||||||
MenuUtils.setMenuItemAvailability(menu, R.id.save, hasVideo && !isLoading);
|
|
||||||
if (!hasVideo) return;
|
|
||||||
final MenuItem shareItem = menu.findItem(R.id.share);
|
|
||||||
final ShareActionProvider shareProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem);
|
|
||||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
|
||||||
final Uri fileUri = Uri.fromFile(file);
|
|
||||||
intent.setDataAndType(fileUri, linkAndType.second);
|
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
|
||||||
final MediaViewerActivity activity = (MediaViewerActivity) getActivity();
|
|
||||||
if (activity.hasStatus()) {
|
|
||||||
final ParcelableStatus status = activity.getStatus();
|
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, Utils.getStatusShareText(activity, status));
|
|
||||||
intent.putExtra(Intent.EXTRA_SUBJECT, Utils.getStatusShareSubject(activity, status));
|
|
||||||
}
|
|
||||||
shareProvider.setShareIntent(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoLoadingStarted(String uri, VideoLoadingListener listener) {
|
public void onVideoLoadingStarted(String uri, VideoLoadingListener listener) {
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
mProgressBar.spin();
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,11 +660,6 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
||||||
inflater.inflate(R.menu.menu_media_viewer_video_page, menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParcelableMedia getMedia() {
|
private ParcelableMedia getMedia() {
|
||||||
final Bundle args = getArguments();
|
final Bundle args = getArguments();
|
||||||
return args.getParcelable(EXTRA_MEDIA);
|
return args.getParcelable(EXTRA_MEDIA);
|
||||||
|
@ -696,18 +681,29 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
switch (item.getItemId()) {
|
super.onPrepareOptionsMenu(menu);
|
||||||
case MENU_SAVE: {
|
final File file = mVideoFile;
|
||||||
saveToGallery();
|
final Pair<String, String> linkAndType = mVideoUrlAndType;
|
||||||
return true;
|
final boolean isLoading = linkAndType != null && mVideoLoader.isLoading(linkAndType.first);
|
||||||
}
|
final boolean hasVideo = file != null && file.exists() && linkAndType != null;
|
||||||
case MENU_REFRESH: {
|
MenuUtils.setMenuItemAvailability(menu, R.id.refresh, !hasVideo && !isLoading);
|
||||||
loadVideo();
|
MenuUtils.setMenuItemAvailability(menu, R.id.share, hasVideo && !isLoading);
|
||||||
return true;
|
MenuUtils.setMenuItemAvailability(menu, R.id.save, hasVideo && !isLoading);
|
||||||
}
|
if (!hasVideo) return;
|
||||||
|
final MenuItem shareItem = menu.findItem(R.id.share);
|
||||||
|
final ShareActionProvider shareProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem);
|
||||||
|
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
|
final Uri fileUri = Uri.fromFile(file);
|
||||||
|
intent.setDataAndType(fileUri, linkAndType.second);
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
||||||
|
final MediaViewerActivity activity = (MediaViewerActivity) getActivity();
|
||||||
|
if (activity.hasStatus()) {
|
||||||
|
final ParcelableStatus status = activity.getStatus();
|
||||||
|
intent.putExtra(Intent.EXTRA_TEXT, Utils.getStatusShareText(activity, status));
|
||||||
|
intent.putExtra(Intent.EXTRA_SUBJECT, Utils.getStatusShareSubject(activity, status));
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
shareProvider.setShareIntent(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class VideoPlayProgressRunnable implements Runnable {
|
private static class VideoPlayProgressRunnable implements Runnable {
|
||||||
|
@ -735,6 +731,28 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.menu_media_viewer_video_page, menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case MENU_SAVE: {
|
||||||
|
saveToGallery();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case MENU_REFRESH: {
|
||||||
|
loadVideo();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
|
@ -32,8 +32,9 @@ import org.mariotaku.twidere.model.ParcelableMedia;
|
||||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||||
import org.mariotaku.twidere.util.ReadStateManager;
|
import org.mariotaku.twidere.util.ReadStateManager;
|
||||||
|
import org.mariotaku.twidere.util.RecyclerViewNavigationHelper;
|
||||||
import org.mariotaku.twidere.util.RecyclerViewUtils;
|
import org.mariotaku.twidere.util.RecyclerViewUtils;
|
||||||
import org.mariotaku.twidere.util.Utils;
|
import org.mariotaku.twidere.util.Utils;
|
||||||
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
|
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
|
||||||
|
@ -49,7 +50,7 @@ import static org.mariotaku.twidere.util.Utils.setMenuForStatus;
|
||||||
* Created by mariotaku on 14/11/5.
|
* Created by mariotaku on 14/11/5.
|
||||||
*/
|
*/
|
||||||
public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<AbsStatusesAdapter<Data>>
|
public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<AbsStatusesAdapter<Data>>
|
||||||
implements LoaderCallbacks<Data>, StatusAdapterListener, ShortcutCallback {
|
implements LoaderCallbacks<Data>, StatusAdapterListener, KeyboardShortcutCallback {
|
||||||
|
|
||||||
private final Object mStatusesBusCallback;
|
private final Object mStatusesBusCallback;
|
||||||
private SharedPreferences mPreferences;
|
private SharedPreferences mPreferences;
|
||||||
|
@ -71,7 +72,7 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
||||||
getFragmentManager(), getTwitterWrapper(), status, item);
|
getFragmentManager(), getTwitterWrapper(), status, item);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private int mPositionBackup;
|
private RecyclerViewNavigationHelper mRecyclerViewNavigationHelper;
|
||||||
|
|
||||||
protected AbsStatusesFragment() {
|
protected AbsStatusesFragment() {
|
||||||
mStatusesBusCallback = createMessageBusCallback();
|
mStatusesBusCallback = createMessageBusCallback();
|
||||||
|
@ -133,39 +134,9 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
public boolean handleKeyboardShortcutRepeat(final int keyCode, final int repeatCount,
|
||||||
if (!KeyboardShortcutsHandler.isValidForHotkey(keyCode, event)) return false;
|
@NonNull final KeyEvent event) {
|
||||||
String action = mKeyboardShortcutsHandler.getKeyAction("navigation", keyCode, event);
|
return mRecyclerViewNavigationHelper.handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||||
final LinearLayoutManager layoutManager = getLayoutManager();
|
|
||||||
final RecyclerView recyclerView = getRecyclerView();
|
|
||||||
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(recyclerView, layoutManager.getFocusedChild());
|
|
||||||
final int position;
|
|
||||||
if (focusedChild != null) {
|
|
||||||
position = recyclerView.getChildLayoutPosition(focusedChild);
|
|
||||||
} else if (layoutManager.findFirstVisibleItemPosition() == 0) {
|
|
||||||
position = -1;
|
|
||||||
} else {
|
|
||||||
final int itemCount = getAdapter().getItemCount();
|
|
||||||
if (layoutManager.findLastVisibleItemPosition() == itemCount - 1) {
|
|
||||||
position = itemCount;
|
|
||||||
} else {
|
|
||||||
position = mPositionBackup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mPositionBackup = position;
|
|
||||||
if (action != null) {
|
|
||||||
switch (action) {
|
|
||||||
case "navigation.previous": {
|
|
||||||
RecyclerViewUtils.focusNavigate(recyclerView, layoutManager, position, -1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case "navigation.next": {
|
|
||||||
RecyclerViewUtils.focusNavigate(recyclerView, layoutManager, position, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -374,7 +345,10 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
||||||
final FragmentActivity activity = getActivity();
|
final FragmentActivity activity = getActivity();
|
||||||
final TwidereApplication application = TwidereApplication.getInstance(activity);
|
final TwidereApplication application = TwidereApplication.getInstance(activity);
|
||||||
mKeyboardShortcutsHandler = application.getKeyboardShortcutsHandler();
|
mKeyboardShortcutsHandler = application.getKeyboardShortcutsHandler();
|
||||||
getAdapter().setListener(this);
|
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||||
|
final RecyclerView recyclerView = getRecyclerView();
|
||||||
|
final LinearLayoutManager layoutManager = getLayoutManager();
|
||||||
|
adapter.setListener(this);
|
||||||
getScrollListener().setOnScrollListener(new OnScrollListener() {
|
getScrollListener().setOnScrollListener(new OnScrollListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||||
|
@ -383,6 +357,7 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
mRecyclerViewNavigationHelper = new RecyclerViewNavigationHelper(mKeyboardShortcutsHandler, recyclerView, layoutManager, adapter);
|
||||||
|
|
||||||
final Bundle loaderArgs = new Bundle(getArguments());
|
final Bundle loaderArgs = new Bundle(getArguments());
|
||||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||||
|
|
|
@ -21,32 +21,61 @@ package org.mariotaku.twidere.fragment.support;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
import android.support.v4.util.Pair;
|
import android.support.v4.util.Pair;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.mariotaku.twidere.adapter.AbsUsersAdapter;
|
import org.mariotaku.twidere.adapter.AbsUsersAdapter;
|
||||||
import org.mariotaku.twidere.adapter.AbsUsersAdapter.UserAdapterListener;
|
import org.mariotaku.twidere.adapter.AbsUsersAdapter.UserAdapterListener;
|
||||||
|
import org.mariotaku.twidere.app.TwidereApplication;
|
||||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
|
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
|
||||||
import org.mariotaku.twidere.model.ParcelableUser;
|
import org.mariotaku.twidere.model.ParcelableUser;
|
||||||
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||||
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||||
|
import org.mariotaku.twidere.util.RecyclerViewNavigationHelper;
|
||||||
import org.mariotaku.twidere.util.Utils;
|
import org.mariotaku.twidere.util.Utils;
|
||||||
import org.mariotaku.twidere.view.holder.UserViewHolder;
|
import org.mariotaku.twidere.view.holder.UserViewHolder;
|
||||||
|
|
||||||
abstract class AbsUsersFragment<Data> extends AbsContentListFragment<AbsUsersAdapter<Data>> implements LoaderCallbacks<Data>, UserAdapterListener {
|
abstract class AbsUsersFragment<Data> extends AbsContentListFragment<AbsUsersAdapter<Data>>
|
||||||
|
implements LoaderCallbacks<Data>, UserAdapterListener, KeyboardShortcutCallback {
|
||||||
|
|
||||||
|
private KeyboardShortcutsHandler mKeyboardShortcutsHandler;
|
||||||
|
private RecyclerViewNavigationHelper mRecyclerViewNavigationHelper;
|
||||||
|
|
||||||
public final Data getData() {
|
public final Data getData() {
|
||||||
return getAdapter().getData();
|
return getAdapter().getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||||
|
return mRecyclerViewNavigationHelper.handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
getAdapter().setListener(this);
|
final FragmentActivity activity = getActivity();
|
||||||
|
final TwidereApplication application = TwidereApplication.getInstance(activity);
|
||||||
|
mKeyboardShortcutsHandler = application.getKeyboardShortcutsHandler();
|
||||||
|
final AbsUsersAdapter<Data> adapter = getAdapter();
|
||||||
|
final RecyclerView recyclerView = getRecyclerView();
|
||||||
|
final LinearLayoutManager layoutManager = getLayoutManager();
|
||||||
|
adapter.setListener(this);
|
||||||
|
|
||||||
|
mRecyclerViewNavigationHelper = new RecyclerViewNavigationHelper(mKeyboardShortcutsHandler, recyclerView, layoutManager, adapter);
|
||||||
final Bundle loaderArgs = new Bundle(getArguments());
|
final Bundle loaderArgs = new Bundle(getArguments());
|
||||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||||
getLoaderManager().initLoader(0, loaderArgs, this);
|
getLoaderManager().initLoader(0, loaderArgs, this);
|
||||||
|
|
|
@ -29,6 +29,7 @@ import android.graphics.Rect;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||||
|
@ -40,6 +41,7 @@ import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
|
||||||
import android.support.v7.widget.FixedLinearLayoutManager;
|
import android.support.v7.widget.FixedLinearLayoutManager;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -70,7 +72,10 @@ import org.mariotaku.twidere.util.AsyncTaskUtils;
|
||||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||||
import org.mariotaku.twidere.util.ContentListScrollListener;
|
import org.mariotaku.twidere.util.ContentListScrollListener;
|
||||||
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListSupport;
|
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListSupport;
|
||||||
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||||
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||||
|
import org.mariotaku.twidere.util.RecyclerViewNavigationHelper;
|
||||||
import org.mariotaku.twidere.util.ThemeUtils;
|
import org.mariotaku.twidere.util.ThemeUtils;
|
||||||
import org.mariotaku.twidere.util.Utils;
|
import org.mariotaku.twidere.util.Utils;
|
||||||
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
|
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
|
||||||
|
@ -85,7 +90,7 @@ import static org.mariotaku.twidere.util.Utils.openMessageConversation;
|
||||||
|
|
||||||
public class DirectMessagesFragment extends BaseSupportFragment implements LoaderCallbacks<Cursor>,
|
public class DirectMessagesFragment extends BaseSupportFragment implements LoaderCallbacks<Cursor>,
|
||||||
RefreshScrollTopInterface, OnRefreshListener, MessageEntriesAdapterListener,
|
RefreshScrollTopInterface, OnRefreshListener, MessageEntriesAdapterListener,
|
||||||
ControlBarOffsetListener, ContentListSupport {
|
ControlBarOffsetListener, ContentListSupport, KeyboardShortcutCallback {
|
||||||
|
|
||||||
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
|
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
|
||||||
this, 0, this);
|
this, 0, this);
|
||||||
|
@ -100,11 +105,54 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
private View mProgressContainer;
|
private View mProgressContainer;
|
||||||
private LinearLayoutManager mLayoutManager;
|
private LinearLayoutManager mLayoutManager;
|
||||||
|
private KeyboardShortcutsHandler mKeyboardShortcutsHandler;
|
||||||
|
private RecyclerViewNavigationHelper mRecyclerViewNavigationHelper;
|
||||||
|
private Rect mSystemWindowsInsets = new Rect();
|
||||||
|
private int mControlBarOffsetPixels;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageEntriesAdapter getAdapter() {
|
||||||
|
return mAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRefreshing() {
|
||||||
|
if (mSwipeRefreshLayout == null || mAdapter == null) return false;
|
||||||
|
return mSwipeRefreshLayout.isRefreshing() || mAdapter.isLoadMoreIndicatorVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRefreshing(boolean refreshing) {
|
||||||
|
if (mAdapter == null || refreshing == mSwipeRefreshLayout.isRefreshing()) return;
|
||||||
|
mSwipeRefreshLayout.setRefreshing(refreshing && !mAdapter.isLoadMoreIndicatorVisible());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMoreContents() {
|
||||||
|
loadMoreMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setControlVisible(boolean visible) {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity instanceof BaseActionBarActivity) {
|
||||||
|
((BaseActionBarActivity) activity).setControlBarVisibleAnimate(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final LongSparseArray<Set<Long>> getUnreadCountsToRemove() {
|
public final LongSparseArray<Set<Long>> getUnreadCountsToRemove() {
|
||||||
return mUnreadCountsToRemove;
|
return mUnreadCountsToRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||||
|
return mRecyclerViewNavigationHelper.handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Activity activity) {
|
public void onAttach(Activity activity) {
|
||||||
super.onAttach(activity);
|
super.onAttach(activity);
|
||||||
|
@ -113,9 +161,98 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_recycler_view, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
private Rect mSystemWindowsInsets = new Rect();
|
@Override
|
||||||
private int mControlBarOffsetPixels;
|
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||||
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
final View view = getView();
|
||||||
|
if (view == null) throw new AssertionError();
|
||||||
|
final TwidereApplication application = TwidereApplication.getInstance(getActivity());
|
||||||
|
mKeyboardShortcutsHandler = application.getKeyboardShortcutsHandler();
|
||||||
|
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||||
|
final Context viewContext = view.getContext();
|
||||||
|
mMultiSelectManager = getMultiSelectManager();
|
||||||
|
mAdapter = new MessageEntriesAdapter(viewContext);
|
||||||
|
mAdapter.setListener(this);
|
||||||
|
mLayoutManager = new FixedLinearLayoutManager(viewContext);
|
||||||
|
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
||||||
|
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||||
|
mSwipeRefreshLayout.setColorSchemeColors(ThemeUtils.getUserAccentColor(viewContext));
|
||||||
|
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||||
|
mRecyclerView.setAdapter(mAdapter);
|
||||||
|
mRecyclerViewNavigationHelper = new RecyclerViewNavigationHelper(mKeyboardShortcutsHandler, mRecyclerView, mLayoutManager, mAdapter);
|
||||||
|
|
||||||
|
final ContentListScrollListener scrollListener = new ContentListScrollListener(this);
|
||||||
|
scrollListener.setTouchSlop(ViewConfiguration.get(viewContext).getScaledTouchSlop());
|
||||||
|
mRecyclerView.setOnScrollListener(scrollListener);
|
||||||
|
|
||||||
|
final DividerItemDecoration itemDecoration = new DividerItemDecoration(viewContext, mLayoutManager.getOrientation());
|
||||||
|
final Resources res = viewContext.getResources();
|
||||||
|
final int decorPaddingLeft = res.getDimensionPixelSize(R.dimen.element_spacing_normal) * 3
|
||||||
|
+ res.getDimensionPixelSize(R.dimen.icon_size_status_profile_image);
|
||||||
|
itemDecoration.setPadding(decorPaddingLeft, 0, 0, 0);
|
||||||
|
itemDecoration.setDecorationEndOffset(1);
|
||||||
|
mRecyclerView.addItemDecoration(itemDecoration);
|
||||||
|
getLoaderManager().initLoader(0, null, this);
|
||||||
|
setListShown(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
final ContentResolver resolver = getContentResolver();
|
||||||
|
resolver.registerContentObserver(Accounts.CONTENT_URI, true, mReloadContentObserver);
|
||||||
|
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
||||||
|
bus.register(this);
|
||||||
|
mAdapter.updateReadState();
|
||||||
|
updateRefreshState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
||||||
|
bus.unregister(this);
|
||||||
|
final ContentResolver resolver = getContentResolver();
|
||||||
|
resolver.unregisterContentObserver(mReloadContentObserver);
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case MENU_COMPOSE: {
|
||||||
|
openMessageConversation(getActivity(), -1, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBaseViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onBaseViewCreated(view, savedInstanceState);
|
||||||
|
mProgressContainer = view.findViewById(R.id.progress_container);
|
||||||
|
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_layout);
|
||||||
|
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetach() {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity instanceof IControlBarActivity) {
|
||||||
|
((IControlBarActivity) activity).unregisterControlBarOffsetListener(this);
|
||||||
|
}
|
||||||
|
super.onDetach();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUserVisibleHint(final boolean isVisibleToUser) {
|
||||||
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void fitSystemWindows(Rect insets) {
|
protected void fitSystemWindows(Rect insets) {
|
||||||
|
@ -131,54 +268,6 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
updateRefreshProgressOffset();
|
updateRefreshProgressOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateRefreshProgressOffset() {
|
|
||||||
if (mSystemWindowsInsets.top == 0 || mSwipeRefreshLayout == null || isRefreshing()) return;
|
|
||||||
final float density = getResources().getDisplayMetrics().density;
|
|
||||||
final int progressCircleDiameter = mSwipeRefreshLayout.getProgressCircleDiameter();
|
|
||||||
final int swipeStart = (mSystemWindowsInsets.top - mControlBarOffsetPixels) - progressCircleDiameter;
|
|
||||||
// 64: SwipeRefreshLayout.DEFAULT_CIRCLE_TARGET
|
|
||||||
final int swipeDistance = Math.round(64 * density);
|
|
||||||
mSwipeRefreshLayout.setProgressViewOffset(true, swipeStart, swipeStart + swipeDistance);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDetach() {
|
|
||||||
final FragmentActivity activity = getActivity();
|
|
||||||
if (activity instanceof IControlBarActivity) {
|
|
||||||
((IControlBarActivity) activity).unregisterControlBarOffsetListener(this);
|
|
||||||
}
|
|
||||||
super.onDetach();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntryClick(int position, DirectMessageEntry entry) {
|
|
||||||
Utils.openMessageConversation(getActivity(), entry.account_id, entry.conversation_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUserClick(int position, DirectMessageEntry entry) {
|
|
||||||
Utils.openUserProfile(getActivity(), entry.account_id, entry.conversation_id, entry.screen_name, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRefresh() {
|
|
||||||
triggerRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setListShown(boolean shown) {
|
|
||||||
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
|
|
||||||
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBaseViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
|
||||||
super.onBaseViewCreated(view, savedInstanceState);
|
|
||||||
mProgressContainer = view.findViewById(R.id.progress_container);
|
|
||||||
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_layout);
|
|
||||||
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
|
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
|
||||||
final Uri uri = DirectMessages.ConversationEntries.CONTENT_URI;
|
final Uri uri = DirectMessages.ConversationEntries.CONTENT_URI;
|
||||||
|
@ -211,54 +300,15 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public void onEntryClick(int position, DirectMessageEntry entry) {
|
||||||
return inflater.inflate(R.layout.fragment_recycler_view, container, false);
|
Utils.openMessageConversation(getActivity(), entry.account_id, entry.conversation_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
public void onUserClick(int position, DirectMessageEntry entry) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
Utils.openUserProfile(getActivity(), entry.account_id, entry.conversation_id, entry.screen_name, null);
|
||||||
final View view = getView();
|
|
||||||
if (view == null) throw new AssertionError();
|
|
||||||
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
|
||||||
final Context viewContext = view.getContext();
|
|
||||||
mMultiSelectManager = getMultiSelectManager();
|
|
||||||
mAdapter = new MessageEntriesAdapter(viewContext);
|
|
||||||
mAdapter.setListener(this);
|
|
||||||
mLayoutManager = new FixedLinearLayoutManager(viewContext);
|
|
||||||
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
|
||||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
|
||||||
mSwipeRefreshLayout.setColorSchemeColors(ThemeUtils.getUserAccentColor(viewContext));
|
|
||||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
|
||||||
mRecyclerView.setAdapter(mAdapter);
|
|
||||||
|
|
||||||
final ContentListScrollListener scrollListener = new ContentListScrollListener(this);
|
|
||||||
scrollListener.setTouchSlop(ViewConfiguration.get(viewContext).getScaledTouchSlop());
|
|
||||||
mRecyclerView.setOnScrollListener(scrollListener);
|
|
||||||
|
|
||||||
final DividerItemDecoration itemDecoration = new DividerItemDecoration(viewContext, mLayoutManager.getOrientation());
|
|
||||||
final Resources res = viewContext.getResources();
|
|
||||||
final int decorPaddingLeft = res.getDimensionPixelSize(R.dimen.element_spacing_normal) * 3
|
|
||||||
+ res.getDimensionPixelSize(R.dimen.icon_size_status_profile_image);
|
|
||||||
itemDecoration.setPadding(decorPaddingLeft, 0, 0, 0);
|
|
||||||
itemDecoration.setDecorationEndOffset(1);
|
|
||||||
mRecyclerView.addItemDecoration(itemDecoration);
|
|
||||||
getLoaderManager().initLoader(0, null, this);
|
|
||||||
setListShown(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStart() {
|
|
||||||
super.onStart();
|
|
||||||
final ContentResolver resolver = getContentResolver();
|
|
||||||
resolver.registerContentObserver(Accounts.CONTENT_URI, true, mReloadContentObserver);
|
|
||||||
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
|
||||||
bus.register(this);
|
|
||||||
mAdapter.updateReadState();
|
|
||||||
updateRefreshState();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onGetMessagesTaskChanged(GetMessagesTaskEvent event) {
|
public void onGetMessagesTaskChanged(GetMessagesTaskEvent event) {
|
||||||
if (event.uri.equals(Inbox.CONTENT_URI) && !event.running) {
|
if (event.uri.equals(Inbox.CONTENT_URI) && !event.running) {
|
||||||
|
@ -269,23 +319,8 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onRefresh() {
|
||||||
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
triggerRefresh();
|
||||||
bus.unregister(this);
|
|
||||||
final ContentResolver resolver = getContentResolver();
|
|
||||||
resolver.unregisterContentObserver(mReloadContentObserver);
|
|
||||||
super.onStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case MENU_COMPOSE: {
|
|
||||||
openMessageConversation(getActivity(), -1, -1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -323,12 +358,6 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUserVisibleHint(final boolean isVisibleToUser) {
|
|
||||||
super.setUserVisibleHint(isVisibleToUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected long getAccountId() {
|
protected long getAccountId() {
|
||||||
final Bundle args = getArguments();
|
final Bundle args = getArguments();
|
||||||
return args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
|
return args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
|
||||||
|
@ -339,17 +368,6 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
setRefreshing(twitter != null && (twitter.isReceivedDirectMessagesRefreshing() || twitter.isSentDirectMessagesRefreshing()));
|
setRefreshing(twitter != null && (twitter.isReceivedDirectMessagesRefreshing() || twitter.isSentDirectMessagesRefreshing()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRefreshing(boolean refreshing) {
|
|
||||||
if (mAdapter == null || refreshing == mSwipeRefreshLayout.isRefreshing()) return;
|
|
||||||
mSwipeRefreshLayout.setRefreshing(refreshing && !mAdapter.isLoadMoreIndicatorVisible());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRefreshing() {
|
|
||||||
if (mSwipeRefreshLayout == null || mAdapter == null) return false;
|
|
||||||
return mSwipeRefreshLayout.isRefreshing() || mAdapter.isLoadMoreIndicatorVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addReadPosition(final int firstVisibleItem) {
|
private void addReadPosition(final int firstVisibleItem) {
|
||||||
if (mFirstVisibleItem != firstVisibleItem) {
|
if (mFirstVisibleItem != firstVisibleItem) {
|
||||||
mReadPositions.add(firstVisibleItem);
|
mReadPositions.add(firstVisibleItem);
|
||||||
|
@ -395,24 +413,6 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessageEntriesAdapter getAdapter() {
|
|
||||||
return mAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setControlVisible(boolean visible) {
|
|
||||||
final FragmentActivity activity = getActivity();
|
|
||||||
if (activity instanceof BaseActionBarActivity) {
|
|
||||||
((BaseActionBarActivity) activity).setControlBarVisibleAnimate(visible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadMoreContents() {
|
|
||||||
loadMoreMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeUnreadCounts() {
|
private void removeUnreadCounts() {
|
||||||
if (mRemoveUnreadCountsTask != null && mRemoveUnreadCountsTask.getStatus() == AsyncTask.Status.RUNNING)
|
if (mRemoveUnreadCountsTask != null && mRemoveUnreadCountsTask.getStatus() == AsyncTask.Status.RUNNING)
|
||||||
return;
|
return;
|
||||||
|
@ -420,6 +420,21 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
||||||
AsyncTaskUtils.executeTask(mRemoveUnreadCountsTask);
|
AsyncTaskUtils.executeTask(mRemoveUnreadCountsTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setListShown(boolean shown) {
|
||||||
|
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
|
||||||
|
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateRefreshProgressOffset() {
|
||||||
|
if (mSystemWindowsInsets.top == 0 || mSwipeRefreshLayout == null || isRefreshing()) return;
|
||||||
|
final float density = getResources().getDisplayMetrics().density;
|
||||||
|
final int progressCircleDiameter = mSwipeRefreshLayout.getProgressCircleDiameter();
|
||||||
|
final int swipeStart = (mSystemWindowsInsets.top - mControlBarOffsetPixels) - progressCircleDiameter;
|
||||||
|
// 64: SwipeRefreshLayout.DEFAULT_CIRCLE_TARGET
|
||||||
|
final int swipeDistance = Math.round(64 * density);
|
||||||
|
mSwipeRefreshLayout.setProgressViewOffset(true, swipeStart, swipeStart + swipeDistance);
|
||||||
|
}
|
||||||
|
|
||||||
static class RemoveUnreadCountsTask extends AsyncTask<Object, Object, Object> {
|
static class RemoveUnreadCountsTask extends AsyncTask<Object, Object, Object> {
|
||||||
private final Set<Integer> read_positions;
|
private final Set<Integer> read_positions;
|
||||||
private final MessageEntriesAdapter adapter;
|
private final MessageEntriesAdapter adapter;
|
||||||
|
|
|
@ -249,7 +249,7 @@ public class KeyboardShortcutsHandler implements Constants {
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface ShortcutCallback {
|
public static interface KeyboardShortcutCallback {
|
||||||
boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event);
|
boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event);
|
||||||
|
|
||||||
boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event);
|
boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event);
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.RecyclerView.Adapter;
|
||||||
|
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 15/4/21.
|
||||||
|
*/
|
||||||
|
public class RecyclerViewNavigationHelper {
|
||||||
|
|
||||||
|
private int positionBackup;
|
||||||
|
private final KeyboardShortcutsHandler handler;
|
||||||
|
private final RecyclerView view;
|
||||||
|
private final LinearLayoutManager manager;
|
||||||
|
private final Adapter<ViewHolder> adapter;
|
||||||
|
|
||||||
|
public RecyclerViewNavigationHelper(KeyboardShortcutsHandler handler, RecyclerView view,
|
||||||
|
LinearLayoutManager manager, Adapter<ViewHolder> adapter) {
|
||||||
|
this.handler = handler;
|
||||||
|
this.view = view;
|
||||||
|
this.manager = manager;
|
||||||
|
this.adapter = adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||||
|
final String action = handler.getKeyAction("navigation", keyCode, event);
|
||||||
|
if (action == null) return false;
|
||||||
|
final LinearLayoutManager layoutManager = this.manager;
|
||||||
|
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(view, layoutManager.getFocusedChild());
|
||||||
|
final int position;
|
||||||
|
if (focusedChild != null) {
|
||||||
|
position = view.getChildLayoutPosition(focusedChild);
|
||||||
|
} else if (layoutManager.findFirstVisibleItemPosition() == 0) {
|
||||||
|
position = -1;
|
||||||
|
} else {
|
||||||
|
final int itemCount = adapter.getItemCount();
|
||||||
|
if (layoutManager.findLastVisibleItemPosition() == itemCount - 1) {
|
||||||
|
position = itemCount;
|
||||||
|
} else {
|
||||||
|
position = positionBackup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
positionBackup = position;
|
||||||
|
switch (action) {
|
||||||
|
case "navigation.previous": {
|
||||||
|
RecyclerViewUtils.focusNavigate(view, layoutManager, position, -1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case "navigation.next": {
|
||||||
|
RecyclerViewUtils.focusNavigate(view, layoutManager, position, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3576,9 +3576,9 @@ public final class Utils implements Constants, TwitterConstants {
|
||||||
final PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
|
final PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
|
||||||
final String version_name = pi.versionName;
|
final String version_name = pi.versionName;
|
||||||
cb.setClientVersion(pi.versionName);
|
cb.setClientVersion(pi.versionName);
|
||||||
cb.setClientName(APP_NAME);
|
cb.setClientName(TWIDERE_APP_NAME);
|
||||||
cb.setClientURL(APP_PROJECT_URL);
|
cb.setClientURL(TWIDERE_PROJECT_URL);
|
||||||
cb.setHttpUserAgent(APP_NAME + " " + APP_PROJECT_URL + " / " + version_name
|
cb.setHttpUserAgent(TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL + " / " + version_name
|
||||||
+ (gzipCompressing ? " (gzip)" : ""));
|
+ (gzipCompressing ? " (gzip)" : ""));
|
||||||
} catch (final PackageManager.NameNotFoundException e) {
|
} catch (final PackageManager.NameNotFoundException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
|
|
|
@ -69,6 +69,10 @@ public class VideoLoader {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLoading(String url) {
|
||||||
|
return mTaskManager.hasRunningTasksForTag(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public int loadVideo(String uri, VideoLoadingListener listener) {
|
public int loadVideo(String uri, VideoLoadingListener listener) {
|
||||||
if (mTaskManager.hasRunningTasksForTag(uri)) {
|
if (mTaskManager.hasRunningTasksForTag(uri)) {
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
<pl.droidsonroids.gif.GifTextureView
|
<pl.droidsonroids.gif.GifTextureView
|
||||||
android:id="@+id/gif_image_view"
|
android:id="@+id/gif_image_view"
|
||||||
|
@ -35,10 +36,11 @@
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
<com.pnikosis.materialishprogress.ProgressWheel
|
<com.pnikosis.materialishprogress.ProgressWheel
|
||||||
android:id="@+id/progress"
|
android:id="@+id/load_progress"
|
||||||
android:layout_width="@dimen/element_size_normal"
|
android:layout_width="@dimen/element_size_normal"
|
||||||
android:layout_height="@dimen/element_size_normal"
|
android:layout_height="@dimen/element_size_normal"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
app:matProg_barColor="@color/branding_color"/>
|
app:matProg_barColor="@color/branding_color"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
-->
|
-->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -49,12 +51,12 @@
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
<ProgressBar
|
<com.pnikosis.materialishprogress.ProgressWheel
|
||||||
android:id="@+id/progress"
|
android:id="@+id/load_progress"
|
||||||
android:layout_width="@dimen/element_size_normal"
|
android:layout_width="@dimen/element_size_normal"
|
||||||
android:layout_height="@dimen/element_size_normal"
|
android:layout_height="@dimen/element_size_normal"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"
|
||||||
|
app:matProg_barColor="@color/branding_color"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
Loading…
Reference in New Issue