package org.fox.ttcomics2; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.BaseColumns; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.ProgressBar; import android.widget.TextView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.nhaarman.listviewanimations.appearance.AnimationAdapter; import com.nhaarman.listviewanimations.appearance.simple.ScaleInAnimationAdapter; import java.io.File; import androidx.cursoradapter.widget.SimpleCursorAdapter; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import icepick.State; import jp.co.recruit_mp.android.widget.HeaderFooterGridView; public class ComicListFragment extends StateSavedFragment implements OnItemClickListener { private final String TAG = this.getClass().getSimpleName(); protected final static int SIZE_DIR = -100; // corresponds to tab indexes private final static int MODE_ALL = 0; private final static int MODE_UNREAD = 1; private final static int MODE_UNFINISHED = 2; private final static int MODE_READ = 3; private MainActivity m_activity; private SharedPreferences m_prefs; private ComicsListAdapter m_adapter; @State protected int m_mode = 0; @State protected String m_baseDirectory = ""; private SwipeRefreshLayout m_swipeLayout; private AnimationAdapter m_animationAdapter; public ComicListFragment() { super(); } public void setBaseDirectory(String baseDirectory) { m_baseDirectory = baseDirectory; } public void setMode(int mode) { m_mode = mode; } public void refresh() { if (m_adapter != null) { m_adapter.changeCursor(createCursor()); //m_animationAdapter.reset(); m_adapter.notifyDataSetChanged(); } } public String getBaseDirectory() { return m_baseDirectory; } static class ComicsViewHolder { TextView name; TextView info; ProgressBar progressBar; ImageView overflow; ImageView thumbnail; public ComicsViewHolder(View v) { name = v.findViewById(R.id.file_name); info = v.findViewById(R.id.file_progress_info); progressBar = v.findViewById(R.id.file_progress_bar); overflow = v.findViewById(R.id.overflow); thumbnail = v.findViewById(R.id.thumbnail); } } private class ComicsListAdapter extends SimpleCursorAdapter { public ComicsListAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); // TODO Auto-generated constructor stub } @Override public View getView(int position, View convertView, ViewGroup parent) { //View v = convertView; Cursor c = (Cursor) getItem(position); final String filePath = c.getString(c.getColumnIndex("path")); final String fileBaseName = c.getString(c.getColumnIndex("filename")); final String firstChild = c.getString(c.getColumnIndex("firstchild")); int lastPos = c.getInt(c.getColumnIndex("position")); final int size = c.getInt(c.getColumnIndex("size")); final ComicsViewHolder holder; if (convertView == null || convertView.getTag() == null) { LayoutInflater vi = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.comics_grid_row, null); holder = new ComicsViewHolder(convertView); convertView.setTag(holder); } else { holder = (ComicsViewHolder) convertView.getTag(); } if (holder.name != null) { holder.name.setText(fileBaseName); } if (holder.info != null) { if (size != -1 && size != SIZE_DIR) { if (lastPos == size - 1) { holder.info.setText(getString(R.string.file_finished)); } else if (lastPos > 0) { holder.info.setText(getString(R.string.file_progress_info, lastPos + 1, size, (int) (lastPos / (float) size * 100f))); } else { holder.info.setText(getString(R.string.file_unread, size)); } holder.info.setVisibility(View.VISIBLE); } else if (size == SIZE_DIR) { holder.info.setText(getString(R.string.list_type_directory)); holder.info.setVisibility(View.VISIBLE); } else { holder.info.setText(getString(R.string.list_type_unknown)); holder.info.setVisibility(View.VISIBLE); } } if (holder.progressBar != null) { if (size != -1 && size != SIZE_DIR) { holder.progressBar.setMax(size - 1); holder.progressBar.setProgress(lastPos); holder.progressBar.setEnabled(true); holder.progressBar.setVisibility(View.VISIBLE); } else { holder.progressBar.setProgress(0); holder.progressBar.setMax(0); holder.progressBar.setEnabled(false); holder.progressBar.setVisibility(View.VISIBLE); } } if (holder.overflow != null) { if (size == SIZE_DIR) { holder.overflow.setImageResource(R.drawable.ic_folder_outline); } else { holder.overflow.setImageResource(R.drawable.ic_dots_circle); } holder.overflow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { PopupMenu popup = new PopupMenu(getActivity(), v); MenuInflater inflater = popup.getMenuInflater(); inflater.inflate(R.menu.context_comic_archive, popup.getMenu()); if (size == SIZE_DIR) { popup.getMenu().findItem(R.id.menu_mark_as_read).setVisible(false); popup.getMenu().findItem(R.id.menu_reset_progress).setVisible(false); } if (!m_activity.m_syncClient.hasOwner()) { popup.getMenu().findItem(R.id.menu_reset_progress).setVisible(false); } popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { return onComicMenuItemSelected(item, filePath + "/" + fileBaseName); } }); popup.show(); } }); } String cacheFilename = CommonActivity.getCacheFileName(m_activity, firstChild != null ? firstChild : filePath + "/" + fileBaseName); if (cacheFilename != null) { File thumbnailFile = new File(cacheFilename); if (holder.thumbnail != null && thumbnailFile.exists()) { Glide.with(m_activity) .load(thumbnailFile) .diskCacheStrategy(DiskCacheStrategy.NONE) .skipMemoryCache(false) .into(holder.thumbnail); } else { holder.thumbnail.setImageDrawable(null); } } else { holder.thumbnail.setImageDrawable(null); } return convertView; } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_comics_grid, container, false); m_swipeLayout = view.findViewById(R.id.comics_swipe_container); m_swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { rescan(); } }); m_adapter = new ComicsListAdapter(getActivity(), R.layout.comics_grid_row, createCursor(), new String[] { "filename" }, new int[] { R.id.file_name }, 0); m_animationAdapter = new ScaleInAnimationAdapter(m_adapter); HeaderFooterGridView grid = view.findViewById(R.id.comics_grid); if (m_prefs.getBoolean("enable_fab", true)) { View footer = inflater.inflate(R.layout.comics_grid_footer, grid, false); grid.addFooterView(footer, null, false); } m_animationAdapter.setAbsListView(grid); grid.setAdapter(m_animationAdapter); //grid.setEmptyView(view.findViewById(R.id.no_comics)); grid.setOnItemClickListener(this); registerForContextMenu(grid); return view; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { getActivity().getMenuInflater().inflate(R.menu.context_comic_archive, menu); AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo; Cursor c = (Cursor) m_adapter.getItem(info.position); if (c != null) { menu.setHeaderTitle(c.getString(c.getColumnIndex("filename"))); int size = c.getInt(c.getColumnIndex("size")); if (size == SIZE_DIR) { menu.findItem(R.id.menu_mark_as_read).setVisible(false); menu.findItem(R.id.menu_reset_progress).setVisible(false); } if (!m_activity.m_syncClient.hasOwner()) { menu.findItem(R.id.menu_reset_progress).setVisible(false); } } super.onCreateContextMenu(menu, v, menuInfo); } protected boolean onComicMenuItemSelected(MenuItem item, String fileName) { if (fileName == null) { return false; } switch (item.getItemId()) { case R.id.menu_open: m_activity.onComicArchiveSelected(fileName); return true; case R.id.menu_reset_progress: m_activity.resetProgress(fileName); return true; case R.id.menu_mark_as_read: m_activity.m_databaseHelper.setLastPosition(fileName, m_activity.m_databaseHelper.getSize(fileName) - 1); refresh(); return true; default: return false; } } @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item .getMenuInfo(); Cursor c = (Cursor) m_adapter.getItem(info.position); String fileName = c.getString(c.getColumnIndex("path")) + "/" + c.getString(c.getColumnIndex("filename")); return onComicMenuItemSelected(item, fileName); } private Cursor createCursor() { String selection; String selectionArgs[]; switch (m_mode) { case MODE_READ: selection = "path = ? AND position = size - 1"; selectionArgs = new String[] { m_baseDirectory }; break; case MODE_UNFINISHED: selection = "path = ? AND position < size AND position > 0 AND position != size - 1"; selectionArgs = new String[] { m_baseDirectory }; break; case MODE_UNREAD: selection = "path = ? AND position = 0 AND size != ?"; selectionArgs = new String[] { m_baseDirectory, String.valueOf(SIZE_DIR) }; break; default: selection = "path = ?"; selectionArgs = new String[] { m_baseDirectory }; } return m_activity .m_databaseHelper .getReadableDatabase() .query("comics_cache", new String[]{BaseColumns._ID, "filename", "path", "position", "size", "(SELECT path || '/' || filename FROM comics_cache AS t2 WHERE t2.path = comics_cache.path || '/' " + "|| comics_cache.filename AND filename != '' ORDER BY filename LIMIT 1) AS firstchild"}, selection, selectionArgs, null, null, "size != " + SIZE_DIR + ", filename, size = " + SIZE_DIR + ", filename"); } @Override public void onAttach(Activity activity) { super.onAttach(activity); m_activity = (MainActivity)activity; m_prefs = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()); } protected void rescan() { if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true); m_activity.m_databaseHelper.rescanDirectory(m_baseDirectory, new DatabaseHelper.DirectoryScanListener() { @Override public void onProgressUpdate(int progress, int max) { refresh(); } @Override public void onPostExecute(int result) { try { m_activity.cleanupCache(); if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); refresh(); } catch (Exception e) { e.printStackTrace(); } } }); } @Override public void onResume() { super.onResume(); Log.d(TAG, "baseDir=" + m_baseDirectory); if (m_activity.m_databaseHelper.getCachedItemCount(m_baseDirectory) == 0) { rescan(); } else { refresh(); m_activity.cleanupCache(); } String comicsDir = m_prefs.getString("comics_directory", ""); if (comicsDir.equals(m_baseDirectory)) { m_activity.setTitle(R.string.app_name); m_activity.getSupportActionBar().setDisplayHomeAsUpEnabled(false); } else { m_activity.setTitle(new File(m_baseDirectory).getName()); m_activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); } } public void onItemClick(AdapterView av, View view, int position, long id) { //Log.d(TAG, "onItemClick position=" + position); Cursor c = (Cursor) m_adapter.getItem(position); String fileName = c.getString(c.getColumnIndex("path")) + "/" + c.getString(c.getColumnIndex("filename")); if (fileName != null) { m_activity.onComicArchiveSelected(fileName); } } }