parent
46aea213ee
commit
5d7765b6d3
|
@ -11,4 +11,5 @@ include ':twidere.donate.nyanwp.wear'
|
|||
include ':twidere.component.nyan'
|
||||
include ':twidere.extension.streaming'
|
||||
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 static final String APP_NAME = "Twidere";
|
||||
public static final String APP_PACKAGE_NAME = "org.mariotaku.twidere";
|
||||
public static final String APP_PROJECT_URL = "https://github.com/mariotaku/twidere";
|
||||
public static final String APP_PROJECT_EMAIL = "twidere.project@gmail.com";
|
||||
public static final String TWIDERE_APP_NAME = "Twidere";
|
||||
public static final String TWIDERE_PACKAGE_NAME = "org.mariotaku.twidere";
|
||||
public static final String TWIDERE_PROJECT_URL = "https://github.com/mariotaku/twidere";
|
||||
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_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.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||
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.view.iface.IExtendedView.OnFitSystemWindowsListener;
|
||||
|
||||
|
@ -41,7 +41,7 @@ import java.util.ArrayList;
|
|||
@SuppressLint("Registered")
|
||||
public class BaseActionBarActivity extends ThemedActionBarActivity implements Constants,
|
||||
OnFitSystemWindowsListener, SystemWindowsInsetsCallback, IControlBarActivity,
|
||||
ShortcutCallback {
|
||||
KeyboardShortcutCallback {
|
||||
|
||||
private boolean mInstanceStateSaved;
|
||||
private boolean mIsVisible;
|
||||
|
|
|
@ -91,7 +91,7 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
|||
import org.mariotaku.twidere.util.ColorUtils;
|
||||
import org.mariotaku.twidere.util.CustomTabUtils;
|
||||
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.MultiSelectEventHandler;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
|
@ -287,6 +287,7 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
mSlidingMenu.showContent(true);
|
||||
} else {
|
||||
mSlidingMenu.showMenu(true);
|
||||
setControlBarVisibleAnimate(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -684,16 +685,16 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
|
||||
private boolean handleFragmentKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||
final Fragment fragment = getCurrentVisibleFragment();
|
||||
if (fragment instanceof ShortcutCallback) {
|
||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
||||
if (fragment instanceof KeyboardShortcutCallback) {
|
||||
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean handleFragmentKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||
final Fragment fragment = getCurrentVisibleFragment();
|
||||
if (fragment instanceof ShortcutCallback) {
|
||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||
if (fragment instanceof KeyboardShortcutCallback) {
|
||||
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||
}
|
||||
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.UserFragment;
|
||||
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.ThemeUtils;
|
||||
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) {
|
||||
final Fragment fragment = getCurrentVisibleFragment();
|
||||
if (fragment instanceof ShortcutCallback) {
|
||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||
if (fragment instanceof KeyboardShortcutCallback) {
|
||||
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean handleFragmentKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||
final Fragment fragment = getCurrentVisibleFragment();
|
||||
if (fragment instanceof ShortcutCallback) {
|
||||
return ((ShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
||||
if (fragment instanceof KeyboardShortcutCallback) {
|
||||
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(keyCode, event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -228,7 +228,7 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
super.onBaseViewCreated(view, savedInstanceState);
|
||||
mImageView = (SubsamplingScaleImageView) view.findViewById(R.id.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
|
||||
|
@ -324,6 +324,11 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
activity.setBarVisibility(false);
|
||||
}
|
||||
|
||||
public void onZoomOut() {
|
||||
final MediaViewerActivity activity = (MediaViewerActivity) getActivity();
|
||||
activity.setBarVisibility(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
|
@ -349,21 +354,11 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
shareProvider.setShareIntent(intent);
|
||||
}
|
||||
|
||||
public void onZoomOut() {
|
||||
final MediaViewerActivity activity = (MediaViewerActivity) getActivity();
|
||||
activity.setBarVisibility(true);
|
||||
}
|
||||
|
||||
private ParcelableMedia getMedia() {
|
||||
final Bundle args = getArguments();
|
||||
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() {
|
||||
getLoaderManager().destroyLoader(0);
|
||||
if (!mLoaderInitialized) {
|
||||
|
@ -387,22 +382,8 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
}
|
||||
|
||||
@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);
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_media_viewer_image_page, menu);
|
||||
}
|
||||
|
||||
private void saveToGallery() {
|
||||
|
@ -427,6 +408,25 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
// 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
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
|
@ -526,6 +526,7 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
private SaveFileTask mSaveFileTask;
|
||||
private File mVideoFile;
|
||||
private Pair<String, String> mVideoUrlAndType;
|
||||
private ProgressWheel mProgressBar;
|
||||
|
||||
public boolean isLoopEnabled() {
|
||||
return getArguments().getBoolean(EXTRA_LOOP, false);
|
||||
|
@ -544,13 +545,6 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
// 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
|
||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||
mVideoViewProgress.removeCallbacks(mVideoProgressRunnable);
|
||||
|
@ -558,6 +552,14 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
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
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
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
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
@ -590,60 +608,32 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
@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
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
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
|
||||
public void onVideoLoadingStarted(String uri, VideoLoadingListener listener) {
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
mProgressBar.spin();
|
||||
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() {
|
||||
final Bundle args = getArguments();
|
||||
return args.getParcelable(EXTRA_MEDIA);
|
||||
|
@ -696,18 +681,29 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_SAVE: {
|
||||
saveToGallery();
|
||||
return true;
|
||||
}
|
||||
case MENU_REFRESH: {
|
||||
loadVideo();
|
||||
return true;
|
||||
}
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
final File file = mVideoFile;
|
||||
final Pair<String, String> linkAndType = mVideoUrlAndType;
|
||||
final boolean isLoading = linkAndType != null && mVideoLoader.isLoading(linkAndType.first);
|
||||
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));
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
shareProvider.setShareIntent(intent);
|
||||
}
|
||||
|
||||
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
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
|
|
@ -32,8 +32,9 @@ import org.mariotaku.twidere.model.ParcelableMedia;
|
|||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
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.RecyclerViewNavigationHelper;
|
||||
import org.mariotaku.twidere.util.RecyclerViewUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
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.
|
||||
*/
|
||||
public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<AbsStatusesAdapter<Data>>
|
||||
implements LoaderCallbacks<Data>, StatusAdapterListener, ShortcutCallback {
|
||||
implements LoaderCallbacks<Data>, StatusAdapterListener, KeyboardShortcutCallback {
|
||||
|
||||
private final Object mStatusesBusCallback;
|
||||
private SharedPreferences mPreferences;
|
||||
|
@ -71,7 +72,7 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
|||
getFragmentManager(), getTwitterWrapper(), status, item);
|
||||
}
|
||||
};
|
||||
private int mPositionBackup;
|
||||
private RecyclerViewNavigationHelper mRecyclerViewNavigationHelper;
|
||||
|
||||
protected AbsStatusesFragment() {
|
||||
mStatusesBusCallback = createMessageBusCallback();
|
||||
|
@ -133,39 +134,9 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||
if (!KeyboardShortcutsHandler.isValidForHotkey(keyCode, event)) return false;
|
||||
String action = mKeyboardShortcutsHandler.getKeyAction("navigation", keyCode, 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;
|
||||
public boolean handleKeyboardShortcutRepeat(final int keyCode, final int repeatCount,
|
||||
@NonNull final KeyEvent event) {
|
||||
return mRecyclerViewNavigationHelper.handleKeyboardShortcutRepeat(keyCode, repeatCount, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -374,7 +345,10 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
|||
final FragmentActivity activity = getActivity();
|
||||
final TwidereApplication application = TwidereApplication.getInstance(activity);
|
||||
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() {
|
||||
@Override
|
||||
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());
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||
|
|
|
@ -21,32 +21,61 @@ package org.mariotaku.twidere.fragment.support;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
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 org.mariotaku.twidere.adapter.AbsUsersAdapter;
|
||||
import org.mariotaku.twidere.adapter.AbsUsersAdapter.UserAdapterListener;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
|
||||
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.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() {
|
||||
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
|
||||
public void onActivityCreated(@Nullable Bundle 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());
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||
getLoaderManager().initLoader(0, loaderArgs, this);
|
||||
|
|
|
@ -29,6 +29,7 @@ import android.graphics.Rect;
|
|||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
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.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
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.ContentListScrollListener;
|
||||
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.RecyclerViewNavigationHelper;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
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>,
|
||||
RefreshScrollTopInterface, OnRefreshListener, MessageEntriesAdapterListener,
|
||||
ControlBarOffsetListener, ContentListSupport {
|
||||
ControlBarOffsetListener, ContentListSupport, KeyboardShortcutCallback {
|
||||
|
||||
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
|
||||
this, 0, this);
|
||||
|
@ -100,11 +105,54 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
|||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private View mProgressContainer;
|
||||
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() {
|
||||
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
|
||||
public void onAttach(Activity 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();
|
||||
private int mControlBarOffsetPixels;
|
||||
@Override
|
||||
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
|
||||
protected void fitSystemWindows(Rect insets) {
|
||||
|
@ -131,54 +268,6 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
|||
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
|
||||
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
|
||||
final Uri uri = DirectMessages.ConversationEntries.CONTENT_URI;
|
||||
|
@ -211,54 +300,15 @@ 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);
|
||||
public void onEntryClick(int position, DirectMessageEntry entry) {
|
||||
Utils.openMessageConversation(getActivity(), entry.account_id, entry.conversation_id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
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);
|
||||
public void onUserClick(int position, DirectMessageEntry entry) {
|
||||
Utils.openUserProfile(getActivity(), entry.account_id, entry.conversation_id, entry.screen_name, null);
|
||||
}
|
||||
|
||||
@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
|
||||
public void onGetMessagesTaskChanged(GetMessagesTaskEvent event) {
|
||||
if (event.uri.equals(Inbox.CONTENT_URI) && !event.running) {
|
||||
|
@ -269,23 +319,8 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
|||
}
|
||||
|
||||
@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);
|
||||
public void onRefresh() {
|
||||
triggerRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -323,12 +358,6 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(final boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
}
|
||||
|
||||
|
||||
protected long getAccountId() {
|
||||
final Bundle args = getArguments();
|
||||
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()));
|
||||
}
|
||||
|
||||
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) {
|
||||
if (mFirstVisibleItem != 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() {
|
||||
if (mRemoveUnreadCountsTask != null && mRemoveUnreadCountsTask.getStatus() == AsyncTask.Status.RUNNING)
|
||||
return;
|
||||
|
@ -420,6 +420,21 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
|
|||
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> {
|
||||
private final Set<Integer> read_positions;
|
||||
private final MessageEntriesAdapter adapter;
|
||||
|
|
|
@ -249,7 +249,7 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
editor.apply();
|
||||
}
|
||||
|
||||
public static interface ShortcutCallback {
|
||||
public static interface KeyboardShortcutCallback {
|
||||
boolean handleKeyboardShortcutSingle(int keyCode, @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 String version_name = pi.versionName;
|
||||
cb.setClientVersion(pi.versionName);
|
||||
cb.setClientName(APP_NAME);
|
||||
cb.setClientURL(APP_PROJECT_URL);
|
||||
cb.setHttpUserAgent(APP_NAME + " " + APP_PROJECT_URL + " / " + version_name
|
||||
cb.setClientName(TWIDERE_APP_NAME);
|
||||
cb.setClientURL(TWIDERE_PROJECT_URL);
|
||||
cb.setHttpUserAgent(TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL + " / " + version_name
|
||||
+ (gzipCompressing ? " (gzip)" : ""));
|
||||
} catch (final PackageManager.NameNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
|
|
|
@ -69,6 +69,10 @@ public class VideoLoader {
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean isLoading(String url) {
|
||||
return mTaskManager.hasRunningTasksForTag(url);
|
||||
}
|
||||
|
||||
|
||||
public int loadVideo(String uri, VideoLoadingListener listener) {
|
||||
if (mTaskManager.hasRunningTasksForTag(uri)) {
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
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_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<pl.droidsonroids.gif.GifTextureView
|
||||
android:id="@+id/gif_image_view"
|
||||
|
@ -35,10 +36,11 @@
|
|||
android:layout_height="match_parent"/>
|
||||
|
||||
<com.pnikosis.materialishprogress.ProgressWheel
|
||||
android:id="@+id/progress"
|
||||
android:id="@+id/load_progress"
|
||||
android:layout_width="@dimen/element_size_normal"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
app:matProg_barColor="@color/branding_color"/>
|
||||
|
||||
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
-->
|
||||
<FrameLayout
|
||||
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_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -49,12 +51,12 @@
|
|||
</RelativeLayout>
|
||||
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
<com.pnikosis.materialishprogress.ProgressWheel
|
||||
android:id="@+id/load_progress"
|
||||
android:layout_width="@dimen/element_size_normal"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
|
||||
android:visibility="gone"
|
||||
app:matProg_barColor="@color/branding_color"/>
|
||||
|
||||
</FrameLayout>
|
Loading…
Reference in New Issue