package com.quran.labs.androidquran.ui; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.SparseIntArray; import android.view.MenuItem; import com.quran.labs.androidquran.QuranApplication; import com.quran.labs.androidquran.R; import com.quran.labs.androidquran.dao.translation.TranslationHeader; import com.quran.labs.androidquran.dao.translation.TranslationItem; import com.quran.labs.androidquran.dao.translation.TranslationRowData; import com.quran.labs.androidquran.presenter.translation.TranslationManagerPresenter; import com.quran.labs.androidquran.service.QuranDownloadService; import com.quran.labs.androidquran.service.util.DefaultDownloadReceiver; import com.quran.labs.androidquran.service.util.QuranDownloadNotifier; import com.quran.labs.androidquran.service.util.ServiceIntentHelper; import com.quran.labs.androidquran.ui.adapter.TranslationsAdapter; import com.quran.labs.androidquran.util.QuranFileUtils; import com.quran.labs.androidquran.util.QuranSettings; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; import io.reactivex.disposables.Disposable; import timber.log.Timber; public class TranslationManagerActivity extends QuranActionBarActivity implements DefaultDownloadReceiver.SimpleDownloadListener { public static final String TRANSLATION_DOWNLOAD_KEY = "TRANSLATION_DOWNLOAD_KEY"; private static final String UPGRADING_EXTENSION = ".old"; private List<TranslationItem> allItems; private SparseIntArray translationPositions; private TranslationsAdapter adapter; private TranslationItem downloadingItem; private String databaseDirectory; private QuranSettings quranSettings; private DefaultDownloadReceiver mDownloadReceiver = null; private Disposable onClickDownloadDisposable; private Disposable onClickRemoveDisposable; @Inject TranslationManagerPresenter presenter; @BindView(R.id.translation_swipe_refresh) SwipeRefreshLayout translationSwipeRefresh; @BindView(R.id.translation_recycler) RecyclerView translationRecycler; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((QuranApplication) getApplication()).getApplicationComponent().inject(this); setContentView(R.layout.translation_manager); ButterKnife.bind(this); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this); translationRecycler.setLayoutManager(mLayoutManager); adapter = new TranslationsAdapter(this); translationRecycler.setAdapter(adapter); databaseDirectory = QuranFileUtils.getQuranDatabaseDirectory(this); final ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setTitle(R.string.prefs_translations); } quranSettings = QuranSettings.getInstance(this); presenter.bind(this); presenter.getTranslationsList(false); onClickDownloadDisposable = adapter.getOnClickDownloadSubject().subscribe(this::downloadItem); onClickRemoveDisposable = adapter.getOnClickRemoveSubject().subscribe(this::removeItem); translationSwipeRefresh.setOnRefreshListener(this::onRefresh); } @Override public void onStop() { if (mDownloadReceiver != null) { mDownloadReceiver.setListener(null); LocalBroadcastManager.getInstance(this) .unregisterReceiver(mDownloadReceiver); mDownloadReceiver = null; } super.onStop(); } @Override protected void onDestroy() { presenter.unbind(this); onClickDownloadDisposable.dispose(); onClickRemoveDisposable.dispose(); super.onDestroy(); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } else { return super.onOptionsItemSelected(item); } } @Override public void handleDownloadSuccess() { if (downloadingItem != null) { if (downloadingItem.exists()) { try { File f = new File(databaseDirectory, downloadingItem.translation.fileName + UPGRADING_EXTENSION); if (f.exists()) { f.delete(); } } catch (Exception e) { Timber.d(e, "error removing old database file"); } } TranslationItem updated = downloadingItem.withTranslationVersion( downloadingItem.translation.currentVersion); updateTranslationItem(updated); } downloadingItem = null; generateListItems(); } @Override public void handleDownloadFailure(int errId) { if (downloadingItem != null && downloadingItem.exists()) { try { File f = new File(databaseDirectory, downloadingItem.translation.fileName + UPGRADING_EXTENSION); File destFile = new File(databaseDirectory, downloadingItem.translation.fileName); if (f.exists() && !destFile.exists()) { f.renameTo(destFile); } else { f.delete(); } } catch (Exception e) { Timber.d(e, "error restoring translation after failed download"); } } downloadingItem = null; } private void onRefresh() { presenter.getTranslationsList(true); } private void updateTranslationItem(TranslationItem updated) { int id = updated.translation.id; int allItemsIndex = translationPositions.get(id); if (allItems != null && allItems.size() > allItemsIndex) { allItems.remove(allItemsIndex); allItems.add(allItemsIndex, updated); } presenter.updateItem(updated); } public void onErrorDownloadTranslations() { translationSwipeRefresh.setRefreshing(false); Snackbar .make(translationRecycler, R.string.error_getting_translation_list, Snackbar.LENGTH_SHORT) .show(); } public void onTranslationsUpdated(List<TranslationItem> items) { translationSwipeRefresh.setRefreshing(false); SparseIntArray itemsSparseArray = new SparseIntArray(items.size()); for (int i = 0, itemsSize = items.size(); i < itemsSize; i++) { TranslationItem item = items.get(i); itemsSparseArray.put(item.translation.id, i); } allItems = items; translationPositions = itemsSparseArray; generateListItems(); } private void generateListItems() { if (allItems == null) { return; } List<TranslationItem> downloaded = new ArrayList<>(); List<TranslationItem> notDownloaded = new ArrayList<>(); for (int i = 0, mAllItemsSize = allItems.size(); i < mAllItemsSize; i++) { TranslationItem item = allItems.get(i); if (item.exists()) { downloaded.add(item); } else { notDownloaded.add(item); } } List<TranslationRowData> result = new ArrayList<>(); if (downloaded.size() > 0) { TranslationHeader hdr = new TranslationHeader(getString(R.string.downloaded_translations)); result.add(hdr); boolean needsUpgrade = false; for (TranslationItem item : downloaded) { result.add(item); needsUpgrade = needsUpgrade || item.needsUpgrade(); } if (!needsUpgrade) { quranSettings.setHaveUpdatedTranslations(false); } } result.add(new TranslationHeader(getString(R.string.available_translations))); result.addAll(notDownloaded); adapter.setTranslations(result); adapter.notifyDataSetChanged(); } private void downloadItem(TranslationRowData translationRowData) { TranslationItem selectedItem = (TranslationItem) translationRowData; if (selectedItem.exists() && !selectedItem.needsUpgrade()) { return; } downloadingItem = selectedItem; if (mDownloadReceiver == null) { mDownloadReceiver = new DefaultDownloadReceiver(this, QuranDownloadService.DOWNLOAD_TYPE_TRANSLATION); LocalBroadcastManager.getInstance(this).registerReceiver( mDownloadReceiver, new IntentFilter( QuranDownloadNotifier.ProgressIntent.INTENT_NAME)); } mDownloadReceiver.setListener(this); // actually start the download String url = selectedItem.translation.fileUrl; if (selectedItem.translation.fileUrl == null) { return; } String destination = databaseDirectory; Timber.d("downloading %s to %s", url, destination); if (selectedItem.exists()) { try { File f = new File(destination, selectedItem.translation.fileName); if (f.exists()) { File newPath = new File(destination, selectedItem.translation.fileName + UPGRADING_EXTENSION); if (newPath.exists()) { newPath.delete(); } f.renameTo(newPath); } } catch (Exception e) { Timber.d(e, "error backing database file up"); } } // start the download String notificationTitle = selectedItem.name(); Intent intent = ServiceIntentHelper.getDownloadIntent(this, url, destination, notificationTitle, TRANSLATION_DOWNLOAD_KEY, QuranDownloadService.DOWNLOAD_TYPE_TRANSLATION); String filename = selectedItem.translation.fileName; if (url.endsWith("zip")) { filename += ".zip"; } intent.putExtra(QuranDownloadService.EXTRA_OUTPUT_FILE_NAME, filename); startService(intent); } private void removeItem(final TranslationRowData translationRowData) { if (adapter == null) { return; } final TranslationItem selectedItem = (TranslationItem) translationRowData; String msg = String.format(getString(R.string.remove_dlg_msg), selectedItem.name()); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.remove_dlg_title) .setMessage(msg) .setPositiveButton(R.string.remove_button, (dialog, id) -> { QuranFileUtils.removeTranslation(TranslationManagerActivity.this, selectedItem.translation.fileName); TranslationItem updatedItem = selectedItem.withTranslationRemoved(); updateTranslationItem(updatedItem); generateListItems(); }) .setNegativeButton(R.string.cancel, (dialog, i) -> dialog.dismiss()); builder.show(); } }