package org.sorz.lab.smallcloudemoji.fragments;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.sorz.lab.smallcloudemoji.R;
import org.sorz.lab.smallcloudemoji.activites.AddRepositoryActivity;
import org.sorz.lab.smallcloudemoji.activites.SettingsActivity;
import org.sorz.lab.smallcloudemoji.adapters.RepositoryAdapter;
import org.sorz.lab.smallcloudemoji.db.Category;
import org.sorz.lab.smallcloudemoji.db.CategoryDao;
import org.sorz.lab.smallcloudemoji.db.DaoSession;
import org.sorz.lab.smallcloudemoji.db.DatabaseHelper;
import org.sorz.lab.smallcloudemoji.db.EntryDao;
import org.sorz.lab.smallcloudemoji.db.Repository;
import org.sorz.lab.smallcloudemoji.db.RepositoryDao;
import org.sorz.lab.smallcloudemoji.db.Source;
import org.sorz.lab.smallcloudemoji.db.SourceDao;
import org.sorz.lab.smallcloudemoji.tasks.DownloadAsyncTask;
import java.util.ArrayList;
import java.util.List;
/**
* A fragment representing a list of repositories.
*/
public class RepositoryFragment extends Fragment {
private Context context;
private OnEmoticonStoreClickListener mListener;
private DaoSession daoSession;
private RepositoryDao repositoryDao;
private RepositoryAdapter adapter;
private ListView listView;
public RepositoryFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getActivity();
mListener = (OnEmoticonStoreClickListener) context;
daoSession = DatabaseHelper.getInstance(context).getDaoSession();
repositoryDao = daoSession.getRepositoryDao();
adapter = new RepositoryAdapter(context, daoSession);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_repository, container, false);
listView = (ListView) view.findViewById(R.id.repository_list);
View footer = getActivity().getLayoutInflater().inflate(R.layout.store_entry, null);
View goEmoticonStore = footer.findViewById(R.id.goEmoticonStore);
listView.addFooterView(footer, null, false);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
popMoreMenu(view.findViewById(R.id.button_more));
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent,
View view, int position, long id) {
Repository repository = adapter.getItem(position);
Uri uri = Uri.parse(repository.getUrl());
ClipboardManager clipboard =
(ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newUri(context.getContentResolver(),
repository.getAlias(), uri);
clipboard.setPrimaryClip(clipData);
Toast.makeText(context, R.string.toast_repository_copied,
Toast.LENGTH_SHORT).show();
return true;
}
});
goEmoticonStore.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onEmoticonStoreClick();
}
});
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.repository_actions, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_repository_add) {
Intent intent = new Intent(context, AddRepositoryActivity.class);
startActivityForResult(intent, SettingsActivity.REQUEST_FOR_ADDING_REPOSITORY);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SettingsActivity.REQUEST_FOR_ADDING_REPOSITORY) {
if (resultCode == AddRepositoryActivity.RESULT_SUCCESS_ADDED) {
notifyRepositoriesChanged();
super.onActivityResult(requestCode, resultCode, data);
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
void notifyRepositoriesChanged() {
adapter.notifyDataSetChanged();
listView.invalidateViews(); // This shit wasted my one hour.
}
private Repository getRepositoryFromView(View view) {
return (Repository) ((View) view.getParent()).getTag();
}
public void hideRepository(View view) {
ImageButton button = (ImageButton) view;
Repository repository = getRepositoryFromView(view);
repository.setHidden(!repository.getHidden());
repository.update();
if (repository.getHidden())
button.setBackgroundResource(R.drawable.ic_eye_slash);
else
button.setBackgroundResource(R.drawable.ic_eye_normal);
}
public void moveUpRepository(View view) {
Repository repository = getRepositoryFromView(view);
Repository targetRepository = repositoryDao.queryBuilder()
.where(RepositoryDao.Properties.Order.lt(repository.getOrder()))
.orderDesc(RepositoryDao.Properties.Order)
.limit(1).unique();
swapRepositoryOrder(repository, targetRepository);
}
public void moveDownRepository(View view) {
Repository repository = getRepositoryFromView(view);
Repository targetRepository = repositoryDao.queryBuilder()
.where(RepositoryDao.Properties.Order.gt(repository.getOrder()))
.orderAsc(RepositoryDao.Properties.Order)
.limit(1).unique();
swapRepositoryOrder(repository, targetRepository);
}
private void swapRepositoryOrder(Repository repositoryA, Repository repositoryB) {
if (repositoryA == null || repositoryB == null)
return;
int order = repositoryA.getOrder();
repositoryA.setOrder(repositoryB.getOrder());
repositoryB.setOrder(order);
repositoryDao.updateInTx(repositoryA, repositoryB);
notifyRepositoriesChanged();
}
public void popMoreMenu(View view) {
final Repository repository = getRepositoryFromView(view);
PopupMenu popupMenu = new PopupMenu(context, view);
popupMenu.inflate(R.menu.repository_more);
// Disable deleting if only one remaining.
long numRepositories = repositoryDao.queryBuilder()
.count();
if (numRepositories <= 1)
popupMenu.getMenu().findItem(R.id.menu_repository_delete).setEnabled(false);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
return moreMenuItemClicked(menuItem.getItemId(), repository);
}
});
popupMenu.show();
}
private boolean moreMenuItemClicked(int itemId, Repository repository) {
if (itemId == R.id.menu_repository_sync) {
syncRepository(repository);
} else if (itemId == R.id.menu_repository_rename) {
renameRepository(repository);
} else if (itemId == R.id.menu_repository_delete) {
deleteRepositoryIfConfirmed(repository);
} else {
return false;
}
return true;
}
private void syncRepository(final Repository repository) {
View itemView = (View) getActivity().findViewById(R.id.repository_list)
.findViewWithTag(repository).getParent();
final ProgressBar progressBar =
(ProgressBar) itemView.findViewById(R.id.repository_progressbar);
new DownloadAsyncTask(context) {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setProgress(0);
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
progressBar.setVisibility(View.GONE);
}
@Override
protected void onCancelled(Integer result) {
super.onCancelled(result);
if (result != DownloadAsyncTask.RESULT_CANCELLED)
return;
progressBar.setVisibility(View.GONE);
}
}.execute(repository);
}
private void renameRepository(final Repository repository) {
final EditText editText = new EditText(context);
editText.setText(repository.getAlias());
editText.selectAll();
DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String newAlias = editText.getText().toString().trim();
if (newAlias.isEmpty())
return;
repository.setAlias(newAlias);
repository.update();
notifyRepositoriesChanged();
}
};
new AlertDialog.Builder(context)
.setTitle(R.string.repository_rename_title)
.setCancelable(true)
.setView(editText)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.yes, onClickListener)
.show();
editText.requestFocus();
}
private void deleteRepositoryIfConfirmed(final Repository repository) {
// Generate message according to whether stars the on repository.
String message = String.format(getString(R.string.confirm_delete_repository_part1),
repository.getAlias());
List<Category> categories = repository.getCategories();
final List<Long> categoryIds = new ArrayList<Long>(categories.size());
for (Category category : categories)
categoryIds.add(category.getId());
long numStar = daoSession.getEntryDao().queryBuilder()
.where(EntryDao.Properties.CategoryId.in(categoryIds),
EntryDao.Properties.Star.eq(true))
.count();
if (numStar > 0)
message += String.format(getString(R.string.confirm_delete_repository_part2),
numStar);
// The actual code deleting the repository.
DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
daoSession.runInTx(new Runnable() {
@Override
public void run() {
SourceDao sourceDao = daoSession.getSourceDao();
List<Source> sources = sourceDao.queryBuilder()
.where(SourceDao.Properties.CodeUrl.eq(repository.getUrl()),
SourceDao.Properties.Installed.eq(true))
.list();
if (!sources.isEmpty()) {
for (Source source : sources)
source.setInstalled(false);
sourceDao.updateInTx(sources);
}
daoSession.getEntryDao().queryBuilder()
.where(EntryDao.Properties.CategoryId.in(categoryIds))
.buildDelete().executeDeleteWithoutDetachingEntities();
daoSession.getCategoryDao().queryBuilder()
.where(CategoryDao.Properties.RepositoryId.eq(repository.getId()))
.buildDelete().executeDeleteWithoutDetachingEntities();
repository.delete();
}
});
notifyRepositoriesChanged();
}
};
// Show alert dialog.
new AlertDialog.Builder(context)
.setCancelable(true)
.setTitle(R.string.confirm_delete_repository_title)
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.yes, onClickListener)
.show();
}
public interface OnEmoticonStoreClickListener {
public void onEmoticonStoreClick();
}
}