package org.mtransit.android.ui.fragment;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import org.mtransit.android.R;
import org.mtransit.android.commons.BundleUtils;
import org.mtransit.android.commons.CollectionUtils;
import org.mtransit.android.commons.ColorUtils;
import org.mtransit.android.commons.MTLog;
import org.mtransit.android.commons.ThemeUtils;
import org.mtransit.android.commons.TimeUtils;
import org.mtransit.android.commons.data.News;
import org.mtransit.android.commons.ui.widget.MTArrayAdapter;
import org.mtransit.android.task.NewsLoader;
import org.mtransit.android.ui.MainActivity;
import org.mtransit.android.ui.view.MTOnItemClickListener;
import org.mtransit.android.ui.widget.ListViewSwipeRefreshLayout;
import org.mtransit.android.util.LoaderUtils;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.TextView;
public class NewsFragment extends ABFragment implements LoaderManager.LoaderCallbacks<ArrayList<News>>, SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = NewsFragment.class.getSimpleName();
@Override
public String getLogTag() {
return TAG;
}
private static final String TRACKING_SCREEN_NAME = "News";
@Override
public String getScreenName() {
return TRACKING_SCREEN_NAME;
}
private static final String EXTRA_COLOR_INT = "extra_color_int";
private static final String EXTRA_SUB_TITLE = "extra_subtitle";
private static final String EXTRA_FILTER_TARGET_AUTHORITIES = "extra_filter_target_authorities";
private static final String EXTRA_FILTER_TARGETS = "extra_filter_targets";
private static final String EXTRA_FILTER_UUIDS = "extra_filter_uuids";
public static NewsFragment newInstance(Integer optColorInt, String optSubtitle, ArrayList<String> optTargetAuthorities, ArrayList<String> optFilterUUIDs,
ArrayList<String> optFilterTargets) {
NewsFragment f = new NewsFragment();
Bundle args = new Bundle();
if (optColorInt != null) {
args.putInt(EXTRA_COLOR_INT, optColorInt);
f.colorInt = optColorInt;
}
if (!TextUtils.isEmpty(optSubtitle)) {
args.putString(EXTRA_SUB_TITLE, optSubtitle);
f.subTitle = optSubtitle;
}
if (CollectionUtils.getSize(optTargetAuthorities) > 0) {
args.putStringArrayList(EXTRA_FILTER_TARGET_AUTHORITIES, optTargetAuthorities);
f.targetAuthorities = optTargetAuthorities;
}
if (CollectionUtils.getSize(optFilterUUIDs) > 0) {
args.putStringArrayList(EXTRA_FILTER_UUIDS, optFilterUUIDs);
f.filterUUIDs = optFilterUUIDs;
}
if (CollectionUtils.getSize(optFilterTargets) > 0) {
args.putStringArrayList(EXTRA_FILTER_TARGETS, optFilterTargets);
f.filterTargets = optFilterTargets;
}
f.setArguments(args);
return f;
}
private Integer colorInt;
private String subTitle;
private ArrayList<String> targetAuthorities;
private ArrayList<String> filterUUIDs;
private ArrayList<String> filterTargets;
private CharSequence emptyText = null;
private NewsAdapter adapter;
private ListViewSwipeRefreshLayout swipeRefreshLayout;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
initAdapters(activity);
}
private void initAdapters(Activity activity) {
this.adapter = new NewsAdapter(activity);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
restoreInstanceState(savedInstanceState, getArguments());
}
private void restoreInstanceState(Bundle... bundles) {
Integer newColorInt = BundleUtils.getInt(EXTRA_COLOR_INT, bundles);
if (newColorInt != null) {
this.colorInt = newColorInt;
}
String newSubtitle = BundleUtils.getString(EXTRA_SUB_TITLE, bundles);
if (!TextUtils.isEmpty(newSubtitle)) {
this.subTitle = newSubtitle;
}
ArrayList<String> newTargetAuthorities = BundleUtils.getStringArrayList(EXTRA_FILTER_TARGET_AUTHORITIES, bundles);
if (CollectionUtils.getSize(newTargetAuthorities) > 0) {
this.targetAuthorities = newTargetAuthorities;
}
ArrayList<String> newFilterUUIDs = BundleUtils.getStringArrayList(EXTRA_FILTER_UUIDS, bundles);
if (CollectionUtils.getSize(newFilterUUIDs) > 0) {
this.filterUUIDs = newFilterUUIDs;
}
ArrayList<String> newFilterTargets = BundleUtils.getStringArrayList(EXTRA_FILTER_TARGETS, bundles);
if (CollectionUtils.getSize(newFilterTargets) > 0) {
this.filterTargets = newFilterTargets;
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
if (this.colorInt != null) {
outState.putInt(EXTRA_COLOR_INT, this.colorInt);
}
if (!TextUtils.isEmpty(this.subTitle)) {
outState.putString(EXTRA_SUB_TITLE, this.subTitle);
}
if (CollectionUtils.getSize(this.targetAuthorities) > 0) {
outState.putStringArrayList(EXTRA_FILTER_TARGET_AUTHORITIES, this.targetAuthorities);
}
if (CollectionUtils.getSize(this.filterUUIDs) > 0) {
outState.putStringArrayList(EXTRA_FILTER_UUIDS, this.filterUUIDs);
}
if (CollectionUtils.getSize(this.filterTargets) > 0) {
outState.putStringArrayList(EXTRA_FILTER_TARGETS, this.filterTargets);
}
super.onSaveInstanceState(outState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_news, container, false);
setupView(view);
return view;
}
@Override
public void onResume() {
super.onResume();
View view = getView();
if (this.modulesUpdated) {
if (view != null) {
view.post(new Runnable() {
@Override
public void run() {
if (NewsFragment.this.modulesUpdated) {
onModulesUpdated();
}
}
});
}
}
if (!this.adapter.isInitialized()) {
LoaderUtils.restartLoader(this, NEWS_LOADER, null, this);
}
this.adapter.onResume();
}
@Override
public void onPause() {
super.onPause();
this.adapter.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
this.adapter.onDestroy();
}
private boolean modulesUpdated = false;
@Override
public void onModulesUpdated() {
this.modulesUpdated = true;
if (!isResumed()) {
return;
}
LoaderUtils.restartLoader(this, NEWS_LOADER, null, this);
this.modulesUpdated = false; // processed
}
private static final int NEWS_LOADER = 0;
@Override
public Loader<ArrayList<News>> onCreateLoader(int id, Bundle args) {
switch (id) {
case NEWS_LOADER:
return new NewsLoader(getActivity(), this.targetAuthorities, this.filterUUIDs, this.filterTargets);
default:
MTLog.w(this, "Loader id '%s' unknown!", id);
return null;
}
}
@Override
public void onLoaderReset(Loader<ArrayList<News>> loader) {
if (this.adapter != null) {
this.adapter.clear();
}
}
@Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {
this.emptyText = getString(R.string.no_news);
this.adapter.setNews(data);
switchView(getView());
}
@Override
public void onRefresh() {
initiateRefresh();
}
private boolean initiateRefresh() {
if (this.adapter != null) {
this.adapter.clear();
}
switchView(getView());
LoaderUtils.restartLoader(this, NEWS_LOADER, null, this);
setSwipeRefreshLayoutRefreshing(false);
return true;
}
public void setSwipeRefreshLayoutRefreshing(boolean refreshing) {
if (this.swipeRefreshLayout != null) {
if (refreshing) {
if (!this.swipeRefreshLayout.isRefreshing()) {
this.swipeRefreshLayout.setRefreshing(true);
}
} else {
this.swipeRefreshLayout.setRefreshing(false);
}
}
}
private void setupView(View view) {
if (view == null) {
return;
}
this.swipeRefreshLayout = (ListViewSwipeRefreshLayout) view.findViewById(R.id.swiperefresh);
this.swipeRefreshLayout.setColorSchemeColors(ThemeUtils.resolveColorAttribute(getActivity(), R.attr.colorAccent));
this.swipeRefreshLayout.setOnRefreshListener(this);
inflateList(view);
switchView(view);
linkAdapterWithListView(view);
}
private void linkAdapterWithListView(View view) {
if (view == null || this.adapter == null) {
return;
}
View listView = view.findViewById(R.id.list);
if (listView != null) {
((AbsListView) listView).setAdapter(this.adapter);
((AbsListView) listView).setOnItemClickListener(this.adapter);
}
}
private void switchView(View view) {
if (view == null) {
return;
}
if (this.adapter == null || !this.adapter.isInitialized()) {
showLoading(view);
} else if (this.adapter.getCount() == 0) {
showEmpty(view);
} else {
showList(view);
}
}
private void showList(View view) {
if (view.findViewById(R.id.loading) != null) { // IF inflated/present DO
view.findViewById(R.id.loading).setVisibility(View.GONE); // hide
}
if (view.findViewById(R.id.empty) != null) { // IF inflated/present DO
view.findViewById(R.id.empty).setVisibility(View.GONE); // hide
}
inflateList(view);
view.findViewById(R.id.list).setVisibility(View.VISIBLE); // show
}
private void inflateList(View view) {
if (view.findViewById(R.id.list) == null) { // IF NOT present/inflated DO
((ViewStub) view.findViewById(R.id.list_stub)).inflate(); // inflate
if (this.swipeRefreshLayout != null) {
this.swipeRefreshLayout.setListViewWR((AbsListView) view.findViewById(R.id.list));
}
}
}
private void showLoading(View view) {
if (view.findViewById(R.id.list) != null) { // IF inflated/present DO
view.findViewById(R.id.list).setVisibility(View.GONE); // hide
}
if (view.findViewById(R.id.empty) != null) { // IF inflated/present DO
view.findViewById(R.id.empty).setVisibility(View.GONE); // hide
}
if (this.swipeRefreshLayout != null) {
this.swipeRefreshLayout.setLoadingViewWR(view.findViewById(R.id.loading));
}
view.findViewById(R.id.loading).setVisibility(View.VISIBLE); // show
}
private void showEmpty(View view) {
if (view.findViewById(R.id.list) != null) { // IF inflated/present DO
view.findViewById(R.id.list).setVisibility(View.GONE); // hide
}
if (view.findViewById(R.id.loading) != null) { // IF inflated/present DO
view.findViewById(R.id.loading).setVisibility(View.GONE); // hide
}
if (view.findViewById(R.id.empty) == null) { // IF NOT present/inflated DO
((ViewStub) view.findViewById(R.id.empty_stub)).inflate(); // inflate
if (this.swipeRefreshLayout != null) {
this.swipeRefreshLayout.setEmptyViewWR(view.findViewById(R.id.empty));
}
}
if (!TextUtils.isEmpty(this.emptyText)) {
((TextView) view.findViewById(R.id.empty_text)).setText(this.emptyText);
}
view.findViewById(R.id.empty).setVisibility(View.VISIBLE); // show
}
@Override
public CharSequence getABTitle(Context context) {
return context.getString(R.string.news);
}
@Override
public CharSequence getABSubtitle(Context context) {
if (!TextUtils.isEmpty(this.subTitle)) {
return this.subTitle;
}
return super.getABSubtitle(context);
}
@Override
public Integer getABBgColor(Context context) {
if (this.colorInt != null) {
return this.colorInt;
}
return super.getABBgColor(context);
}
private static class NewsAdapter extends MTArrayAdapter<News> implements TimeUtils.TimeChangedReceiver.TimeChangedListener, AdapterView.OnItemClickListener {
private static final String TAG = NewsAdapter.class.getSimpleName();
@Override
public String getLogTag() {
return TAG;
}
private LayoutInflater layoutInflater;
private WeakReference<Activity> activityWR;
private ArrayList<News> news;
private NewsAdapter(Activity activity) {
super(activity, -1);
setActivity(activity);
this.layoutInflater = LayoutInflater.from(getContext());
}
public void setActivity(Activity activity) {
this.activityWR = new WeakReference<Activity>(activity);
}
private Activity getActivityOrNull() {
return this.activityWR == null ? null : this.activityWR.get();
}
public boolean isInitialized() {
return this.news != null;
}
private void resetNowToTheMinute() {
notifyDataSetChanged();
}
@Override
public void onTimeChanged() {
resetNowToTheMinute();
}
private final BroadcastReceiver timeChangedReceiver = new TimeUtils.TimeChangedReceiver(this);
private boolean timeChangedReceiverEnabled = false;
private void enableTimeChangedReceiver() {
if (!this.timeChangedReceiverEnabled) {
getContext().registerReceiver(timeChangedReceiver, TimeUtils.TIME_CHANGED_INTENT_FILTER);
this.timeChangedReceiverEnabled = true;
}
}
private void disableTimeChangeddReceiver() {
if (this.timeChangedReceiverEnabled) {
getContext().unregisterReceiver(this.timeChangedReceiver);
this.timeChangedReceiverEnabled = false;
}
}
public void setNews(ArrayList<News> news) {
this.news = news;
notifyDataSetChanged();
}
@Override
public void clear() {
if (this.news != null) {
this.news.clear();
this.news = null; // not initialized
}
super.clear();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
MTOnItemClickListener.onItemClickS(parent, view, position, id, new MTOnItemClickListener() {
@Override
public void onItemClickMT(AdapterView<?> parent, View view, int position, long id) {
News news = getItem(position);
if (news == null) {
return;
}
Activity activity = getActivityOrNull();
if (activity == null) {
return;
}
((MainActivity) activity).addFragmentToStack(NewsDetailsFragment.newInstance(news.getUUID(), news.getAuthority(), news));
}
});
}
@Override
public int getCount() {
return CollectionUtils.getSize(this.news);
}
public void onPause() {
disableTimeChangeddReceiver();
}
public void onResume() {
enableTimeChangedReceiver();
}
public void onDestroy() {
disableTimeChangeddReceiver();
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public int getItemViewType(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = this.layoutInflater.inflate(R.layout.layout_news_base, parent, false);
NewsViewHolder holder = new NewsViewHolder();
holder.newsTv = (TextView) convertView.findViewById(R.id.newsText);
holder.authorTv = (TextView) convertView.findViewById(R.id.author);
holder.dateTv = (TextView) convertView.findViewById(R.id.date);
convertView.setTag(holder);
}
NewsViewHolder holder = (NewsViewHolder) convertView.getTag();
News news = getItem(position);
holder.authorTv.setText(getContext().getString(R.string.news_shared_on_and_author_and_source, news.getAuthorOneLine(), news.getSourceLabel()));
if (news.hasColor()) {
holder.authorTv.setTextColor(news.getColorInt());
} else {
holder.authorTv.setTextColor(ColorUtils.getTextColorSecondary(getContext()));
}
holder.dateTv.setText(TimeUtils.formatRelativeTime(getContext(), news.getCreatedAtInMs()));
holder.newsTv.setText(news.getText());
if (news.hasColor()) {
holder.newsTv.setLinkTextColor(news.getColorInt());
} else {
holder.newsTv.setLinkTextColor(ColorUtils.getTextColorPrimary(getContext()));
}
return convertView;
}
@Override
public News getItem(int position) {
return this.news == null ? null : this.news.get(position);
}
private static final class NewsViewHolder {
private TextView newsTv;
private TextView authorTv;
private TextView dateTv;
}
}
}