diff options
Diffstat (limited to 'app')
24 files changed, 709 insertions, 457 deletions
diff --git a/app/app.iml b/app/app.iml index 28b7ee49..64c8e5af 100644 --- a/app/app.iml +++ b/app/app.iml @@ -71,9 +71,12 @@ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.1.1/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/mediarouter-v7/22.1.1/jars" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.1.1/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.1.1/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-base/7.0.0/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-cast/7.0.0/jars" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.sothree.slidinguppanel/library/3.0.0/jars" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/de.hdodenhof/circleimageview/1.2.1/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" /> @@ -94,27 +97,31 @@ <orderEntry type="library" exported="" name="mediarouter-v7-22.1.1" level="project" /> <orderEntry type="library" exported="" name="seamless-util-1.1.0" level="project" /> <orderEntry type="library" exported="" name="cling-core-2.0.1" level="project" /> + <orderEntry type="library" exported="" name="recyclerview-v7-22.1.1" level="project" /> <orderEntry type="library" exported="" name="jetty-continuation-8.1.16.v20140903" level="project" /> - <orderEntry type="library" exported="" name="javax.servlet-3.0.0.v201112011016" level="project" /> - <orderEntry type="library" exported="" name="jetty-server-8.1.16.v20140903" level="project" /> <orderEntry type="library" exported="" name="support-annotations-22.1.1" level="project" /> - <orderEntry type="library" exported="" name="support-v4-22.1.1" level="project" /> <orderEntry type="library" exported="" name="play-services-cast-7.0.0" level="project" /> - <orderEntry type="library" exported="" name="cling-support-2.0.1" level="project" /> <orderEntry type="library" exported="" name="seamless-http-1.1.0" level="project" /> <orderEntry type="library" exported="" name="jetty-util-8.1.16.v20140903" level="project" /> <orderEntry type="library" exported="" name="appcompat-v7-22.1.1" level="project" /> <orderEntry type="library" exported="" name="seamless-swing-1.1.0" level="project" /> <orderEntry type="library" exported="" name="seamless-xml-1.1.0" level="project" /> + <orderEntry type="library" exported="" name="kryo-2.21-all" level="project" /> + <orderEntry type="library" exported="" name="play-services-base-7.0.0" level="project" /> + <orderEntry type="library" exported="" name="jetty-http-8.1.16.v20140903" level="project" /> + <orderEntry type="library" exported="" name="library-2.4.0" level="project" /> + <orderEntry type="library" exported="" name="javax.servlet-3.0.0.v201112011016" level="project" /> + <orderEntry type="library" exported="" name="jetty-server-8.1.16.v20140903" level="project" /> + <orderEntry type="library" exported="" name="support-v4-22.1.1" level="project" /> + <orderEntry type="library" exported="" name="cling-support-2.0.1" level="project" /> <orderEntry type="library" exported="" name="jetty-io-8.1.16.v20140903" level="project" /> <orderEntry type="library" exported="" name="CWAC-EndlessAdapter" level="project" /> + <orderEntry type="library" exported="" name="circleimageview-1.2.1" level="project" /> <orderEntry type="library" exported="" name="jetty-security-8.1.16.v20140903" level="project" /> - <orderEntry type="library" exported="" name="kryo-2.21-all" level="project" /> - <orderEntry type="library" exported="" name="play-services-base-7.0.0" level="project" /> <orderEntry type="library" exported="" name="jetty-servlet-8.1.16.v20140903" level="project" /> <orderEntry type="library" exported="" name="CWAC-AdapterWrapper" level="project" /> + <orderEntry type="library" exported="" name="library-3.0.0" level="project" /> <orderEntry type="library" exported="" name="jetty-client-8.1.16.v20140903" level="project" /> - <orderEntry type="library" exported="" name="jetty-http-8.1.16.v20140903" level="project" /> <orderEntry type="module" module-name="DragSort ListView" exported="" /> <orderEntry type="module" module-name="Server Proxy" exported="" /> </component> diff --git a/app/build.gradle b/app/build.gradle index 97e72a11..56da71aa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,6 +33,8 @@ dependencies { compile 'com.android.support:appcompat-v7:22.1.1' compile 'com.android.support:mediarouter-v7:22.1.1' compile 'com.google.android.gms:play-services-cast:7.0.0' + compile 'com.sothree.slidinguppanel:library:3.0.0' + compile 'de.hdodenhof:circleimageview:1.2.1' compile group: 'org.fourthline.cling', name: 'cling-core', version:'2.0.1' compile group: 'org.fourthline.cling', name: 'cling-support', version:'2.0.1' compile group: 'org.eclipse.jetty', name: 'jetty-server', version:'8.1.16.v20140903' diff --git a/app/src/main/java/github/daneren2005/dsub/activity/DownloadActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/DownloadActivity.java deleted file mode 100644 index e13a8b8c..00000000 --- a/app/src/main/java/github/daneren2005/dsub/activity/DownloadActivity.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see <http://www.gnu.org/licenses/>. - - Copyright 2009 (C) Sindre Mehus - */ -package github.daneren2005.dsub.activity; - -import github.daneren2005.dsub.R; -import android.os.Bundle; -import android.view.MotionEvent; -import github.daneren2005.dsub.fragments.NowPlayingFragment; - -import android.widget.EditText; - -import github.daneren2005.dsub.util.Constants; - -public class DownloadActivity extends SubsonicActivity { - private static final String TAG = DownloadActivity.class.getSimpleName(); - private EditText playlistNameView; - - /** - * Called when the activity is first created. - */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.download_activity); - - if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) { - currentFragment = new NowPlayingFragment(); - if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) { - Bundle args = new Bundle(); - args.putBoolean(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true); - currentFragment.setArguments(args); - } - currentFragment.setPrimaryFragment(true); - getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit(); - } - } - - @Override - public boolean onTouchEvent(MotionEvent me) { - if(currentFragment != null && currentFragment.getGestureDetector() != null) { - return currentFragment.getGestureDetector().onTouchEvent(me); - } else { - return false; - } - } -} diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java index 4651eb0b..cb09728c 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java @@ -51,6 +51,7 @@ import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; +import android.widget.ImageView; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; @@ -68,6 +69,7 @@ import github.daneren2005.dsub.service.DownloadService; import github.daneren2005.dsub.service.HeadphoneListenerService; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.ImageLoader; +import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.adapter.DrawerAdapter; import github.daneren2005.dsub.view.UpdateView; @@ -97,6 +99,10 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte ActionBarDrawerToggle drawerToggle; DrawerAdapter drawerAdapter; ListView drawerList; + View drawerHeader; + ImageView drawerUserAvatar; + TextView drawerServerName; + TextView drawerUserName; TextView lastSelectedView = null; int lastSelectedPosition = 0; boolean drawerOpen = false; @@ -118,17 +124,6 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte super.onCreate(bundle); startService(new Intent(this, DownloadService.class)); setVolumeControlStream(AudioManager.STREAM_MUSIC); - - View actionbar = getLayoutInflater().inflate(R.layout.actionbar_spinner, null); - actionBarSpinner = (Spinner)actionbar.findViewById(R.id.spinner); - spinnerAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item); - spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - actionBarSpinner.setOnItemSelectedListener(this); - actionBarSpinner.setAdapter(spinnerAdapter); - - getSupportActionBar().setCustomView(actionbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); if(getIntent().hasExtra(Constants.FRAGMENT_POSITION)) { lastSelectedPosition = getIntent().getIntExtra(Constants.FRAGMENT_POSITION, 0); @@ -138,6 +133,13 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); + + if(spinnerAdapter == null) { + createCustomActionBarView(); + } + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setHomeButtonEnabled(true); + // Sync the toggle state after onRestoreInstanceState has occurred. if(drawerToggle != null) { drawerToggle.syncState(); @@ -150,6 +152,17 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } } + protected void createCustomActionBarView() { + View customActionbar = getLayoutInflater().inflate(R.layout.actionbar_spinner, null); + actionBarSpinner = (Spinner)customActionbar.findViewById(R.id.spinner); + spinnerAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item); + spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + actionBarSpinner.setOnItemSelectedListener(this); + actionBarSpinner.setAdapter(spinnerAdapter); + + getSupportActionBar().setCustomView(customActionbar); + } + @Override protected void onResume() { super.onResume(); @@ -160,7 +173,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte restart(); overridePendingTransition(R.anim.fade_in, R.anim.fade_out); } - + populateDrawer(); UpdateView.addActiveActivity(); } @@ -210,12 +223,12 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte LayoutInflater layoutInflater = getLayoutInflater(); layoutInflater.inflate(viewId, rootView); } - + drawerList = (ListView) findViewById(R.id.left_drawer); drawerList.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, final View view, final int position, long id) { - final int actualPosition = drawerAdapter.getActualPosition(position); + final int actualPosition = drawerAdapter.getActualPosition(position - 1); if("Settings".equals(drawerItemsDescriptions[actualPosition])) { startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class)); drawer.closeDrawers(); @@ -232,7 +245,13 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } }); + drawerHeader = getLayoutInflater().inflate(R.layout.drawer_header, drawerList, false); + drawerServerName = (TextView) drawerHeader.findViewById(R.id.header_server_name); + drawerUserName = (TextView) drawerHeader.findViewById(R.id.header_user_name); + drawerUserAvatar = (ImageView) drawerHeader.findViewById(R.id.header_user_avatar); + updateDrawerHeader(); + drawerList.addHeaderView(drawerHeader, null, false); if(!isTv()) { drawer = (DrawerLayout) findViewById(R.id.drawer_layout); @@ -258,7 +277,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } if (lastSelectedView == null && drawerList.getCount() > lastSelectedPosition) { - lastSelectedView = (TextView) drawerList.getChildAt(lastSelectedPosition).findViewById(R.id.drawer_name); + lastSelectedView = (TextView) drawerList.getChildAt(lastSelectedPosition + 1).findViewById(R.id.drawer_name); if (lastSelectedView != null) { lastSelectedView.setTextAppearance(SubsonicActivity.this, R.style.DSub_TextViewStyle_Bold); } @@ -299,7 +318,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte primaryContainer = findViewById(R.id.fragment_container); } } - + @Override public void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); @@ -370,10 +389,11 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte public void onNewIntent(Intent intent) { super.onNewIntent(intent); } - + @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); + SubsonicFragment currentFragment = getCurrentFragment(); if(drawerOpen) { menuInflater.inflate(R.menu.drawer_menu, menu); } else if(currentFragment != null) { @@ -399,7 +419,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte return true; } - return currentFragment.onOptionsItemSelected(item); + return getCurrentFragment().onOptionsItemSelected(item); } @Override @@ -415,7 +435,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } return super.onKeyDown(keyCode, event); } - + @Override public void setTitle(CharSequence title) { if(title != null && !title.equals(getSupportActionBar().getTitle())) { @@ -426,7 +446,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte public void setSubtitle(CharSequence title) { getSupportActionBar().setSubtitle(title); } - + @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { int top = spinnerAdapter.getCount() - 1; @@ -439,9 +459,9 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte @Override public void onNothingSelected(AdapterView<?> parent) { - + } - + private void populateDrawer() { SharedPreferences prefs = Util.getPreferences(this); boolean podcastsEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_PODCASTS_ENABLED, true); @@ -449,7 +469,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte boolean sharedEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SHARED_ENABLED, true) && !Util.isOffline(this); boolean chatEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_CHAT_ENABLED, true) && !Util.isOffline(this); boolean adminEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_ADMIN_ENABLED, true) && !Util.isOffline(this); - + if(drawerItems == null || !enabledItems[0] == podcastsEnabled || !enabledItems[1] == bookmarksEnabled || !enabledItems[2] == sharedEnabled || !enabledItems[3] == chatEnabled || !enabledItems[4] == adminEnabled) { drawerItems = getResources().getStringArray(R.array.drawerItems); drawerItemsDescriptions = getResources().getStringArray(R.array.drawerItemsDescriptions); @@ -488,7 +508,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte if(!getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) { drawerItemsVisibleList.set(8, false); } - + drawerList.setAdapter(drawerAdapter = new DrawerAdapter(this, drawerItemsList, drawerItemsIconsList, drawerItemsVisibleList)); enabledItems[0] = podcastsEnabled; enabledItems[1] = bookmarksEnabled; @@ -506,26 +526,26 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } } - if(drawerList.getChildAt(lastSelectedPosition) == null) { + if(drawerList.getChildAt(lastSelectedPosition + 1) == null) { lastSelectedView = null; drawerAdapter.setSelectedPosition(lastSelectedPosition); } else { - lastSelectedView = (TextView) drawerList.getChildAt(lastSelectedPosition).findViewById(R.id.drawer_name); + lastSelectedView = (TextView) drawerList.getChildAt(lastSelectedPosition + 1).findViewById(R.id.drawer_name); if(lastSelectedView != null) { lastSelectedView.setTextAppearance(SubsonicActivity.this, R.style.DSub_TextViewStyle_Bold); } } } } - - private void drawerItemSelected(int position, View view) { + + protected void drawerItemSelected(int position, View view) { startFragmentActivity(drawerItemsDescriptions[position]); - + if(lastSelectedView != view) { if(lastSelectedView != null) { lastSelectedView.setTextAppearance(this, R.style.DSub_TextViewStyle); } - + lastSelectedView = (TextView) view.findViewById(R.id.drawer_name); lastSelectedView.setTextAppearance(this, R.style.DSub_TextViewStyle_Bold); lastSelectedPosition = position; @@ -575,6 +595,10 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } } + protected SubsonicFragment getCurrentFragment() { + return this.currentFragment; + } + public void replaceFragment(SubsonicFragment fragment, int tag) { replaceFragment(fragment, tag, false); } @@ -628,11 +652,11 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte backStack.remove(backStack.size() - 1); } } - + // Add fragment to the right container trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); trans.add(R.id.fragment_second_container, fragment, tag + ""); - + // Commit it all trans.commit(); } @@ -656,7 +680,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte trans.commit(); } else { FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); - + // Remove old right fragment trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left); trans.remove(oldFrag); @@ -682,7 +706,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte secondaryContainer.startAnimation(AnimationUtils.loadAnimation(this, R.anim.exit_to_right)); secondaryContainer.setVisibility(View.GONE); } - + trans.commit(); } recreateSpinner(); @@ -697,14 +721,17 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte currentFragment.invalidate(); populateDrawer(); } - + supportInvalidateOptionsMenu(); } - + protected void recreateSpinner() { if(currentFragment == null || currentFragment.getTitle() == null) { return; } + if(spinnerAdapter == null) { + createCustomActionBarView(); + } if(backStack.size() > 0) { spinnerAdapter.clear(); @@ -727,6 +754,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte getSupportActionBar().setDisplayShowCustomEnabled(true); } } else if(!isTv()) { + getSupportActionBar().setTitle(currentFragment.getTitle()); getSupportActionBar().setDisplayShowCustomEnabled(false); } } @@ -745,7 +773,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte theme = theme.substring(0, theme.indexOf("_fullscreen")); Util.setTheme(this, theme); } - + Util.applyTheme(this, theme); } private void applyFullscreen() { @@ -754,8 +782,8 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte // Hide additional elements on higher Android versions if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_FULLSCREEN | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; getWindow().getDecorView().setSystemUiVisibility(flags); } else if(Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { @@ -786,7 +814,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte if(finished) { return null; } - + // If service is not available, request it to start and wait for it. for (int i = 0; i < 5; i++) { DownloadService downloadService = DownloadService.getInstance(); @@ -799,7 +827,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } return DownloadService.getInstance(); } - + public static String getThemeName() { return theme; } @@ -811,6 +839,38 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte return touchscreen; } + public void openNowPlaying() { + + } + public void closeNowPlaying() { + + } + + public void setActiveServer(int instance) { + if (Util.getActiveServer(this) != instance) { + final DownloadService service = getDownloadService(); + if (service != null) { + new SilentBackgroundTask<Void>(this) { + @Override + protected Void doInBackground() throws Throwable { + service.clearIncomplete(); + return null; + } + }.execute(); + + } + Util.setActiveServer(this, instance); + invalidate(); + UserUtil.refreshCurrentUser(this, false, true); + updateDrawerHeader(); + } + } + private void updateDrawerHeader() { + drawerServerName.setText(Util.getServerName(this)); + drawerUserName.setText(UserUtil.getCurrentUsername(this)); + getImageLoader().loadAvatar(this, drawerUserAvatar, UserUtil.getCurrentUsername(this)); + } + private void setUncaughtExceptionHandler() { Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler(); if (!(handler instanceof SubsonicActivity.SubsonicUncaughtExceptionHandler)) { diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java index 6614e09d..83d5bce8 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java @@ -31,14 +31,17 @@ import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.FragmentTransaction; +import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.MenuItem; import android.view.View; import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.TextView; +import com.sothree.slidinguppanel.SlidingUpPanelLayout; + import java.io.File; -import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -53,6 +56,7 @@ import github.daneren2005.dsub.fragments.AdminFragment; import github.daneren2005.dsub.fragments.ChatFragment; import github.daneren2005.dsub.fragments.DownloadFragment; import github.daneren2005.dsub.fragments.MainFragment; +import github.daneren2005.dsub.fragments.NowPlayingFragment; import github.daneren2005.dsub.fragments.SearchFragment; import github.daneren2005.dsub.fragments.SelectArtistFragment; import github.daneren2005.dsub.fragments.SelectBookmarkFragment; @@ -66,7 +70,6 @@ import github.daneren2005.dsub.service.DownloadService; import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.service.MusicServiceFactory; import github.daneren2005.dsub.updates.Updater; -import github.daneren2005.dsub.util.BackgroundTask; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.SilentBackgroundTask; @@ -83,9 +86,15 @@ public class SubsonicFragmentActivity extends SubsonicActivity { private static boolean sessionInitialized = false; private static long ALLOWED_SKEW = 30000L; + private Handler handler = new Handler(); + private SlidingUpPanelLayout slideUpPanel; + private NowPlayingFragment nowPlayingFragment; + private Toolbar mainToolbar; + private Toolbar nowPlayingToolbar; + private ScheduledExecutorService executorService; private View bottomBar; - private View coverArtView; + private ImageView coverArtView; private TextView trackView; private TextView artistView; private ImageButton startButton; @@ -105,14 +114,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity { if(drawerAdapter != null) { drawerAdapter.setDownloadVisible(true); } - } else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) { - DownloadService service = getDownloadService(); - if((service != null && service.getCurrentPlaying() != null)) { - getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD); - Intent intent = new Intent(); - intent.setClass(this, DownloadActivity.class); - startActivity(intent); - } } setContentView(R.layout.abstract_fragment_activity); @@ -128,49 +129,112 @@ public class SubsonicFragmentActivity extends SubsonicActivity { } } currentFragment = getNewFragment(fragmentType); - + if("".equals(fragmentType) || fragmentType == null || firstRun) { // Initial startup stuff if(!sessionInitialized) { loadSession(); } } - + currentFragment.setPrimaryFragment(true); getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit(); - + if(getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) { SearchFragment fragment = new SearchFragment(); replaceFragment(fragment, fragment.getSupportTag()); } - + // If a album type is set, switch to that album type view String albumType = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE); if(albumType != null) { SubsonicFragment fragment = new SelectDirectoryFragment(); - + Bundle args = new Bundle(); args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, albumType); 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, fragment.getSupportTag()); } } - bottomBar = findViewById(R.id.bottom_bar); - bottomBar.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(); - intent.setClass(v.getContext(), DownloadActivity.class); - startActivity(intent); + slideUpPanel = (SlidingUpPanelLayout) findViewById(R.id.slide_up_panel); + slideUpPanel.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() { + @Override + public void onPanelSlide(View panel, float slideOffset) { + + } + + @Override + public void onPanelCollapsed(View panel) { + bottomBar.setVisibility(View.VISIBLE); + nowPlayingToolbar.setVisibility(View.GONE); + nowPlayingFragment.setPrimaryFragment(false); + setSupportActionBar(mainToolbar); + + if(getSupportActionBar().getCustomView() == null) { + createCustomActionBarView(); + } + recreateSpinner(); + if(drawerToggle != null && backStack.size() > 0) { + drawerToggle.setDrawerIndicatorEnabled(false); + } else { + drawerToggle.setDrawerIndicatorEnabled(true); + } + } + + @Override + public void onPanelExpanded(View panel) { + // Disable custom view before switching + getSupportActionBar().setDisplayShowCustomEnabled(false); + + bottomBar.setVisibility(View.GONE); + nowPlayingToolbar.setVisibility(View.VISIBLE); + setSupportActionBar(nowPlayingToolbar); + nowPlayingFragment.setPrimaryFragment(true); + + drawerToggle.setDrawerIndicatorEnabled(false); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setHomeAsUpIndicator(coverArtView.getDrawable()); + } + + @Override + public void onPanelAnchored(View panel) { + + } + + @Override + public void onPanelHidden(View panel) { + } }); - coverArtView = bottomBar.findViewById(R.id.album_art); + + if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) { + // Post this later so it actually runs + handler.postDelayed(new Runnable() { + @Override + public void run() { + openNowPlaying(); + } + }, 200); + } + + bottomBar = findViewById(R.id.bottom_bar); + mainToolbar = (Toolbar) findViewById(R.id.main_toolbar); + nowPlayingToolbar = (Toolbar) findViewById(R.id.now_playing_toolbar); + coverArtView = (ImageView) bottomBar.findViewById(R.id.album_art); trackView = (TextView) bottomBar.findViewById(R.id.track_name); artistView = (TextView) bottomBar.findViewById(R.id.artist_name); + setSupportActionBar(mainToolbar); + + nowPlayingFragment = new NowPlayingFragment(); + FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); + trans.add(R.id.now_playing_fragment_container, nowPlayingFragment, nowPlayingFragment.getTag() + ""); + trans.commit(); + ImageButton previousButton = (ImageButton) findViewById(R.id.download_previous); previousButton.setOnClickListener(new View.OnClickListener() { @Override @@ -262,7 +326,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity { } } } - + @Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); @@ -300,7 +364,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity { public void onResume() { super.onResume(); - final Handler handler = new Handler(); Runnable runnable = new Runnable() { @Override public void run() { @@ -369,7 +432,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity { @Override public void onBackPressed() { - if(onBackPressedSupport()) { + if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + } else if(onBackPressedSupport()) { if(!Util.disableExitPrompt(this) && lastBackPressTime < (System.currentTimeMillis() - 4000)) { lastBackPressTime = System.currentTimeMillis(); Util.toast(this, R.string.main_back_confirm); @@ -380,6 +445,15 @@ public class SubsonicFragmentActivity extends SubsonicActivity { } @Override + protected SubsonicFragment getCurrentFragment() { + if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + return nowPlayingFragment; + } else { + return super.getCurrentFragment(); + } + } + + @Override public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) { super.replaceFragment(fragment, tag, replaceCurrent); if(drawerToggle != null) { @@ -393,24 +467,33 @@ public class SubsonicFragmentActivity extends SubsonicActivity { drawerToggle.setDrawerIndicatorEnabled(true); } } - + + @Override + protected void drawerItemSelected(int position, View view) { + super.drawerItemSelected(position, view); + + if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + } + } + @Override public void startFragmentActivity(String fragmentType) { // Create a transaction that does all of this FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); - + // Clear existing stack for(int i = backStack.size() - 1; i >= 0; i--) { trans.remove(backStack.get(i)); } trans.remove(currentFragment); backStack.clear(); - + // Create new stack currentFragment = getNewFragment(fragmentType); currentFragment.setPrimaryFragment(true); trans.add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + ""); - + // Done, cleanup trans.commit(); supportInvalidateOptionsMenu(); @@ -426,7 +509,16 @@ public class SubsonicFragmentActivity extends SubsonicActivity { drawerToggle.setDrawerIndicatorEnabled(true); } } - + + @Override + public void openNowPlaying() { + slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); + } + @Override + public void closeNowPlaying() { + slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + } + private SubsonicFragment getNewFragment(String fragmentType) { if("Artist".equals(fragmentType)) { return new SelectArtistFragment(); @@ -447,7 +539,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity { } else { return new MainFragment(); } - } + } private void update() { DownloadService downloadService = getDownloadService(); @@ -470,11 +562,23 @@ public class SubsonicFragmentActivity extends SubsonicActivity { trackView.setText(song.getTitle()); artistView.setText(song.getArtist()); } else { - trackView.setText("Title"); - artistView.setText("Artist"); + trackView.setText(R.string.main_title); + artistView.setText(R.string.main_artist); } - getImageLoader().loadImage(coverArtView, song, false, false); + SilentBackgroundTask task = getImageLoader().loadImage(coverArtView, song, false, coverArtView.getHeight(), false); + if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + if(task == null) { + getSupportActionBar().setHomeAsUpIndicator(coverArtView.getDrawable()); + } else { + task.setOnCompletionListener(new Runnable() { + @Override + public void run() { + getSupportActionBar().setHomeAsUpIndicator(coverArtView.getDrawable()); + } + }); + } + } int[] attrs = new int[] {(state == PlayerState.STARTED) ? R.attr.media_button_pause : R.attr.media_button_start}; TypedArray typedArray = this.obtainStyledAttributes(attrs); startButton.setImageResource(typedArray.getResourceId(0, 0)); @@ -502,7 +606,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity { if(ServerInfo.canSavePlayQueue(this) && !Util.isOffline(this)) { loadRemotePlayQueue(); } - + sessionInitialized = true; } private void loadSettings() { @@ -551,7 +655,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity { return true; } } - + private void loadBookmarks() { final Context context = this; new SilentBackgroundTask<Void>(context) { @@ -562,7 +666,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity { return null; } - + @Override public void error(Throwable error) { Log.e(TAG, "Failed to get bookmarks", error); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java index ae38534a..71c135aa 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java @@ -140,7 +140,7 @@ public class MainFragment extends SubsonicFragment { } int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE; - setActiveServer(activeServer); + context.setActiveServer(activeServer); return true; } @@ -252,25 +252,6 @@ public class MainFragment extends SubsonicFragment { } } - 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); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java index 3e30af50..b9ef412c 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java @@ -20,6 +20,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import android.annotation.TargetApi; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; @@ -141,6 +142,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis startFlipped = true; } } + primaryFragment = false; } @Override @@ -153,11 +155,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { rootView = inflater.inflate(R.layout.download, container, false); setTitle(R.string.button_bar_now_playing); - + mainLayout = rootView.findViewById(R.id.download_layout); - if(!primaryFragment) { - mainLayout.setVisibility(View.GONE); - } WindowManager w = context.getWindowManager(); Display d = w.getDefaultDisplay(); @@ -397,7 +396,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } else { // Immediately skip to the next song downloadService.next(true); - + // Otherwise set rating to 1 setRating(entry, 1); rateBadButton.setImageResource(R.drawable.ic_action_rating_bad_selected); @@ -543,13 +542,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis registerForContextMenu(playlistView); - DownloadService downloadService = getDownloadService(); - if (downloadService != null && context.getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) { - context.getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE); - warnIfStorageUnavailable(); - downloadService.setShufflePlayEnabled(true); - } - if(Build.MODEL.equals("Nexus 4") || Build.MODEL.equals("GT-I9100")) { View slider = rootView.findViewById(R.id.download_slider); slider.setPadding(0, 0, 0, 0); @@ -604,7 +596,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis if(menuItemSelected(menuItem.getItemId(), null)) { return true; } - + return super.onOptionsItemSelected(menuItem); } @@ -641,7 +633,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis if(!primaryFragment) { return false; } - + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); DownloadFile downloadFile = (DownloadFile) playlistView.getItemAtPosition(info.position); return menuItemSelected(menuItem.getItemId(), downloadFile) || super.onContextItemSelected(menuItem); @@ -841,7 +833,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override public void onResume() { super.onResume(); - + if(this.primaryFragment) { + onResumeHandlers(); + } else { + update(); + } + } + private void onResumeHandlers() { final Handler handler = new Handler(); Runnable runnable = new Runnable() { @Override @@ -898,25 +896,46 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override public void onPause() { super.onPause(); - executorService.shutdown(); - if(getDownloadService() != null) { - getDownloadService().stopRemoteScan(); + onPauseHandlers(); + } + private void onPauseHandlers() { + if(executorService != null) { + executorService.shutdown(); + if (getDownloadService() != null) { + getDownloadService().stopRemoteScan(); + } + executorService = null; + playlistFlipper.setDisplayedChild(0); } } - + @Override public void setPrimaryFragment(boolean primary) { super.setPrimaryFragment(primary); if(rootView != null) { if(primary) { - mainLayout.setVisibility(View.VISIBLE); - updateButtons(); + onResumeHandlers(); } else { - mainLayout.setVisibility(View.GONE); + onPauseHandlers(); } } } + @Override + public void setTitle(int title) { + this.title = context.getResources().getString(title); + if(this.primaryFragment) { + context.setTitle(this.title); + } + } + @Override + public void setSubtitle(CharSequence title) { + this.subtitle = title; + if(this.primaryFragment) { + context.setSubtitle(title); + } + } + private void scheduleHideControls() { if (hideControlsFuture != null) { hideControlsFuture.cancel(false); @@ -954,7 +973,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis if(context == null) { return; } - + if(Util.isOffline(context)) { bookmarkButton.setVisibility(View.GONE); rateBadButton.setVisibility(View.GONE); @@ -971,6 +990,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } // Scroll to current playing/downloading. + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void scrollToCurrent() { if (getDownloadService() == null || songListAdapter == null) { scrollWhenLoaded = true; @@ -1043,26 +1063,26 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis public void onStopTrackingTouch(SeekBar seekBar) { } }); - lengthBar.setProgress(length - 1); + lengthBar.setProgress(length - 1); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.menu_set_timer) - .setView(dialogView) - .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - int length = getMinutes(lengthBar.getProgress()); + .setView(dialogView) + .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + int length = getMinutes(lengthBar.getProgress()); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(Constants.PREFERENCES_KEY_SLEEP_TIMER_DURATION, Integer.toString(length)); - editor.commit(); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(Constants.PREFERENCES_KEY_SLEEP_TIMER_DURATION, Integer.toString(length)); + editor.commit(); - getDownloadService().setSleepTimerDuration(length); - getDownloadService().startSleepTimer(); - context.supportInvalidateOptionsMenu(); - } - }) - .setNegativeButton(R.string.common_cancel, null); + getDownloadService().setSleepTimerDuration(length); + getDownloadService().startSleepTimer(); + context.supportInvalidateOptionsMenu(); + } + }) + .setNegativeButton(R.string.common_cancel, null); AlertDialog dialog = builder.create(); dialog.show(); } @@ -1087,7 +1107,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis playlistFlipper.setInAnimation(AnimationUtils.loadAnimation(context, R.anim.push_up_in)); playlistFlipper.setOutAnimation(AnimationUtils.loadAnimation(context, R.anim.push_up_out)); playlistFlipper.setDisplayedChild(1); - + UpdateView.triggerUpdate(); } } @@ -1125,7 +1145,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis protected Void doInBackground() throws Throwable { currentPlayingIndex = downloadService.getCurrentPlayingIndex() + 1; size = downloadService.size(); - + return null; } @@ -1133,14 +1153,14 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis protected void done(Void result) { List<DownloadFile> list; list = downloadService.getSongs(); - + if(downloadService.isShufflePlayEnabled()) { emptyTextView.setText(R.string.download_shuffle_loading); } else { emptyTextView.setText(R.string.download_empty); } - + if(songListAdapter == null || refresh) { songList = new ArrayList<DownloadFile>(); songList.addAll(list); @@ -1150,7 +1170,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis songList.addAll(list); songListAdapter.notifyDataSetChanged(); } - + emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE); currentRevision = downloadService.getDownloadListUpdateRevision(); @@ -1171,7 +1191,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis default: break; } - + if(scrollWhenLoaded) { scrollToCurrent(); scrollWhenLoaded = false; @@ -1194,7 +1214,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis if (downloadService == null || onCurrentChangedTask != null) { return; } - + onCurrentChangedTask = new SilentBackgroundTask<Void>(context) { int currentPlayingIndex; int currentPlayingSize; @@ -1255,7 +1275,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } } }; - + if(onDownloadListChangedTask == null) { onCurrentChangedTask.execute(); } @@ -1395,33 +1415,33 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } }.execute(); } - + private void createBookmark() { DownloadService downloadService = getDownloadService(); if(downloadService == null) { return; } - + final DownloadFile currentDownload = downloadService.getCurrentPlaying(); if(currentDownload == null) { return; } - + View dialogView = context.getLayoutInflater().inflate(R.layout.create_bookmark, null); final EditText commentBox = (EditText)dialogView.findViewById(R.id.comment_text); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.download_save_bookmark_title) - .setView(dialogView) - .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - String comment = commentBox.getText().toString(); + .setView(dialogView) + .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + String comment = commentBox.getText().toString(); - createBookmark(currentDownload, comment); - } - }) - .setNegativeButton(R.string.common_cancel, null); + createBookmark(currentDownload, comment); + } + }) + .setNegativeButton(R.string.common_cancel, null); AlertDialog dialog = builder.create(); dialog.show(); } @@ -1430,13 +1450,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis if(downloadService == null) { return; } - + final Entry currentSong = currentDownload.getSong(); final int position = downloadService.getPlayerPosition(); final Bookmark oldBookmark = currentSong.getBookmark(); currentSong.setBookmark(new Bookmark(position)); bookmarkButton.setImageResource(R.drawable.ic_menu_bookmark_selected); - + new SilentBackgroundTask<Void>(context) { @Override protected Void doInBackground() throws Throwable { @@ -1458,12 +1478,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis Util.toast(context, R.string.download_save_bookmark); setControlsVisible(true); } - + @Override protected void error(Throwable error) { Log.w(TAG, "Failed to create bookmark", error); currentSong.setBookmark(oldBookmark); - + // If no bookmark at start, then return to no bookmark if(oldBookmark == null) { int bookmark; @@ -1474,14 +1494,14 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } bookmarkButton.setImageResource(bookmark); } - + String msg; if(error instanceof OfflineException || error instanceof ServerTooOldException) { msg = getErrorMessage(error); } else { msg = context.getResources().getString(R.string.download_save_bookmark_failed) + getErrorMessage(error); } - + Util.toast(context, msg, false); } }.execute(); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java index c71d99f6..830e2957 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java @@ -25,7 +25,6 @@ import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import github.daneren2005.dsub.R; -import github.daneren2005.dsub.activity.DownloadActivity; import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.service.DownloadService; @@ -110,7 +109,7 @@ public class SelectBookmarkFragment extends SelectListFragment<MusicDirectory.En @Override protected void done(Void result) { - Util.startActivityWithoutTransition(context, DownloadActivity.class); + context.openNowPlaying(); } }.execute(); } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 841a6369..9e7cd053 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -46,7 +46,6 @@ import java.io.Serializable; import java.util.Iterator; import java.util.List; -import github.daneren2005.dsub.activity.DownloadActivity; import github.daneren2005.dsub.domain.PodcastEpisode; import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.service.MusicServiceFactory; @@ -993,7 +992,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override protected void done(Void result) { if (autoplay) { - Util.startActivityWithoutTransition(context, DownloadActivity.class); + context.openNowPlaying(); } else if (save) { Util.toast(context, context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); @@ -1335,7 +1334,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override protected void done(Void result) { - Util.startActivityWithoutTransition(context, DownloadActivity.class); + context.openNowPlaying(); } }.execute(); } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java index 109983ba..fcae3a5c 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java @@ -18,6 +18,7 @@ */ package github.daneren2005.dsub.fragments; +import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; @@ -28,6 +29,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.media.MediaMetadataRetriever; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.StatFs; import android.support.v4.app.Fragment; @@ -49,7 +51,6 @@ import android.widget.EditText; import android.widget.RatingBar; import android.widget.TextView; import github.daneren2005.dsub.R; -import github.daneren2005.dsub.activity.DownloadActivity; import github.daneren2005.dsub.activity.SubsonicActivity; import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.domain.Artist; @@ -101,7 +102,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR private static final String TAG = SubsonicFragment.class.getSimpleName(); private static int TAG_INC = 10; private int tag; - + protected SubsonicActivity context; protected CharSequence title = null; protected CharSequence subtitle = null; @@ -116,7 +117,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR protected boolean artistOverride = false; protected SwipeRefreshLayout refreshLayout; protected boolean firstRun; - + public SubsonicFragment() { super(); tag = TAG_INC++; @@ -187,7 +188,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR return false; } - + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo, Object selected) { MenuInflater inflater = context.getMenuInflater(); @@ -199,7 +200,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } else { inflater.inflate(R.menu.select_podcast_episode_context, menu); - + if(entry.getBookmark() == null) { menu.removeItem(R.id.bookmark_menu_delete); } @@ -223,7 +224,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } else { inflater.inflate(R.menu.select_song_context, menu); - + if(entry.getBookmark() == null) { menu.removeItem(R.id.bookmark_menu_delete); } @@ -286,7 +287,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if(info.targetView instanceof SongView) { SongView songView = (SongView) info.targetView; DownloadFile downloadFile = songView.getDownloadFile(); - + try { if(downloadFile != null) { if(downloadFile.isWorkDone()) { @@ -294,7 +295,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if(downloadFile.isSaved()) { menu.removeItem(R.id.song_menu_pin); } - + // Remove cache option no matter what if already downloaded menu.removeItem(R.id.song_menu_download); } else { @@ -324,7 +325,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR folder = ((ArtistEntryView) info.targetView).getFile(); id = R.id.artist_menu_delete; } - + try { if(folder != null && !folder.exists()) { menu.removeItem(id); @@ -475,7 +476,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR return true; } - + public void replaceFragment(SubsonicFragment fragment) { replaceFragment(fragment, true); } @@ -492,7 +493,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR public int getSupportTag() { return tag; } - + public void setPrimaryFragment(boolean primary) { primaryFragment = primary; if(primary) { @@ -650,9 +651,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR protected void onShuffleRequested() { if(Util.isOffline(context)) { - Intent intent = new Intent(context, DownloadActivity.class); - intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true); - Util.startActivityWithoutTransition(context, intent); + DownloadService downloadService = getDownloadService(); + if(downloadService == null) { + return; + } + downloadService.setShufflePlayEnabled(true); + context.openNowPlaying(); return; } @@ -691,21 +695,21 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.shuffle_pick_genre) - .setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if(which == 0) { - genreCombo.setText(""); - } else { - genreCombo.setText(finalNames.get(which)); - } - } - }); + .setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + if(which == 0) { + genreCombo.setText(""); + } else { + genreCombo.setText(finalNames.get(which)); + } + } + }); AlertDialog dialog = builder.create(); dialog.show(); } @Override - protected void error(Throwable error) { + protected void error(Throwable error) { String msg; if (error instanceof OfflineException || error instanceof ServerTooOldException) { msg = getErrorMessage(error); @@ -731,31 +735,34 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.shuffle_title) - .setView(dialogView) - .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - Intent intent = new Intent(context, DownloadActivity.class); - intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true); - String genre; - if(useCombo) { - genre = genreCombo.getText().toString(); - } else { - genre = genreBox.getText().toString(); + .setView(dialogView) + .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + String genre; + if (useCombo) { + genre = genreCombo.getText().toString(); + } else { + genre = genreBox.getText().toString(); + } + String startYear = startYearBox.getText().toString(); + String endYear = endYearBox.getText().toString(); + + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear); + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear); + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre); + editor.commit(); + + DownloadService downloadService = getDownloadService(); + if (downloadService == null) { + return; + } + downloadService.setShufflePlayEnabled(true); + context.openNowPlaying(); } - String startYear = startYearBox.getText().toString(); - String endYear = endYearBox.getText().toString(); - - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear); - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear); - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre); - editor.commit(); - - Util.startActivityWithoutTransition(context, intent); - } - }) - .setNegativeButton(R.string.common_cancel, null); + }) + .setNegativeButton(R.string.common_cancel, null); AlertDialog dialog = builder.create(); dialog.show(); } @@ -906,7 +913,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR playNowOverride = true; return false; } - + if (!append && !background) { downloadService.clear(); } @@ -994,7 +1001,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR MusicService musicService = MusicServiceFactory.getMusicService(context); List<Playlist> playlists = new ArrayList<Playlist>(); playlists.addAll(musicService.getPlaylists(false, context, this)); - + // Iterate through and remove all non owned public playlists Iterator<Playlist> it = playlists.iterator(); while(it.hasNext()) { @@ -1003,7 +1010,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR it.remove(); } } - + return playlists; } @@ -1016,7 +1023,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override public View getView(int position, View convertView, ViewGroup parent) { Playlist playlist = getItem(position); - + // Create new if not getting a convert view to use PlaylistSongView view; if(convertView instanceof PlaylistSongView) { @@ -1033,21 +1040,21 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.playlist_add_to) - .setAdapter(playlistAdapter, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if (which > 0) { - addToPlaylist(playlists.get(which), songs); - } else { - createNewPlaylist(songs, false); + .setAdapter(playlistAdapter, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + if (which > 0) { + addToPlaylist(playlists.get(which), songs); + } else { + createNewPlaylist(songs, false); + } } - } - }); + }); AlertDialog dialog = builder.create(); dialog.show(); } @Override - protected void error(Throwable error) { + protected void error(Throwable error) { String msg; if (error instanceof OfflineException || error instanceof ServerTooOldException) { msg = getErrorMessage(error); @@ -1075,7 +1082,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } @Override - protected void error(Throwable error) { + protected void error(Throwable error) { String msg; if (error instanceof OfflineException || error instanceof ServerTooOldException) { msg = getErrorMessage(error); @@ -1087,7 +1094,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } }.execute(); } - + protected void createNewPlaylist(final List<Entry> songs, final boolean getSuggestion) { View layout = context.getLayoutInflater().inflate(R.layout.save_playlist, null); final EditText playlistNameView = (EditText) layout.findViewById(R.id.save_playlist_name); @@ -1115,34 +1122,34 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.download_playlist_title) - .setMessage(R.string.download_playlist_name) - .setView(layout) - .setPositiveButton(R.string.common_save, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - String playlistName = String.valueOf(playlistNameView.getText()); - if(overwriteCheckBox.isChecked()) { - overwritePlaylist(songs, playlistName, getDownloadService().getSuggestedPlaylistId()); - } else { - createNewPlaylist(songs, playlistName); - - if(getSuggestion) { - DownloadService downloadService = getDownloadService(); - if(downloadService != null) { - downloadService.setSuggestedPlaylistName(playlistName, null); + .setMessage(R.string.download_playlist_name) + .setView(layout) + .setPositiveButton(R.string.common_save, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + String playlistName = String.valueOf(playlistNameView.getText()); + if(overwriteCheckBox.isChecked()) { + overwritePlaylist(songs, playlistName, getDownloadService().getSuggestedPlaylistId()); + } else { + createNewPlaylist(songs, playlistName); + + if(getSuggestion) { + DownloadService downloadService = getDownloadService(); + if(downloadService != null) { + downloadService.setSuggestedPlaylistName(playlistName, null); + } } } } - } - }) - .setNegativeButton(R.string.common_cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }) - .setCancelable(true); - + }) + .setNegativeButton(R.string.common_cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }) + .setCancelable(true); + AlertDialog dialog = builder.create(); dialog.show(); } @@ -1184,7 +1191,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } @Override - protected void error(Throwable error) { + protected void error(Throwable error) { String msg; if (error instanceof OfflineException || error instanceof ServerTooOldException) { msg = getErrorMessage(error); @@ -1197,6 +1204,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } + @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) public void displaySongInfo(final Entry song) { Integer duration = null; Integer bitrate = null; @@ -1209,12 +1217,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if(file.exists()) { MediaMetadataRetriever metadata = new MediaMetadataRetriever(); metadata.setDataSource(file.getAbsolutePath()); - + String tmp = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); duration = Integer.parseInt((tmp != null) ? tmp : "0") / 1000; format = FileUtil.getExtension(file.getName()); size = file.length(); - + // If no duration try to read bitrate tag if(duration == null) { tmp = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); @@ -1224,7 +1232,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR // Divide by 1000 so in kbps bitrate = (int) (size / duration) / 1000 * 8; } - + if(Util.isOffline(context)) { song.setGenre(metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE)); String year = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR); @@ -1286,7 +1294,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR Util.info(context, song.getTitle(), msg); } - + protected void playVideo(Entry entry) { if(entryExists(entry)) { playExternalPlayer(entry); @@ -1315,7 +1323,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR intent.putExtra(Intent.EXTRA_TITLE, entry.getTitle()); List<ResolveInfo> intents = context.getPackageManager() - .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); if(intents != null && intents.size() > 0) { startActivity(intent); }else { @@ -1373,7 +1381,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR public void deleteRecursively(Artist artist) { deleteRecursively(FileUtil.getArtistDirectory(context, artist)); } - + public void deleteRecursively(Entry album) { deleteRecursively(FileUtil.getAlbumDirectory(context, album)); @@ -1490,7 +1498,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR intent.putExtra(Intent.EXTRA_TEXT, share.getUrl()); context.startActivity(Intent.createChooser(intent, context.getResources().getString(R.string.share_via))); } - + public GestureDetector getGestureDetector() { return gestureScanner; } @@ -1515,7 +1523,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR public void onClick(DialogInterface dialog, int id) { final Bookmark oldBookmark = song.getBookmark(); song.setBookmark(null); - + new SilentBackgroundTask<Void>(context) { @Override protected Void doInBackground() throws Throwable { @@ -1528,7 +1536,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override protected void error(Throwable error) { song.setBookmark(oldBookmark); - + String msg; if (error instanceof OfflineException || error instanceof ServerTooOldException) { msg = getErrorMessage(error); @@ -1546,7 +1554,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR AlertDialog dialog = builder.create(); dialog.show(); } - + protected void playNow(List<Entry> entries) { playNow(entries, null, null); } @@ -1558,7 +1566,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR break; } } - + // If no bookmark found, just play from start if(bookmark == null) { playNow(entries, 0, playlistName, playlistId); @@ -1585,17 +1593,17 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if(downloadService == null) { return null; } - + downloadService.clear(); downloadService.download(entries, false, true, true, false, entries.indexOf(song), position); downloadService.setSuggestedPlaylistName(playlistName, playlistId); return null; } - + @Override protected void done(Void result) { - Util.startActivityWithoutTransition(context, DownloadActivity.class); + context.openNowPlaying(); } }.execute(); } @@ -1657,19 +1665,19 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR View layout = context.getLayoutInflater().inflate(R.layout.rating, null); final RatingBar ratingBar = (RatingBar) layout.findViewById(R.id.rating_bar); ratingBar.setRating((float) entry.getRating()); - + AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(context.getResources().getString(R.string.rating_title, entry.getTitle())) - .setView(layout) - .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - int rating = (int) ratingBar.getRating(); - setRating(entry, rating, onRatingChange); - } - }) - .setNegativeButton(R.string.common_cancel, null); - + .setView(layout) + .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + int rating = (int) ratingBar.getRating(); + setRating(entry, rating, onRatingChange); + } + }) + .setNegativeButton(R.string.common_cancel, null); + AlertDialog dialog = builder.create(); dialog.show(); } @@ -1684,7 +1692,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if(onRatingChange != null) { onRatingChange.ratingChange(rating); } - + new SilentBackgroundTask<Void>(context) { @Override protected Void doInBackground() throws Throwable { @@ -1711,7 +1719,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if(onRatingChange != null) { onRatingChange.ratingChange(oldRating); } - + String msg; if (error instanceof OfflineException || error instanceof ServerTooOldException) { msg = getErrorMessage(error); @@ -1723,16 +1731,16 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } }.execute(); } - + protected abstract class EntryInstanceUpdater { private Entry entry; - + public EntryInstanceUpdater(Entry entry) { this.entry = entry; } - + public abstract void update(Entry found); - + public void execute() { DownloadService downloadService = getDownloadService(); if(downloadService != null && !entry.isDirectory()) { @@ -1745,12 +1753,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR serializeChanges = true; } } - + if(serializeChanges) { downloadService.serializeQueue(); } } - + Entry find = UpdateView.findEntry(entry); if(find != null) { update(find); @@ -1810,7 +1818,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } if(result) { - Util.startActivityWithoutTransition(context, DownloadActivity.class); + context.openNowPlaying(); } } } diff --git a/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java b/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java index 444b6cff..7cb3ce8b 100644 --- a/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java +++ b/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java @@ -39,7 +39,6 @@ import android.util.Log; import android.view.View; import android.widget.RemoteViews; import github.daneren2005.dsub.R; -import github.daneren2005.dsub.activity.DownloadActivity; import github.daneren2005.dsub.activity.SubsonicActivity; import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.domain.MusicDirectory; @@ -270,9 +269,7 @@ public class DSubWidgetProvider extends AppWidgetProvider { /** * Link up various button actions using {@link PendingIntent}. * - * @param playerActive True if player is active in background, which means - * widget click will launch {@link DownloadActivity}, - * otherwise we launch {@link github.daneren2005.dsub.activity.SubsonicFragmentActivity}. + * @param playerActive @param playerActive True if player is active in background. Launch {@link github.daneren2005.dsub.activity.SubsonicFragmentActivity}. */ private void linkButtons(Context context, RemoteViews views, boolean playerActive) { Intent intent = new Intent(context, SubsonicFragmentActivity.class); diff --git a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java index 7ba2064b..c3d86d4b 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java +++ b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java @@ -190,8 +190,11 @@ public class ImageLoader { } public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) { - // TODO: If we know this a artist, try to load artist info instead int size = large ? imageSizeLarge : imageSizeDefault; + return loadImage(view, entry, large, size, crossfade); + } + public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) { + // TODO: If we know this a artist, try to load artist info instead if(entry != null && !entry.isAlbum() && ServerInfo.checkServerVersion(context, "1.11") && !Util.isOffline(context)) { SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade); task.execute(); @@ -280,6 +283,7 @@ public class ImageLoader { view.setImageDrawable(drawable); return null; } + view.setImageDrawable(null); SilentBackgroundTask<Void> task = new AvatarTask(context, view, username); task.execute(); @@ -582,7 +586,6 @@ public class ImageLoader { } } catch (Throwable x) { Log.e(TAG, "Failed to download album art.", x); - cancelled.set(true); } return null; @@ -592,6 +595,8 @@ public class ImageLoader { protected void done(Void result) { if(mDrawable != null) { mView.setImageDrawable(mDrawable); + } else { + mView.setImageResource(R.drawable.ic_social_person); } } } diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java index 032facd6..969e178e 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Util.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java @@ -48,6 +48,7 @@ import android.view.Gravity; import android.widget.TextView; import android.widget.Toast; import github.daneren2005.dsub.R; +import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; import github.daneren2005.dsub.domain.RepeatMode; @@ -256,14 +257,26 @@ public final class Util { } public static void applyTheme(Context context, String theme) { - if ("dark".equals(theme)) { - context.setTheme(R.style.Theme_DSub_Dark); - } else if ("black".equals(theme)) { - context.setTheme(R.style.Theme_DSub_Black); - } else if ("holo".equals(theme)) { - context.setTheme(R.style.Theme_DSub_Holo); + if(context instanceof SubsonicFragmentActivity) { + if ("dark".equals(theme)) { + context.setTheme(R.style.Theme_DSub_Dark_No_Actionbar); + } else if ("black".equals(theme)) { + context.setTheme(R.style.Theme_DSub_Black_No_Actionbar); + } else if ("holo".equals(theme)) { + context.setTheme(R.style.Theme_DSub_Holo_No_Actionbar); + } else { + context.setTheme(R.style.Theme_DSub_Light_No_Actionbar); + } } else { - context.setTheme(R.style.Theme_DSub_Light); + if ("dark".equals(theme)) { + context.setTheme(R.style.Theme_DSub_Dark); + } else if ("black".equals(theme)) { + context.setTheme(R.style.Theme_DSub_Black); + } else if ("holo".equals(theme)) { + context.setTheme(R.style.Theme_DSub_Holo); + } else { + context.setTheme(R.style.Theme_DSub_Light); + } } SharedPreferences prefs = Util.getPreferences(context); diff --git a/app/src/main/res/layout-large-land/abstract_fragment_container.xml b/app/src/main/res/layout-large-land/abstract_fragment_container.xml index 5e3b1561..3901710f 100644 --- a/app/src/main/res/layout-large-land/abstract_fragment_container.xml +++ b/app/src/main/res/layout-large-land/abstract_fragment_container.xml @@ -2,8 +2,8 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" - android:layout_height="0px" - android:layout_weight="1"> + android:layout_height="match_parent" + android:layout_marginTop="?attr/actionBarSize"> <FrameLayout android:id="@+id/fragment_container" diff --git a/app/src/main/res/layout/abstract_fragment_activity.xml b/app/src/main/res/layout/abstract_fragment_activity.xml index d9c99f2f..29fbc3b1 100644 --- a/app/src/main/res/layout/abstract_fragment_activity.xml +++ b/app/src/main/res/layout/abstract_fragment_activity.xml @@ -1,84 +1,131 @@ -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<com.sothree.slidinguppanel.SlidingUpPanelLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sothree="http://schemas.android.com/apk/res-auto" + android:id="@+id/slide_up_panel" android:layout_width="match_parent" android:layout_height="match_parent" - android:gravity="center_horizontal" - android:orientation="vertical" > + android:gravity="bottom" + sothree:umanoPanelHeight="?attr/actionBarSize" + sothree:umanoShadowHeight="4dp" + sothree:umanoDragView="@+id/slide_up_swipe_target"> - <include layout="@layout/abstract_fragment_container" /> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent"> - <View - android:layout_width="fill_parent" - android:layout_height="1px" - android:background="@color/dividerColor"/> + <android.support.v7.widget.Toolbar + android:id="@+id/main_toolbar" + style="?attr/actionBarStyle" + android:layout_height="?attr/actionBarSize" + android:layout_width="match_parent"/> + + <include layout="@layout/abstract_fragment_container"/> + </FrameLayout> <LinearLayout - android:id="@+id/bottom_bar" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - style="@style/BasicButton" - android:orientation="horizontal"> - - <github.daneren2005.dsub.view.RecyclingImageView - android:id="@+id/album_art" - android:layout_width="50dip" - android:layout_height="50dip" - android:layout_gravity="left|center" - android:scaleType="fitStart"/> - - <LinearLayout - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_weight="1" - android:orientation="vertical" - android:paddingLeft="8dip"> - - <TextView - android:id="@+id/track_name" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:textColor="?android:textColorPrimary" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textSize="13sp" - android:text="@string/search.artists"/> - - <TextView - android:id="@+id/artist_name" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <FrameLayout + android:id="@+id/slide_up_swipe_target" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <android.support.v7.widget.Toolbar + android:id="@+id/now_playing_toolbar" + style="?attr/actionBarStyle" + android:layout_height="?attr/actionBarSize" + android:layout_width="match_parent" + android:visibility="gone"/> + + <LinearLayout + android:id="@+id/bottom_bar" + android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:textColor="?android:textColorSecondary" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textSize="12sp" - android:text="@string/search.albums"/> - </LinearLayout> - - <LinearLayout - android:layout_height="wrap_content" - android:layout_width="0dp" - android:layout_weight="1"> - - <ImageButton - style="@style/PlaybackControl.Small" - android:id="@+id/download_previous" - android:src="?attr/media_button_backward" - android:layout_width="0dp" - android:layout_weight="1"/> - - <ImageButton - style="@style/PlaybackControl.Small" - android:id="@+id/download_start" - android:src="?attr/media_button_start" - android:layout_width="0dp" - android:layout_weight="1"/> - - <ImageButton - style="@style/PlaybackControl.Small" - android:id="@+id/download_next" - android:src="?attr/media_button_forward" - android:layout_width="0dp" - android:layout_weight="1"/> - </LinearLayout> + style="@style/BasicButton" + android:orientation="horizontal"> + + <github.daneren2005.dsub.view.RecyclingImageView + android:id="@+id/album_art" + android:layout_width="?attr/actionBarSize" + android:layout_height="?attr/actionBarSize" + android:layout_gravity="left|center" + android:scaleType="fitStart"/> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_weight="1" + android:orientation="vertical" + android:paddingLeft="8dip"> + + <TextView + android:id="@+id/track_name" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textColor="?android:textColorPrimary" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textSize="@dimen/BottomBar.Text.Major" + android:text="@string/main.title" + android:ellipsize="marquee" + android:marqueeRepeatLimit="marquee_forever" + android:scrollHorizontally="true" + android:focusable="true" + android:focusableInTouchMode="true"> + + <requestFocus android:focusable="true" + android:focusableInTouchMode="true" + android:duplicateParentState="true" /> + </TextView> + + <TextView + android:id="@+id/artist_name" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textColor="?android:textColorSecondary" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textSize="@dimen/BottomBar.Text.Minor" + android:text="@string/main.artist"/> + </LinearLayout> + + + <LinearLayout + android:layout_height="fill_parent" + android:layout_width="0dp" + android:layout_weight="1"> + + <ImageButton + style="@style/PlaybackControl.Match" + android:id="@+id/download_previous" + android:src="?attr/media_button_backward" + android:layout_width="0dp" + android:layout_weight="1"/> + + <ImageButton + style="@style/PlaybackControl.Match" + android:id="@+id/download_start" + android:src="?attr/media_button_start" + android:layout_width="0dp" + android:layout_weight="1"/> + + <ImageButton + style="@style/PlaybackControl.Match" + android:id="@+id/download_next" + android:src="?attr/media_button_forward" + android:layout_width="0dp" + android:layout_weight="1"/> + </LinearLayout> + </LinearLayout> + </FrameLayout> + + <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/now_playing_fragment_container" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1"/> </LinearLayout> -</LinearLayout>
\ No newline at end of file +</com.sothree.slidinguppanel.SlidingUpPanelLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/abstract_fragment_container.xml b/app/src/main/res/layout/abstract_fragment_container.xml index 61e17d1d..f13356c4 100644 --- a/app/src/main/res/layout/abstract_fragment_container.xml +++ b/app/src/main/res/layout/abstract_fragment_container.xml @@ -2,5 +2,5 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" - android:layout_height="0px" - android:layout_weight="1"/>
\ No newline at end of file + android:layout_height="match_parent" + android:layout_marginTop="?attr/actionBarSize"/>
\ No newline at end of file diff --git a/app/src/main/res/layout/drawer_header.xml b/app/src/main/res/layout/drawer_header.xml new file mode 100644 index 00000000..00441b73 --- /dev/null +++ b/app/src/main/res/layout/drawer_header.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="178dp" + android:orientation="vertical" + android:weightSum="1"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="56dp" + android:orientation="vertical" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true"> + + <TextView + android:id="@+id/header_server_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="16dp" + android:textColor="?android:textColorPrimary" + android:textSize="14sp" + android:textStyle="bold"/> + + <TextView + android:id="@+id/header_user_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="16dp" + android:layout_marginTop="5dp" + android:textColor="?android:textColorSecondary" + android:textSize="14sp" + android:textStyle="normal"/> + </LinearLayout> + + <de.hdodenhof.circleimageview.CircleImageView + android:id="@+id/header_user_avatar" + android:layout_width="70dp" + android:layout_height="70dp" + android:layout_marginLeft="16dp" + android:layout_marginTop="38dp"/> +</RelativeLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/drawer_list_item.xml b/app/src/main/res/layout/drawer_list_item.xml index 5f17c9e9..607b3658 100644 --- a/app/src/main/res/layout/drawer_list_item.xml +++ b/app/src/main/res/layout/drawer_list_item.xml @@ -20,7 +20,8 @@ android:id="@+id/drawer_name" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="26sp" android:singleLine="true" - android:textColor="?android:textColorPrimary"/> + android:textColor="?android:textColorPrimary" + android:textAppearance="?android:attr/textAppearanceLarge" + style="DSub.TextViewStyle"/> </LinearLayout> diff --git a/app/src/main/res/values-large/dimens.xml b/app/src/main/res/values-large/dimens.xml index b08dda86..fe8f1a6c 100644 --- a/app/src/main/res/values-large/dimens.xml +++ b/app/src/main/res/values-large/dimens.xml @@ -4,4 +4,6 @@ <dimen name="Button.Small">54dip</dimen> <dimen name="AlbumArt.Small">96dip</dimen> <dimen name="AlbumArt.Header">210dip</dimen> + <dimen name="BottomBar.Text.Major">18sp</dimen> + <dimen name="BottomBar.Text.Minor">16sp</dimen> </resources>
\ No newline at end of file diff --git a/app/src/main/res/values-v16/themes.xml b/app/src/main/res/values-v16/themes.xml index 013ac0aa..a14b6a1b 100644 --- a/app/src/main/res/values-v16/themes.xml +++ b/app/src/main/res/values-v16/themes.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <style name="DSub.TextViewStyle" parent="android:Widget.TextView"> - <item name="android:fontFamily">sans-serif-light</item> + <item name="android:fontFamily">sans-serif</item> </style> <style name="DSub.TextViewStyle.Bold" parent="android:Widget.TextView"> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index be3e843d..9759e1c2 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -4,4 +4,6 @@ <dimen name="Button.Small">46dip</dimen> <dimen name="AlbumArt.Small">78dip</dimen> <dimen name="AlbumArt.Header">120dip</dimen> + <dimen name="BottomBar.Text.Major">13sp</dimen> + <dimen name="BottomBar.Text.Minor">12sp</dimen> </resources>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8544c6e3..e6e19b4c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -79,6 +79,8 @@ <string name="main.songs_genres">@string/main.albums_genres</string> <string name="main.back_confirm">Press back again to exit</string> <string name="main.scan_complete">Completed scan of Server</string> + <string name="main.artist">Artist</string> + <string name="main.title">Title</string> <string name="menu.search">Search</string> <string name="menu.shuffle">Shuffle</string> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 43271afd..061cfae7 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -23,6 +23,12 @@ <item name="android:layout_width">@dimen/Button.Small</item> <item name="android:layout_height">@dimen/Button.Small</item> </style> + + <style name="PlaybackControl.Match" parent="@style/PlaybackControl"> + <item name="android:padding">4dip</item> + <item name="android:layout_height">match_parent</item> + <item name="android:layout_width">wrap_content</item> + </style> <style name="MenuBarButton" parent="@style/BasicButton"> <item name="android:layout_width">0dip</item> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 78a2c34d..50d2d171 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -76,6 +76,23 @@ <style name="Theme.DSub.Holo" parent="Theme.DSub.Dark"> <item name="android:windowBackground">@drawable/background</item> </style> + + <style name="Theme.DSub.Light.No_Actionbar" parent="Theme.DSub.Light"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + <style name="Theme.DSub.Black.No_Actionbar" parent="Theme.DSub.Black"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + <style name="Theme.DSub.Dark.No_Actionbar" parent="Theme.DSub.Dark"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + <style name="Theme.DSub.Holo.No_Actionbar" parent="Theme.DSub.Holo"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> <style name="Widget.DSub.ActionBarStyle.Light" parent="Widget.AppCompat.Light.ActionBar.Solid"> <item name="background">@android:color/transparent</item> |