package fr.ydelouis.selfoss.fragment; import android.app.Fragment; import android.content.Intent; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.j256.ormlite.dao.RuntimeExceptionDao; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.Background; import org.androidannotations.annotations.Bean; import org.androidannotations.annotations.Click; import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.FragmentArg; import org.androidannotations.annotations.IgnoredWhenDetached; import org.androidannotations.annotations.InstanceState; import org.androidannotations.annotations.OrmLiteDao; import org.androidannotations.annotations.Receiver; import org.androidannotations.annotations.UiThread; import org.androidannotations.annotations.ViewById; import java.util.ArrayList; import java.util.Collections; import java.util.List; import fr.ydelouis.selfoss.R; import fr.ydelouis.selfoss.config.model.Config; import fr.ydelouis.selfoss.config.ui.ConfigActivity_; import fr.ydelouis.selfoss.config.model.ConfigManager; import fr.ydelouis.selfoss.entity.ArticleType; import fr.ydelouis.selfoss.entity.Filter; import fr.ydelouis.selfoss.entity.Source; import fr.ydelouis.selfoss.entity.Tag; import fr.ydelouis.selfoss.model.ArticleDao; import fr.ydelouis.selfoss.model.DatabaseHelper; import fr.ydelouis.selfoss.sync.SourceSync; import fr.ydelouis.selfoss.sync.TagSync; import fr.ydelouis.selfoss.view.SourceView; import fr.ydelouis.selfoss.view.SourceView_; import fr.ydelouis.selfoss.view.TagView; import fr.ydelouis.selfoss.view.TagView_; import fr.ydelouis.selfoss.view.TypeView; @EFragment(R.layout.fragment_menu) public class MenuFragment extends Fragment implements View.OnClickListener { @Bean protected ConfigManager configManager; @FragmentArg @InstanceState protected Filter filter = new Filter(); @OrmLiteDao(helper = DatabaseHelper.class) protected RuntimeExceptionDao<Tag, String> tagDao; @OrmLiteDao(helper = DatabaseHelper.class) protected RuntimeExceptionDao<Source, Integer> sourceDao; @OrmLiteDao(helper = DatabaseHelper.class) protected ArticleDao articleDao; private Listener listener = new DummyListener(); @ViewById protected TextView url; @ViewById protected TypeView newest; @ViewById protected TypeView unread; @ViewById protected TypeView starred; @ViewById protected ViewGroup tagContainer; @ViewById protected ViewGroup sourceContainer; public void onOpened() { updateViews(); } @AfterViews protected void updateViews() { articleDao.setContext(getActivity()); Config config = configManager.get(); if (config != null) { url.setText(config.getUrl()); } updateTypes(); loadAndUpdateTags(); loadAndUpdateSources(); } private void updateTypes() { for (TypeView typeView : new TypeView[] {newest, unread, starred}) { typeView.setSelected(filter.getType()); } for (TypeView typeView : new TypeView[] {unread, starred}) { loadTypeCount(typeView); } } @Background protected void loadTypeCount(TypeView typeView) { typeView.setCount(articleDao.queryForCount(typeView.getType())); } @Background protected void loadAndUpdateTags() { List<Tag> tags = tagDao.queryForAll(); for (Tag tag : tags) { tag.setUnread(articleDao.queryForCount(ArticleType.Unread, tag)); } sortAndUpdateTags(tags); } @Background protected void loadAndUpdateSources() { List<Source> sources = sourceDao.queryForAll(); for (Source source : sources) { source.setUnread(articleDao.queryForCount(ArticleType.Unread, source)); } sortAndUpdateSources(sources); } @Receiver(actions = {TagSync.ACTION_SYNC_TAGS}, registerAt = Receiver.RegisterAt.OnResumeOnPause) protected void onTagsSynced(Intent intent) { sortAndUpdateTags(intent.<Tag>getParcelableArrayListExtra(TagSync.EXTRA_TAGS)); } @Receiver(actions = {SourceSync.ACTION_SYNC_SOURCES}, registerAt = Receiver.RegisterAt.OnResumeOnPause) protected void onSourcesSynced(Intent intent) { sortAndUpdateSources(intent.<Source>getParcelableArrayListExtra(SourceSync.EXTRA_SOURCES)); } protected void sortAndUpdateTags(List<Tag> tags) { Collections.sort(tags, Tag.COMPARATOR_UNREAD_INVERSE); int unreadAll = 0; for (Tag tag : tags) { unreadAll += tag.getUnread(); } Tag.ALL.setUnread(unreadAll); tags.add(0, Tag.ALL); updateTags(tags); } @Background protected void sortAndUpdateSources(List<Source> sources) { Collections.sort(sources, Source.COMPARATOR_UNREAD_INVERSE); updateSources(sources, tagDao.queryForAll()); } @UiThread @IgnoredWhenDetached protected void updateTags(List<Tag> tags) { tagContainer.removeAllViews(); for (Tag tag : tags) { TagView tagView = TagView_.build(getActivity()); tagView.setTag(tag); if (tag.equals(Tag.ALL)) { tagView.setAllTags(tags.subList(1,tags.size())); } tagView.setSelected(tag.equals(filter.getTag())); tagView.setOnClickListener(this); tagContainer.addView(tagView); } } @UiThread @IgnoredWhenDetached protected void updateSources(List<Source> sources, List<Tag> tags) { sourceContainer.removeAllViews(); for (Source source : sources) { SourceView sourceView = SourceView_.build(getActivity()); sourceView.setSource(source, getTagsOfSource(source, tags)); sourceView.setSelected(source.equals(filter.getSource())); sourceView.setOnClickListener(this); sourceContainer.addView(sourceView); } } private List<Tag> getTagsOfSource(Source source, List<Tag> tags) { List<Tag> tagsOfSource = new ArrayList<>(); for (Tag tag : tags) { if (source.getTags().contains(tag.getName(getActivity()))) { tagsOfSource.add(tag); } } return tagsOfSource; } private void selectTagAndSource() { selectTag(); selectSource(); listener.onFilterChanged(filter); } private void selectTag() { for (int i = 0; i < tagContainer.getChildCount(); i++) { View view = tagContainer.getChildAt(i); if (view instanceof TagView) { TagView tagView = (TagView) view; tagView.setSelected(tagView.getTag().equals(filter.getTag())); } } } private void selectSource() { for (int i = 0; i < sourceContainer.getChildCount(); i++) { View view = sourceContainer.getChildAt(i); if (view instanceof SourceView) { SourceView sourceView = (SourceView) view; sourceView.setSelected(sourceView.getSource().equals(filter.getSource())); } } } @Click(R.id.url) protected void openSelfossAccountActivity() { ConfigActivity_.intent(getActivity()).start(); listener.onAccountActivityStarted(); } @Click({ R.id.newest, R.id.unread, R.id.starred}) protected void onArticleTypeClick(View view) { ArticleType newType = ArticleType.fromId(view.getId()); setArticleType(newType); } public void setArticleType(ArticleType newType) { if (newType != filter.getType()) { filter.setType(newType); updateTypes(); listener.onFilterChanged(filter); } } @Override public void onClick(View view) { if (view instanceof TagView) { Tag newTag = ((TagView) view).getTag(); if (!newTag.equals(filter.getTag())) { filter.setTag(newTag); selectTagAndSource(); listener.onFilterChanged(filter); } } if (view instanceof SourceView) { Source newSource = ((SourceView) view).getSource(); if (!newSource.equals(filter.getSource())) { filter.setSource(newSource); selectTagAndSource(); listener.onFilterChanged(filter); } } } public void setListener(Listener listener) { this.listener = listener != null ? listener : new DummyListener(); } public interface Listener { void onAccountActivityStarted(); void onFilterChanged(Filter filter); } private class DummyListener implements Listener { @Override public void onAccountActivityStarted() {} @Override public void onFilterChanged(Filter filter) {} } }