package com.gettingmobile.goodnews.itemview;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.*;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.*;
import com.gettingmobile.android.app.actions.AbstractAction;
import com.gettingmobile.android.app.actions.Action;
import com.gettingmobile.android.app.actions.ActionContext;
import com.gettingmobile.android.app.actions.MarketAction;
import com.gettingmobile.android.app.settings.AbstractSettings;
import com.gettingmobile.android.app.settings.OnSettingChangeListener;
import com.gettingmobile.android.view.NookTouchKeyCodes;
import com.gettingmobile.android.widget.OnScrollChangedListener;
import com.gettingmobile.android.widget.WebViewWithTitle;
import com.gettingmobile.goodnews.Activity;
import com.gettingmobile.goodnews.Application;
import com.gettingmobile.goodnews.R;
import com.gettingmobile.goodnews.settings.ItemDisplayType;
import com.gettingmobile.goodnews.settings.ItemTitleClickAction;
import com.gettingmobile.goodnews.util.*;
import com.gettingmobile.goodnews.widget.MessageBar;
import com.gettingmobile.google.reader.ElementId;
import com.gettingmobile.google.reader.Item;
import com.gettingmobile.google.reader.ItemState;
import com.gettingmobile.google.reader.db.ItemDatabaseAdapter;
import com.gettingmobile.google.reader.db.ItemTagChangeDatabaseAdapter;
import com.gettingmobile.google.reader.db.ItemTagChangeListener;
import com.gettingmobile.net.mobilizer.MobilizerImplementation;
import com.gettingmobile.net.mobilizer.NullUrlMobilizer;
import com.gettingmobile.net.mobilizer.UrlMobilizer;
import com.github.rtyley.android.sherlock.roboguice.fragment.RoboSherlockFragment;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Set;
public final class ItemViewContentFragment extends RoboSherlockFragment
implements CompoundButton.OnCheckedChangeListener, View.OnClickListener, ItemTagChangeListener {
private static final String LOG_TAG = "goodnews.ItemViewFragment";
private static final String URL_EMPTY = "about:blank";
protected static final String EXTRA_KEY_ITEM_KEY = Activity.EXTRA_KEY_BASE + "ITEM_KEY";
private final ItemDatabaseAdapter itemAdapter = new ItemDatabaseAdapter();
private final ItemTagChangeDatabaseAdapter itemTagChangeAdapter = new ItemTagChangeDatabaseAdapter();
private long itemKey = -1;
private Item item = null;
private boolean current = false;
private ItemUrlSharer pageUrlSharer = null;
private String pageUrl = null;
private String pageTitle = null;
private final BrowseHistory browseHistory = new BrowseHistory();
private ProgressBar progressBar = null;
private Animation progressBarFadeOutAnimation = null;
private TextView titleTextView = null;
private TextView feedTitle = null;
private ToggleButton readButton = null;
private ToggleButton readListButton = null;
private ToggleButton starButton = null;
private MessageBar msgBar = null;
private TextView labelView = null;
private TextView authorView = null;
private TextView timestampView = null;
private ItemTimestampFormat timestampFormat = null;
private WebViewWithTitle contentView = null;
private boolean externalContent = false;
private ContentLoadState contentLoadState = ContentLoadState.FORBIDDEN;
private int defaultFontSize = 0;
private int defaultFixedFontSize = 0;
private final OnWebTextSizeChangeListener webTextSizeChangeListener = new OnWebTextSizeChangeListener();
/*
* initialization
*/
static ItemViewContentFragment newInstance(long itemKey) {
final ItemViewContentFragment f = new ItemViewContentFragment();
final Bundle args = new Bundle();
args.putLong(EXTRA_KEY_ITEM_KEY, itemKey);
f.setArguments(args);
return f;
}
public ItemViewContentFragment() {
itemTagChangeAdapter.addListener(this);
}
/*
* current handling
*/
public void setCurrent(ItemUrlSharer pageUrlSharer) {
current = true;
this.pageUrlSharer = pageUrlSharer;
implicitlyUpdateItemTagsIfApplicable();
allowContentLoad();
}
public void unsetCurrent() {
current =false;
pageUrlSharer = null;
}
public Item getItem() {
return item;
}
/*
* life cycle management
*/
private static boolean isAlive(Activity activity) {
return activity != null && !activity.isFinishing();
}
private boolean isAlive() {
return isAlive(getAppActivity());
}
@Override
public void onAttach(android.app.Activity activity) {
browseHistory.setListener((BrowseHistoryListener) activity);
super.onAttach(activity);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
itemKey = getArguments().getLong(EXTRA_KEY_ITEM_KEY);
}
new ItemLoader(this, getApp()).load(itemKey);
}
private void initProgressBar(ViewGroup root) {
progressBar = (ProgressBar) root.findViewById(R.id.item_load_progress);
progressBar.setMax(100);
progressBarFadeOutAnimation = AnimationUtils.loadAnimation(getAppActivity(), android.R.anim.fade_out);
progressBarFadeOutAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// not interested
}
@Override
public void onAnimationEnd(Animation animation) {
if (isAlive()) {
progressBar.setVisibility(View.GONE);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
// not interested
}
});
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(LOG_TAG, "starting general initialization");
final ViewGroup root = (ViewGroup) inflater.inflate(R.layout.item_view_content_fragment, container, false);
initProgressBar(root);
/*
* init web view
*/
Log.i(LOG_TAG, "starting web view initialization");
final LinearLayout contentViewContainer = (LinearLayout) root.findViewById(R.id.item_content_container);
//noinspection deprecation
WebView.enablePlatformNotifications();
contentView = WebViewWithTitle.createInstance(getAppActivity());
contentViewContainer.addView(contentView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1));
contentView.setTitle(R.layout.item_title);
registerForContextMenu(contentView);
ItemWebViewInitializerFactory.createItemWebViewInitializer().initWebView(contentView);
contentView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
setLoadProgress(progress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
if (isAlive()) {
setPageInfo(getCurrentPageUrl(), title);
}
}
});
contentView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (isAlive() && MarketAction.isMarketUrl(url)) {
new MarketAction(url).onFired(getAppActivity());
return true;
} else {
return false;
}
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
if (isAlive()) {
msgBar.showWarning(description);
}
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d(LOG_TAG, "Loading page with URL " + url);
if (isAlive()) {
applyWebTextSize();
}
}
});
contentView.setOnTouchListener(new LinkClickDetector());
contentView.setOnScrollChangedListener(new OnScrollChangedListener() {
@Override
public void onScrollChanged(int scrollX, int scrollY) {
final ContentHistoryEntry historyEntry = (ContentHistoryEntry) browseHistory.getCurrent();
if (historyEntry != null) {
historyEntry.rememberScroll(scrollX, scrollY);
}
}
});
setContentViewThemeParameters();
defaultFontSize = contentView.getSettings().getDefaultFontSize();
defaultFixedFontSize = contentView.getSettings().getDefaultFixedFontSize();
getApp().getSettings().registerChangeListener("item_view_text_size", webTextSizeChangeListener);
if (savedInstanceState != null) {
contentView.restoreState(savedInstanceState);
}
clearContent();
/*
* init title
*/
final View titleView = root.findViewById(R.id.title);
titleView.setOnClickListener(this);
titleTextView = (TextView) root.findViewById(R.id.title_text);
feedTitle = (TextView) root.findViewById(R.id.feed_title);
readButton = (ToggleButton) root.findViewById(R.id.button_read);
readButton.setOnCheckedChangeListener(this);
readListButton = (ToggleButton) root.findViewById(R.id.button_readlist);
readListButton.setOnCheckedChangeListener(this);
starButton = (ToggleButton) root.findViewById(R.id.button_starred);
starButton.setOnCheckedChangeListener(this);
labelView = (TextView) root.findViewById(R.id.labels);
labelView.setOnClickListener(this);
/*
* init other properties
*/
msgBar = new MessageBar(getAppActivity());
timestampFormat = new ItemTimestampFormat(getApp(), true);
/*
* init item information
*/
authorView = (TextView) root.findViewById(R.id.author);
timestampView = (TextView) root.findViewById(R.id.timestamp);
/*
* done
*/
Log.i(LOG_TAG, "done with onCreate");
return root;
}
private void setContentViewThemeParameters() {
contentView.addJavascriptInterface(
getApp().getThemeUtil().getThemeColorWebString(getActivity(), R.attr.articleBackgroundColor),
"themeColorBackground");
contentView.addJavascriptInterface(
getApp().getThemeUtil().getThemeColorWebString(getActivity(), R.attr.themeTextColorPrimary),
"themeColorText");
final String baseTheme;
switch (getApp().getSettings().getTheme()) {
case BLACK:
case DARK:
baseTheme = "dark";
break;
default:
baseTheme = "light";
}
contentView.addJavascriptInterface(baseTheme, "baseTheme");
contentView.setBackgroundColor(getThemeUtil().getThemeColor(getAppActivity(), R.attr.articleBackgroundColor));
}
@Override
public void onResume() {
super.onResume();
contentView.resume();
}
@Override
public void onPause() {
contentView.pause();
commitTagChanges(getDb());
super.onPause();
}
@Override
public void onDestroy() {
getApp().getSettings().unregisterChangeListener("item_view_text_size", webTextSizeChangeListener);
super.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
Log.d(LOG_TAG, "onSaveInstanceState");
if (contentView != null) {
contentView.saveState(outState);
}
super.onSaveInstanceState(outState);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(LOG_TAG, "onConfigurationChanged");
super.onConfigurationChanged(newConfig);
}
//
// action handling
//
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
if (v == contentView) {
final WebView.HitTestResult hit = contentView.getHitTestResult();
if (hit.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
final String url = hit.getExtra();
getActivity().getMenuInflater().inflate(R.menu.link_context, menu);
menu.setHeaderTitle(url);
menu.findItem(R.id.menu_link_browser).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
openInBrowser(url);
return true;
}
});
menu.findItem(R.id.menu_link_share).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
final ItemUrlSharer linkSharer = new ClassicItemUrlSharer(getAppActivity());
linkSharer.setItemInfo(url, null);
linkSharer.handleAction();
return true;
}
});
}
} else {
super.onCreateContextMenu(menu, v, menuInfo);
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.getId() == R.id.button_read) {
onMarkRead(isChecked);
} else if (buttonView.getId() == R.id.button_readlist) {
onReadList(isChecked);
} else if (buttonView.getId() == R.id.button_starred) {
onStar(isChecked);
}
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.labels) {
showTagSelectionDialog();
} else if (view.getId() == R.id.title) {
onTitleClicked();
}
}
public final Action<Application> editTagsAction = new AbstractAction<Application>() {
@Override
public boolean onFired(ActionContext<? extends Application> context) {
showTagSelectionDialog();
return true;
}
};
public final Action<Application> openInBrowserAction = new AbstractAction<Application>() {
@Override
public boolean onFired(ActionContext<? extends Application> actionContext) {
final String url = getCurrentPageUrl();
if (url != null) {
openInBrowser(url);
}
return true;
}
};
public final Action<Application> loadContentAction = new Action<Application>() {
@Override
public int getState(ActionContext<? extends Application> actionContext) {
return !browseHistory.canGoBack() && !browseHistory.isEmpty() &&
!(browseHistory.getCurrent() instanceof UrlHistoryEntry) ? ENABLED : GONE;
}
@Override
public boolean onFired(ActionContext<? extends Application> actionContext) {
loadContent();
return true;
}
};
private boolean execute(int menuResId) {
return getAppActivity().fireAction(menuResId);
}
private boolean onTitleClicked() {
final ItemTitleClickAction action = getApp().getSettings().getItemTitleClickAction();
switch (action) {
case LABELS:
return execute(R.id.menu_item_labels);
case BROWSER:
return execute(R.id.menu_item_browser);
case LOAD:
return execute(R.id.menu_item_load);
case FULL_SCREEN:
return execute(R.id.menu_full_screen) || execute(R.id.menu_full_screen_disable);
default:
// nothing
return false;
}
}
private boolean useVolumeKeysForScrolling() {
return getApp().getSettings().useVolumeKeysForArticleScrolling();
}
private boolean handleVolumeKeys(KeyEvent event) {
if (useVolumeKeysForScrolling()) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
return (event.getAction() != KeyEvent.ACTION_DOWN) || contentView.pageDown(false);
case KeyEvent.KEYCODE_VOLUME_UP:
return (event.getAction() != KeyEvent.ACTION_DOWN) || contentView.pageUp(false);
}
}
return false;
}
private boolean handleBackKey(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && browseHistory.canGoBack()) {
if (event.getAction() == KeyEvent.ACTION_UP)
browseHistory.goBack().show();
return true;
} else {
return false;
}
}
public boolean handleStandardKeyOverriding(KeyEvent event) {
return handleVolumeKeys(event) || handleBackKey(event);
}
private boolean handleNookTouchKeys(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case NookTouchKeyCodes.LEFT_NEXT_PAGE:
case NookTouchKeyCodes.RIGHT_NEXT_PAGE:
return contentView.pageDown(false);
case NookTouchKeyCodes.LEFT_PREV_PAGE:
case NookTouchKeyCodes.RIGHT_PREV_PAGE:
return contentView.pageUp(false);
}
}
return false;
}
public boolean handleAdditionalKeys(KeyEvent event) {
return handleNookTouchKeys(event);
}
//
// label handling
//
protected void onMarkRead(boolean read) {
if (item != null) {
itemTagChangeAdapter.markItemRead(item, read);
updateLabelControls();
}
}
protected void onReadList(boolean readList) {
changeTag(getApp().getSettings().getLabelReadListId(), readList);
}
protected void onStar(boolean star) {
changeTag(ItemState.STARRED.getId(), star);
}
protected void changeTag(ElementId tag, boolean add) {
if (item != null) {
itemTagChangeAdapter.changeItemTag(item, tag, add);
}
}
protected void updateLabels() {
if (item != null) {
final Set<ElementId> tags = itemAdapter.readItemTags(getReadOnlyDb(), item.getKey());
item.getTagIds().clear();
item.getTagIds().addAll(tags);
updateLabelControls();
}
}
protected void updateLabelControls() {
if (item != null) {
readButton.setChecked(item.isRead());
readListButton.setChecked(item.hasTag(getApp().getSettings().getLabelReadListId()));
starButton.setChecked(item.hasTag(ItemState.STARRED.getId()));
TagListViewController.setTags(labelView,
TagFilter.filterSpecialTagIds(getApp().getSettings(), item.getTagIds()),
getResources().getColor(R.color.highlight));
}
}
private void showTagSelectionDialog() {
if (item != null) {
new TagSelectionDialogBuilder(getActivity(), item, itemTagChangeAdapter).show();
}
}
@Override
public void onItemReadStateChanged(long itemKey, boolean read) {
if (item != null && item.getKey() == itemKey) {
updateLabelControls();
}
}
@Override
public void onItemTagChanged(long itemKey, ElementId tag, boolean added) {
if (item != null && item.getKey() == itemKey) {
updateLabelControls();
}
}
//
// url sharing
//
private void setPageInfo(String url, String title) {
pageUrl = url;
pageTitle = title;
updateUrlSharer();
}
private void updateUrlSharer() {
if (pageUrlSharer != null && isAlive()) {
pageUrlSharer.setItemInfo(pageUrl, pageTitle);
}
}
//
// url handling
//
protected UrlMobilizer getUrlMobilizer() {
return item != null ?
getApp().getSettings().getUrlMobilizer(item.getFeedId()) :
new NullUrlMobilizer();
}
protected String getItemUrl() {
return item != null && item.getAlternate() != null && item.getAlternate().getHref().length() > 0 ?
item.getAlternate().getHref() : null;
}
protected String getMobilizedUrl() {
final String url = getItemUrl();
return url != null ?
getUrlMobilizer().mobilize(url, getApp().getSettings().scaleImages(item.getFeedId())) : null;
}
protected String getCurrentPageUrl() {
final String url = contentView.getUrl();
return url != null && url.length() > 0 && !URL_EMPTY.equalsIgnoreCase(url) ?
getUrlMobilizer().unmobilize(url) : getItemUrl();
}
//
// browse history
//
private abstract class ContentHistoryEntry implements BrowseHistoryEntry {
private int scrollX = 0;
private int scrollY = 0;
public void rememberScroll(int x, int y) {
scrollX = x;
scrollY = y;
}
@Override
public void show() {
contentView.setInitialScroll(scrollX, scrollY);
}
}
final class UrlHistoryEntry extends ContentHistoryEntry {
private final String url;
public UrlHistoryEntry(String url) {
this.url = url;
}
@Override
public void show() {
super.show();
setContentUrl(url);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UrlHistoryEntry that = (UrlHistoryEntry) o;
return !(url != null ? !url.equals(that.url) : that.url != null);
}
@Override
public String toString() {
return "UrlHistoryEntry{" +
"url='" + url + '\'' +
'}';
}
}
final class ItemContentHistoryEntry extends ContentHistoryEntry {
@Override
public void show() {
super.show();
showContent();
}
@Override
public String toString() {
return "ItemContentHistoryEntry";
}
}
final class ItemSummaryHistoryEntry extends ContentHistoryEntry {
@Override
public void show() {
super.show();
showSummary();
}
@Override
public String toString() {
return "ItemSummaryHistoryEntry";
}
}
final class ShowNothingHistoryEntry extends ContentHistoryEntry {
@Override
public void show() {
showNothing();
}
@Override
public String toString() {
return "ShowNothingHistoryEntry";
}
}
//
// font size handling
//
final class OnWebTextSizeChangeListener implements OnSettingChangeListener {
@Override
public void onSettingChanged(AbstractSettings settings, SharedPreferences sharedPreferences, String key) {
applyWebTextSize();
}
}
protected int getFontSize(int defaultSize, WebSettings.TextSize size) {
final double percentage;
switch (size) {
case SMALLEST:
percentage = 0.8;
break;
case SMALLER:
percentage = 0.9;
break;
case LARGER:
percentage = 1.1;
break;
case LARGEST:
percentage = 1.2;
break;
default:
percentage = 1.0;
}
return (int) Math.round(percentage * defaultSize);
}
protected void applyWebTextSize(WebSettings.TextSize size) {
contentView.getSettings().setDefaultFontSize(getFontSize(defaultFontSize, size));
contentView.getSettings().setDefaultFixedFontSize(getFontSize(defaultFixedFontSize, size));
}
protected void applyWebTextSize() {
final MobilizerImplementation mobilizerImpl = item != null ?
getApp().getSettings().getMobilizerImplementation(item.getFeedId()) : MobilizerImplementation.NONE;
applyWebTextSize(externalContent && mobilizerImpl == MobilizerImplementation.NONE ?
WebSettings.TextSize.NORMAL : getApp().getSettings().getItemViewTextSize());
}
//
// content view handling
//
protected void showNothing() {
setContent("");
}
protected void showSummary() {
setContent(item.getSummary());
}
protected void showContent() {
setContent(item.getContent());
}
private void addUrlToHistory(String url) {
browseHistory.setCurrent(new UrlHistoryEntry(url));
}
protected void loadContent() {
final String url = getMobilizedUrl();
if (url != null) {
addUrlToHistory(url);
setContentUrl(url);
}
}
protected void openInBrowser(String url) {
try {
startActivity(new Intent(Intent.ACTION_VIEW, android.net.Uri.parse(url)));
} catch (ActivityNotFoundException ex) {
Log.e(LOG_TAG, "Failed to open activity in browser", ex);
}
}
protected void setContent(String content) {
externalContent = false;
final String baseUrl;
if (item.hasImages()) {
baseUrl = "file://" + item.getDirectory(getApp().getSettings().getContentStorageProvider()).getAbsolutePath() + "/";
} else if (getApp().isInternetAvailableAndRequired()) {
baseUrl = item.getAlternate() != null ? item.getAlternate().getHref() : null;
} else {
baseUrl = null;
}
Log.d(LOG_TAG, "Setting baseUrl to " + baseUrl);
setContent(baseUrl, ItemTextUtil.getItemTitle(getActivity(), item), content,
getApp().getSettings().scaleImages(item.getFeedId()));
}
protected void setContent(String baseUrl, String title, String content, boolean scaleImages) {
final String data = HtmlBuilder.build(
title, content,
getThemeUtil().getThemeColorWebString(getActivity(), R.attr.themeTextColorPrimary),
getThemeUtil().getThemeColorWebString(getActivity(), R.attr.articleBackgroundColor),
scaleImages);
contentView.loadDataWithBaseURL(baseUrl, data, "text/html", "utf-8", null);
}
protected void setContentUrl(String url) {
externalContent = true;
contentView.loadUrl(url);
}
protected void clearContent() {
setContent(null, null, "", false);
}
private class LinkClickDetector extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener {
private final GestureDetector clickDetector = new GestureDetector(getAppActivity(), this);
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
clickDetector.onTouchEvent(motionEvent);
return false;
}
public boolean onSingleTapConfirmed(MotionEvent e) {
final WebView.HitTestResult hit = contentView.getHitTestResult();
if (hit.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
addUrlToHistory(hit.getExtra());
}
return false;
}
}
//
// helper
//
private Activity getAppActivity() {
return (Activity) getSherlockActivity();
}
private Application getApp() {
return getAppActivity().getApp();
}
private ThemeUtil getThemeUtil() {
return getAppActivity().getThemeUtil();
}
private SQLiteDatabase getDb() {
return getApp().getDbHelper().getDatabase();
}
private SQLiteDatabase getReadOnlyDb() {
return getApp().getDbHelper().getReadOnlyDatabase();
}
//
// item loading and persistence
//
private enum ContentLoadState {
FORBIDDEN,
ALLOWED,
LOADING_OR_LOADED
}
private void allowContentLoad() {
if (contentLoadState == ContentLoadState.FORBIDDEN) {
contentLoadState = ContentLoadState.ALLOWED;
}
loadContentIfApplicable();
}
private void loadContentIfApplicable() {
if (item != null && contentLoadState == ContentLoadState.ALLOWED) {
final ItemDisplayType itemDisplayType = getApp().getSettings().getItemDisplayType(item);
Log.d(LOG_TAG, "Item " + item + " has " + (item.hasContent() ? "" : "no ") + "content. ItemDisplayType: " + itemDisplayType);
setPageInfo(item.getAlternate() != null ? item.getAlternate().getHref() : null, item.getTitle());
browseHistory.clear();
contentLoadState = ContentLoadState.LOADING_OR_LOADED;
switch (itemDisplayType) {
case SUMMARY:
browseHistory.setCurrent(new ItemSummaryHistoryEntry());
showSummary();
break;
case CONTENT:
browseHistory.setCurrent(new ItemContentHistoryEntry());
showContent();
break;
case LOAD:
loadContent();
break;
default:
browseHistory.setCurrent(new ShowNothingHistoryEntry());
showNothing();
}
}
}
private void implicitlyUpdateItemTagsIfApplicable() {
if (current && item != null) {
//
// mark item as read and remove it from read list
//
Log.i(LOG_TAG, "update item tags");
if (getApp().getSettings().markReadOnView()) {
itemTagChangeAdapter.markItemRead(item, true);
}
if (getApp().getSettings().removeFromReadListOnView()) {
itemTagChangeAdapter.removeItemTag(item, getApp().getSettings().getLabelReadListId());
}
}
}
private void commitTagChanges(SQLiteDatabase db) {
if (itemTagChangeAdapter.commitChanges(db)) {
getApp().onItemTagsChanged();
}
}
private static final class ItemLoader extends AsyncTask<Long, Integer, Item> {
private final ItemViewContentFragment fragment;
private final Application app;
public ItemLoader(ItemViewContentFragment fragment, Application app) {
this.fragment = fragment;
this.app = app;
}
public void load(long itemKey) {
execute(itemKey);
}
@Override
protected Item doInBackground(Long... longs) {
return fetchItem(app.getDbHelper().getReadOnlyDatabase(), longs[0]);
}
protected Item fetchItem(SQLiteDatabase readOnlyDb, long itemKey) {
fragment.commitTagChanges(app.getDbHelper().getDatabase());
Log.i(LOG_TAG, "fetching item " + itemKey);
final Item item = fragment.itemAdapter.readFullByKey(readOnlyDb, itemKey);
Log.i(LOG_TAG, "fetching item " + (item != null ? "succeeded" : "failed"));
if (item != null) {
try {
item.loadIfRequired(app.getSettings().getContentStorageProvider());
item.updateContentFlags();
Log.i(LOG_TAG, "item loaded");
} catch (IOException ex) {
Log.e(LOG_TAG, "Failed to load item", ex);
final String errorMsg = app.getString(R.string.error_failed_loading_local_content);
if (item.hasSummary()) {
item.setSummary(errorMsg);
}
if (item.hasContent()) {
item.setContent(errorMsg);
}
}
}
return item;
}
@Override
protected void onPostExecute(Item item) {
fragment.updateView(item);
}
}
private boolean updateView(Item item) {
Log.i(LOG_TAG, "updating view");
if (item == null || !isAlive())
return false;
ItemViewContentFragment.this.item = item;
implicitlyUpdateItemTagsIfApplicable();
//
// set title
//
Log.i(LOG_TAG, "updating view header");
titleTextView.setText(Html.fromHtml(ItemTextUtil.getItemTitle(getActivity(), item)));
String feedTitleText = ItemTextUtil.getItemSpecialFeedTitle(getActivity(), item);
if (feedTitleText == null) {
feedTitleText = item.getFeedTitle();
}
feedTitle.setText(feedTitleText != null ? feedTitleText : "");
//
// set author and date
//
if (item.getAuthor() != null) {
authorView.setText(MessageFormat.format(getString(R.string.author_by), item.getAuthor()));
authorView.setVisibility(View.VISIBLE);
} else {
authorView.setText("");
authorView.setVisibility(View.GONE);
}
final Date timestamp = item.getTimestamp();
timestampView.setText(timestampFormat.format(timestamp));
timestampView.setVisibility(timestamp != null ? View.VISIBLE : View.INVISIBLE);
//
// update button visibility
//
readListButton.setVisibility(getApp().getSettings().shouldShowReadListTag() ? View.VISIBLE : View.GONE);
updateLabelControls();
//
// inform listener
//
loadContentIfApplicable();
Log.i(LOG_TAG, "done updating view");
return true;
}
private void setLoadProgress(int progress) {
if (isAlive()) {
if (progress < 100)
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(progress);
if (progress >= 100)
progressBar.startAnimation(progressBarFadeOutAnimation);
}
}
}