aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
diff options
context:
space:
mode:
authorScott Jackson <daneren2005@gmail.com>2015-04-25 17:03:02 -0700
committerScott Jackson <daneren2005@gmail.com>2015-04-25 17:03:05 -0700
commitcfd014d38cba03ba05f571597b361ab253bff578 (patch)
tree4256723561dec7ef3ed3507382eb7020724ec570 /app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
parent8a332a20ec272d59fe74520825b18017a8f0cac3 (diff)
downloaddsub-cfd014d38cba03ba05f571597b361ab253bff578.tar.gz
dsub-cfd014d38cba03ba05f571597b361ab253bff578.tar.bz2
dsub-cfd014d38cba03ba05f571597b361ab253bff578.zip
Update to gradle
Diffstat (limited to 'app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java')
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java586
1 files changed, 586 insertions, 0 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
new file mode 100644
index 00000000..ae38534a
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
@@ -0,0 +1,586 @@
+package github.daneren2005.dsub.fragments;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.StatFs;
+import android.util.Log;
+import android.view.ContextMenu;
+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.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ListView;
+import android.widget.TextView;
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.ServerInfo;
+import github.daneren2005.dsub.service.DownloadService;
+import github.daneren2005.dsub.util.Constants;
+import github.daneren2005.dsub.util.FileUtil;
+import github.daneren2005.dsub.util.LoadingTask;
+import github.daneren2005.dsub.util.Pair;
+import github.daneren2005.dsub.util.UserUtil;
+import github.daneren2005.dsub.adapter.MergeAdapter;
+import github.daneren2005.dsub.util.Util;
+import github.daneren2005.dsub.service.MusicService;
+import github.daneren2005.dsub.service.MusicServiceFactory;
+import github.daneren2005.dsub.util.SilentBackgroundTask;
+import github.daneren2005.dsub.view.ChangeLog;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MainFragment extends SubsonicFragment {
+ private static final String TAG = MainFragment.class.getSimpleName();
+ private LayoutInflater inflater;
+ private TextView countView;
+
+ private static final int MENU_GROUP_SERVER = 10;
+ private static final int MENU_ITEM_SERVER_BASE = 100;
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
+ this.inflater = inflater;
+ rootView = inflater.inflate(R.layout.home, container, false);
+
+ createLayout();
+
+ return rootView;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+ menuInflater.inflate(R.menu.main, menu);
+
+ try {
+ if (!ServerInfo.isMadsonic(context) || !UserUtil.isCurrentAdmin()) {
+ menu.setGroupVisible(R.id.madsonic, false);
+ }
+ } catch(Exception e) {
+ Log.w(TAG, "Error on setting madsonic invisible", e);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if(super.onOptionsItemSelected(item)) {
+ return true;
+ }
+
+ switch (item.getItemId()) {
+ case R.id.menu_log:
+ getLogs();
+ return true;
+ case R.id.menu_about:
+ showAboutDialog();
+ return true;
+ case R.id.menu_changelog:
+ ChangeLog changeLog = new ChangeLog(context, Util.getPreferences(context));
+ changeLog.getFullLogDialog().show();
+ return true;
+ case R.id.menu_faq:
+ showFAQDialog();
+ return true;
+ case R.id.menu_rescan:
+ rescanServer();
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, view, menuInfo);
+
+ int serverCount = Util.getServerCount(context);
+ int activeServer = Util.getActiveServer(context);
+ for(int i = 1; i <= serverCount; i++) {
+ android.view.MenuItem menuItem = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_BASE + i, MENU_ITEM_SERVER_BASE + i, Util.getServerName(context, i));
+ if(i == activeServer) {
+ menuItem.setChecked(true);
+ }
+ }
+ menu.setGroupCheckable(MENU_GROUP_SERVER, true, true);
+ menu.setHeaderTitle(R.string.main_select_server);
+
+ recreateContextMenu(menu);
+ }
+
+ @Override
+ public boolean onContextItemSelected(android.view.MenuItem menuItem) {
+ if(menuItem.getGroupId() != getSupportTag()) {
+ return false;
+ }
+
+ int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE;
+ setActiveServer(activeServer);
+ return true;
+ }
+
+ @Override
+ protected void refresh(boolean refresh) {
+ createLayout();
+ }
+
+ private void createLayout() {
+ View buttons = inflater.inflate(R.layout.main_buttons, null);
+
+ final View serverButton = buttons.findViewById(R.id.main_select_server);
+ final TextView serverTextView = (TextView) serverButton.findViewById(R.id.main_select_server_2);
+ final TextView offlineButton = (TextView) buttons.findViewById(R.id.main_offline);
+ offlineButton.setText(Util.isOffline(context) ? R.string.main_online : R.string.main_offline);
+
+ final View albumsTitle = buttons.findViewById(R.id.main_albums);
+ final View videoTitle = buttons.findViewById(R.id.main_video_section);
+ final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest);
+ countView = (TextView) buttons.findViewById(R.id.main_albums_recent_count);
+ final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random);
+ final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest);
+ final View albumsRecentButton = buttons.findViewById(R.id.main_albums_recent);
+ final View albumsFrequentButton = buttons.findViewById(R.id.main_albums_frequent);
+ final View albumsStarredButton = buttons.findViewById(R.id.main_albums_starred);
+ final View albumsGenresButton = buttons.findViewById(R.id.main_albums_genres);
+ final View albumsYearButton = buttons.findViewById(R.id.main_albums_year);
+ final View albumsAlphabeticalButton = buttons.findViewById(R.id.main_albums_alphabetical);
+ final View videosButton = buttons.findViewById(R.id.main_videos);
+
+ final View dummyView = rootView.findViewById(R.id.main_dummy);
+
+ final CheckBox albumsPerFolderCheckbox = (CheckBox) buttons.findViewById(R.id.main_albums_per_folder);
+ if(!Util.isOffline(context) && ServerInfo.canAlbumListPerFolder(context)) {
+ albumsPerFolderCheckbox.setChecked(Util.getAlbumListsPerFolder(context));
+ albumsPerFolderCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ Util.setAlbumListsPerFolder(context, isChecked);
+ }
+ });
+ } else {
+ albumsPerFolderCheckbox.setVisibility(View.GONE);
+ }
+
+ int instance = Util.getActiveServer(context);
+ String name = Util.getServerName(context, instance);
+ serverTextView.setText(name);
+
+ ListView list = (ListView) rootView.findViewById(R.id.main_list);
+
+ MergeAdapter adapter = new MergeAdapter();
+ if (!Util.isOffline(context)) {
+ adapter.addViews(Arrays.asList(serverButton), true);
+ }
+ adapter.addView(offlineButton, true);
+ if (!Util.isOffline(context)) {
+ adapter.addView(albumsTitle, false);
+ adapter.addViews(Arrays.asList(albumsNewestButton, albumsRandomButton), true);
+ if(ServerInfo.checkServerVersion(context, "1.8")) {
+ adapter.addView(albumsAlphabeticalButton, true);
+ }
+ if(!Util.isTagBrowsing(context)) {
+ adapter.addView(albumsHighestButton, true);
+ }
+ adapter.addViews(Arrays.asList(albumsStarredButton, albumsGenresButton, albumsYearButton, albumsRecentButton, albumsFrequentButton), true);
+ if(ServerInfo.checkServerVersion(context, "1.8") && !Util.isTagBrowsing(context)) {
+ adapter.addView(videoTitle, false);
+ adapter.addView(videosButton, true);
+ }
+ }
+ list.setAdapter(adapter);
+ registerForContextMenu(dummyView);
+
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (view == serverButton) {
+ dummyView.showContextMenu();
+ } else if (view == offlineButton) {
+ toggleOffline();
+ } else if (view == albumsNewestButton) {
+ showAlbumList("newest");
+ } else if (view == albumsRandomButton) {
+ showAlbumList("random");
+ } else if (view == albumsHighestButton) {
+ showAlbumList("highest");
+ } else if (view == albumsRecentButton) {
+ showAlbumList("recent");
+ } else if (view == albumsFrequentButton) {
+ showAlbumList("frequent");
+ } else if (view == albumsStarredButton) {
+ showAlbumList("starred");
+ } else if(view == albumsGenresButton) {
+ showAlbumList("genres");
+ } else if(view == albumsYearButton) {
+ showAlbumList("years");
+ } else if(view == albumsAlphabeticalButton) {
+ showAlbumList("alphabeticalByName");
+ } else if(view == videosButton) {
+ showVideos();
+ }
+ }
+ });
+ setTitle(R.string.common_appname);
+
+ if(!Util.isOffline(context)) {
+ getMostRecentCount();
+ }
+ }
+
+ private void setActiveServer(int instance) {
+ if (Util.getActiveServer(context) != instance) {
+ final DownloadService service = getDownloadService();
+ if (service != null) {
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ service.clearIncomplete();
+ return null;
+ }
+ }.execute();
+
+ }
+ Util.setActiveServer(context, instance);
+ context.invalidate();
+ UserUtil.refreshCurrentUser(context, false, true);
+ }
+ }
+
+ private void toggleOffline() {
+ boolean isOffline = Util.isOffline(context);
+ Util.setOffline(context, !isOffline);
+ context.invalidate();
+ DownloadService service = getDownloadService();
+ if (service != null) {
+ service.setOnline(isOffline);
+ }
+
+ // Coming back online
+ if(isOffline) {
+ int scrobblesCount = Util.offlineScrobblesCount(context);
+ int starsCount = Util.offlineStarsCount(context);
+ if(scrobblesCount > 0 || starsCount > 0){
+ showOfflineSyncDialog(scrobblesCount, starsCount);
+ }
+ }
+
+ UserUtil.seedCurrentUser(context);
+ }
+
+ private void showAlbumList(String type) {
+ if("genres".equals(type)) {
+ SubsonicFragment fragment = new SelectGenreFragment();
+ replaceFragment(fragment);
+ } else if("years".equals(type)) {
+ SubsonicFragment fragment = new SelectYearFragment();
+ replaceFragment(fragment);
+ } else {
+ // Clear out recently added count when viewing
+ if("newest".equals(type)) {
+ SharedPreferences.Editor editor = Util.getPreferences(context).edit();
+ editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
+ editor.commit();
+
+ // Clear immediately so doesn't still show when pressing back
+ setMostRecentCount(0);
+ }
+
+ SubsonicFragment fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type);
+ args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
+ args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
+ fragment.setArguments(args);
+
+ replaceFragment(fragment);
+ }
+ }
+ private void showVideos() {
+ SubsonicFragment fragment = new SelectVideoFragment();
+ replaceFragment(fragment);
+ }
+
+ private void showOfflineSyncDialog(final int scrobbleCount, final int starsCount) {
+ String syncDefault = Util.getSyncDefault(context);
+ if(syncDefault != null) {
+ if("sync".equals(syncDefault)) {
+ syncOffline(scrobbleCount, starsCount);
+ return;
+ } else if("delete".equals(syncDefault)) {
+ deleteOffline();
+ return;
+ }
+ }
+
+ View checkBoxView = context.getLayoutInflater().inflate(R.layout.sync_dialog, null);
+ final CheckBox checkBox = (CheckBox)checkBoxView.findViewById(R.id.sync_default);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setIcon(android.R.drawable.ic_dialog_info)
+ .setTitle(R.string.offline_sync_dialog_title)
+ .setMessage(context.getResources().getString(R.string.offline_sync_dialog_message, scrobbleCount, starsCount))
+ .setView(checkBoxView)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ if(checkBox.isChecked()) {
+ Util.setSyncDefault(context, "sync");
+ }
+ syncOffline(scrobbleCount, starsCount);
+ }
+ }).setNeutralButton(R.string.common_cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ dialogInterface.dismiss();
+ }
+ }).setNegativeButton(R.string.common_delete, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ if(checkBox.isChecked()) {
+ Util.setSyncDefault(context, "delete");
+ }
+ deleteOffline();
+ }
+ });
+
+ builder.create().show();
+ }
+
+ private void syncOffline(final int scrobbleCount, final int starsCount) {
+ new SilentBackgroundTask<Integer>(context) {
+ @Override
+ protected Integer doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ return musicService.processOfflineSyncs(context, null);
+ }
+
+ @Override
+ protected void done(Integer result) {
+ if(result == scrobbleCount) {
+ Util.toast(context, context.getResources().getString(R.string.offline_sync_success, result));
+ } else {
+ Util.toast(context, context.getResources().getString(R.string.offline_sync_partial, result, scrobbleCount + starsCount));
+ }
+ }
+
+ @Override
+ protected void error(Throwable error) {
+ Log.w(TAG, "Failed to sync offline stats", error);
+ String msg = context.getResources().getString(R.string.offline_sync_error) + " " + getErrorMessage(error);
+ Util.toast(context, msg);
+ }
+ }.execute();
+ }
+ private void deleteOffline() {
+ SharedPreferences.Editor offline = Util.getOfflineSync(context).edit();
+ offline.putInt(Constants.OFFLINE_SCROBBLE_COUNT, 0);
+ offline.putInt(Constants.OFFLINE_STAR_COUNT, 0);
+ offline.commit();
+ }
+
+ private void showAboutDialog() {
+ new LoadingTask<String>(context) {
+ @Override
+ protected String doInBackground() throws Throwable {
+ File rootFolder = FileUtil.getMusicDirectory(context);
+ StatFs stat = new StatFs(rootFolder.getPath());
+ long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
+ long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
+
+ Pair<Long, Long> used = FileUtil.getUsedSize(context, rootFolder);
+
+ return getResources().getString(R.string.main_about_text,
+ context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName,
+ used.getFirst(),
+ Util.formatLocalizedBytes(used.getSecond(), context),
+ Util.formatLocalizedBytes(Util.getCacheSizeMB(context) * 1024L * 1024L, context),
+ Util.formatLocalizedBytes(bytesAvailableFs, context),
+ Util.formatLocalizedBytes(bytesTotalFs, context));
+ }
+
+ @Override
+ protected void done(String msg) {
+ try {
+ Util.info(context, R.string.main_about_title, msg);
+ } catch(Exception e) {
+ Util.toast(context, "Failed to open dialog");
+ }
+ }
+ }.execute();
+ }
+
+ private void showFAQDialog() {
+ Util.showHTMLDialog(context, R.string.main_faq_title, R.string.main_faq_text);
+ }
+
+ private void rescanServer() {
+ new LoadingTask<Void>(context, false) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ musicService.startRescan(context, this);
+ return null;
+ }
+
+ @Override
+ protected void done(Void value) {
+ Util.toast(context, R.string.main_scan_complete);
+ }
+ }.execute();
+ }
+
+ private void getLogs() {
+ try {
+ final String version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
+ new LoadingTask<File>(context) {
+ @Override
+ protected File doInBackground() throws Throwable {
+ updateProgress("Gathering Logs");
+ File logcat = new File(FileUtil.getSubsonicDirectory(context), "logcat.txt");
+ Util.delete(logcat);
+ Process logcatProc = null;
+
+ try {
+ List<String> progs = new ArrayList<String>();
+ progs.add("logcat");
+ progs.add("-v");
+ progs.add("time");
+ progs.add("-d");
+ progs.add("-f");
+ progs.add(logcat.getCanonicalPath());
+ progs.add("*:I");
+
+ logcatProc = Runtime.getRuntime().exec(progs.toArray(new String[progs.size()]));
+ logcatProc.waitFor();
+ } catch(Exception e) {
+ Util.toast(context, "Failed to gather logs");
+ } finally {
+ if(logcatProc != null) {
+ logcatProc.destroy();
+ }
+ }
+
+ return logcat;
+ }
+
+ @Override
+ protected void done(File logcat) {
+ String footer = "Android SDK: " + Build.VERSION.SDK;
+ footer += "\nDevice Model: " + Build.MODEL;
+ footer += "\nDevice Name: " + Build.MANUFACTURER + " " + Build.PRODUCT;
+ footer += "\nROM: " + Build.DISPLAY;
+
+ Intent email = new Intent(Intent.ACTION_SENDTO,
+ Uri.fromParts("mailto", "dsub.android@gmail.com", null));
+ email.putExtra(Intent.EXTRA_SUBJECT, "DSub " + version + " Error Logs");
+ email.putExtra(Intent.EXTRA_TEXT, "Describe the problem here\n\n\n" + footer);
+ Uri attachment = Uri.fromFile(logcat);
+ email.putExtra(Intent.EXTRA_STREAM, attachment);
+ startActivity(email);
+ }
+ }.execute();
+ } catch(Exception e) {}
+ }
+
+ private void getMostRecentCount() {
+ // Use stashed value until after refresh occurs
+ SharedPreferences prefs = Util.getPreferences(context);
+ final int startCount = prefs.getInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
+ setMostRecentCount(startCount);
+
+ new SilentBackgroundTask<Integer>(context) {
+ @Override
+ public Integer doInBackground() throws Exception {
+ String recentAddedFile = Util.getCacheName(context, "recent_count");
+ ArrayList<String> recents = FileUtil.deserialize(context, recentAddedFile, ArrayList.class);
+ if(recents == null) {
+ recents = new ArrayList<String>();
+ }
+
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ MusicDirectory recentlyAdded = musicService.getAlbumList("newest", 20, 0, context, null);
+
+ // If first run, just put everything in it and return 0
+ boolean firstRun = recents.isEmpty();
+
+ // Count how many new albums are in the list
+ int count = 0;
+ for(MusicDirectory.Entry album: recentlyAdded.getChildren()) {
+ if(!recents.contains(album.getId())) {
+ recents.add(album.getId());
+ count++;
+ }
+ }
+
+ // Keep recents list from growing infinitely
+ while(recents.size() > 40) {
+ recents.remove(0);
+ }
+ FileUtil.serialize(context, recents, recentAddedFile);
+
+ if(firstRun) {
+ return 0;
+ } else {
+ // Add the old count which will get cleared out after viewing recents
+ count += startCount;
+ SharedPreferences.Editor editor = Util.getPreferences(context).edit();
+ editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), count);
+ editor.commit();
+
+ return count;
+ }
+ }
+
+ @Override
+ public void done(Integer result) {
+ setMostRecentCount(result);
+ }
+
+ @Override
+ public void error(Throwable x) {
+ Log.w(TAG, "Failed to refresh most recent count", x);
+ }
+ }.execute();
+ }
+
+ private void setMostRecentCount(int count) {
+ if(count <= 0) {
+ countView.setVisibility(View.GONE);
+ } else {
+ String displayValue;
+ if(count < 10) {
+ displayValue = "0" + count;
+ } else {
+ displayValue = "" + count;
+ }
+
+ countView.setText(displayValue);
+ countView.setVisibility(View.VISIBLE);
+ }
+ }
+}