diff options
author | Scott Jackson <daneren2005@gmail.com> | 2015-06-18 17:26:49 -0700 |
---|---|---|
committer | Scott Jackson <daneren2005@gmail.com> | 2015-06-18 17:26:49 -0700 |
commit | 44faeb4cc59d69df0c633d04c76d3a94c4fac2aa (patch) | |
tree | 10ab1ccbd9e9e54539fe4095e3bcc481ee13cb56 /app/src/main | |
parent | 9f8e9b89bb2d564bcaf00309b38ed9c4d970aeb9 (diff) | |
parent | f632dc5f46943c6a258d5f1cd85c6c6d923c4a3a (diff) | |
download | dsub-44faeb4cc59d69df0c633d04c76d3a94c4fac2aa.tar.gz dsub-44faeb4cc59d69df0c633d04c76d3a94c4fac2aa.tar.bz2 dsub-44faeb4cc59d69df0c633d04c76d3a94c4fac2aa.zip |
Merge branch 'NavigationView' into SlideUpPanel2
Diffstat (limited to 'app/src/main')
30 files changed, 785 insertions, 1319 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SettingsActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SettingsActivity.java index d5ac60d3..595529b7 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SettingsActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SettingsActivity.java @@ -19,61 +19,25 @@ package github.daneren2005.dsub.activity; import android.annotation.TargetApi; -import android.accounts.Account; -import android.content.ContentResolver; -import android.content.Context; -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.preference.CheckBoxPreference; -import android.preference.EditTextPreference; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceCategory; -import android.preference.PreferenceScreen; -import android.support.v7.app.ActionBarActivity; -import android.text.InputType; -import android.util.Log; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; -import android.widget.FrameLayout; +import android.support.v7.widget.Toolbar; import github.daneren2005.dsub.R; import github.daneren2005.dsub.fragments.PreferenceCompatFragment; import github.daneren2005.dsub.fragments.SettingsFragment; -import github.daneren2005.dsub.service.DownloadService; -import github.daneren2005.dsub.service.MusicService; -import github.daneren2005.dsub.service.MusicServiceFactory; import github.daneren2005.dsub.util.Constants; -import github.daneren2005.dsub.util.LoadingTask; -import github.daneren2005.dsub.util.SyncUtil; -import github.daneren2005.dsub.view.ErrorDialog; -import github.daneren2005.dsub.util.FileUtil; -import github.daneren2005.dsub.util.Util; - -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.net.URL; -import java.text.DecimalFormat; -import java.util.LinkedHashMap; -import java.util.Map; public class SettingsActivity extends SubsonicActivity { - private static final String TAG = SettingsActivity.class.getSimpleName(); + private static final String TAG = SettingsActivity.class.getSimpleName(); private PreferenceCompatFragment fragment; @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.download_activity); + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + lastSelectedPosition = R.id.drawer_settings; + setContentView(R.layout.settings_activity); if (savedInstanceState == null) { fragment = new SettingsFragment(); @@ -87,5 +51,8 @@ public class SettingsActivity extends SubsonicActivity { currentFragment.setPrimaryFragment(true); getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit(); } - } + + Toolbar mainToolbar = (Toolbar) findViewById(R.id.main_toolbar); + setSupportActionBar(mainToolbar); + } } 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 cb09728c..fe785ef8 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java @@ -25,11 +25,11 @@ import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.content.res.TypedArray; import android.media.AudioManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.support.design.widget.NavigationView; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; @@ -52,14 +52,12 @@ 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; import java.io.File; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import github.daneren2005.dsub.R; @@ -71,7 +69,6 @@ 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; import github.daneren2005.dsub.util.UserUtil; @@ -80,10 +77,10 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte private static ImageLoader IMAGE_LOADER; protected static String theme; protected static boolean fullScreen; - private String[] drawerItemsDescriptions; - private String[] drawerItems; + private static final int MENU_GROUP_SERVER = 10; + private static final int MENU_ITEM_SERVER_BASE = 100; + private boolean drawerIdle = true; - private boolean[] enabledItems = {true, true, true, true, true}; private boolean destroyed = false; private boolean finished = false; protected List<SubsonicFragment> backStack = new ArrayList<SubsonicFragment>(); @@ -97,15 +94,15 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte ViewGroup rootView; DrawerLayout drawer; ActionBarDrawerToggle drawerToggle; - DrawerAdapter drawerAdapter; - ListView drawerList; + NavigationView drawerList; View drawerHeader; ImageView drawerUserAvatar; TextView drawerServerName; TextView drawerUserName; - TextView lastSelectedView = null; int lastSelectedPosition = 0; + boolean showingTabs = true; boolean drawerOpen = false; + SharedPreferences.OnSharedPreferenceChangeListener preferencesListener; @Override protected void onCreate(Bundle bundle) { @@ -128,6 +125,33 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte if(getIntent().hasExtra(Constants.FRAGMENT_POSITION)) { lastSelectedPosition = getIntent().getIntExtra(Constants.FRAGMENT_POSITION, 0); } + + if(preferencesListener == null) { + preferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + // When changing drawer settings change visibility + switch(key) { + case Constants.PREFERENCES_KEY_PODCASTS_ENABLED: + setDrawerItemVisible(R.id.drawer_podcasts, false); + break; + case Constants.PREFERENCES_KEY_BOOKMARKS_ENABLED: + setDrawerItemVisible(R.id.drawer_bookmarks, false); + break; + case Constants.PREFERENCES_KEY_SHARED_ENABLED: + setDrawerItemVisible(R.id.drawer_shares, false); + break; + case Constants.PREFERENCES_KEY_CHAT_ENABLED: + setDrawerItemVisible(R.id.drawer_chat, false); + break; + case Constants.PREFERENCES_KEY_ADMIN_ENABLED: + setDrawerItemVisible(R.id.drawer_admin, false); + break; + } + } + }; + Util.getPreferences(this).registerOnSharedPreferenceChangeListener(preferencesListener); + } } @Override @@ -174,7 +198,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte overridePendingTransition(R.anim.fade_in, R.anim.fade_out); } - populateDrawer(); + populateTabs(); UpdateView.addActiveActivity(); } @@ -189,6 +213,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte protected void onDestroy() { super.onDestroy(); destroyed = true; + Util.getPreferences(this).unregisterOnSharedPreferenceChangeListener(preferencesListener); } @Override @@ -198,19 +223,6 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } @Override - public void startActivity(Intent intent) { - if(intent.getComponent() != null) { - String name = intent.getComponent().getClassName(); - if(name != null && name.indexOf("DownloadActivity") != -1) { - intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition); - } else if(name != null && name.indexOf("SettingsActivity") != -1) { - intent.putExtra(Constants.FRAGMENT_POSITION, drawerItems.length - 1); - } - } - super.startActivity(intent); - } - - @Override public void setContentView(int viewId) { if(isTv()) { super.setContentView(R.layout.static_drawer_activity); @@ -224,34 +236,88 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte layoutInflater.inflate(viewId, rootView); } - drawerList = (ListView) findViewById(R.id.left_drawer); - drawerList.setOnItemClickListener(new ListView.OnItemClickListener() { + drawerList = (NavigationView) findViewById(R.id.left_drawer); + drawerList.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override - public void onItemClick(AdapterView<?> parent, final View view, final int position, long id) { - final int actualPosition = drawerAdapter.getActualPosition(position - 1); - if("Settings".equals(drawerItemsDescriptions[actualPosition])) { - startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class)); - drawer.closeDrawers(); - } else if("Admin".equals(drawerItemsDescriptions[actualPosition]) && UserUtil.isCurrentAdmin()) { - UserUtil.confirmCredentials(SubsonicActivity.this, new Runnable() { - @Override - public void run() { - drawerItemSelected(actualPosition, view); - } - }); + public boolean onNavigationItemSelected(MenuItem menuItem) { + if(showingTabs) { + // Settings are on a different selectable track + if (menuItem.getItemId() != R.id.drawer_settings) { + menuItem.setChecked(true); + lastSelectedPosition = menuItem.getItemId(); + } + + switch (menuItem.getItemId()) { + case R.id.drawer_home: + drawerItemSelected("Home"); + return true; + case R.id.drawer_library: + drawerItemSelected("Artist"); + return true; + case R.id.drawer_playlists: + drawerItemSelected("Playlist"); + return true; + case R.id.drawer_podcasts: + drawerItemSelected("Podcast"); + return true; + case R.id.drawer_bookmarks: + drawerItemSelected("Bookmark"); + return true; + case R.id.drawer_shares: + drawerItemSelected("Share"); + return true; + case R.id.drawer_chat: + drawerItemSelected("Chat"); + return true; + case R.id.drawer_admin: + if (UserUtil.isCurrentAdmin()) { + UserUtil.confirmCredentials(SubsonicActivity.this, new Runnable() { + @Override + public void run() { + drawerItemSelected("Admin"); + } + }); + } else { + drawerItemSelected("Admin"); + } + return true; + case R.id.drawer_downloading: + drawerItemSelected("Download"); + return true; + case R.id.drawer_settings: + startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class)); + drawer.closeDrawers(); + return true; + } } else { - drawerItemSelected(actualPosition, view); + int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE; + SubsonicActivity.this.setActiveServer(activeServer); + populateTabs(); + return true; + } + + return false; + } + }); + populateTabs(); + + drawerHeader = drawerList.inflateHeaderView(R.layout.drawer_header); + drawerHeader.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(showingTabs) { + populateServers(); + } else { + populateTabs(); } } }); - 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); @@ -265,23 +331,19 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte drawerOpen = false; supportInvalidateOptionsMenu(); + if(!showingTabs) { + populateTabs(); + } } @Override public void onDrawerOpened(View view) { DownloadService downloadService = getDownloadService(); - if (downloadService == null || downloadService.getBackgroundDownloads().isEmpty()) { - drawerAdapter.setDownloadVisible(false); - } else { - drawerAdapter.setDownloadVisible(true); - } - - if (lastSelectedView == null && drawerList.getCount() > lastSelectedPosition) { - lastSelectedView = (TextView) drawerList.getChildAt(lastSelectedPosition + 1).findViewById(R.id.drawer_name); - if (lastSelectedView != null) { - lastSelectedView.setTextAppearance(SubsonicActivity.this, R.style.DSub_TextViewStyle_Bold); - } + boolean downloadingVisible = downloadService != null && !downloadService.getBackgroundDownloads().isEmpty(); + if(lastSelectedPosition == R.id.drawer_downloading) { + downloadingVisible = true; } + setDrawerItemVisible(R.id.drawer_downloading, downloadingVisible); getSupportActionBar().setTitle(R.string.common_appname); getSupportActionBar().setDisplayShowCustomEnabled(false); @@ -382,6 +444,12 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } lastSelectedPosition = savedInstanceState.getInt(Constants.FRAGMENT_POSITION); + if(lastSelectedPosition != 0) { + MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition); + if(item != null) { + item.setChecked(true); + } + } recreateSpinner(); } @@ -462,7 +530,10 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } - private void populateDrawer() { + private void populateTabs() { + drawerList.getMenu().clear(); + drawerList.inflateMenu(R.menu.drawer_navigation); + SharedPreferences prefs = Util.getPreferences(this); boolean podcastsEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_PODCASTS_ENABLED, true); boolean bookmarksEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_BOOKMARKS_ENABLED, true) && !Util.isOffline(this) && ServerInfo.canBookmark(this); @@ -470,88 +541,56 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte 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); - - List<String> drawerItemsList = new ArrayList<String>(Arrays.asList(drawerItems)); - List<Integer> drawerItemsIconsList = new ArrayList<Integer>(); - List<Boolean> drawerItemsVisibleList = new ArrayList<Boolean>(); - - int[] arrayAttr = {R.attr.drawerItemsIcons}; - TypedArray arrayType = obtainStyledAttributes(arrayAttr); - int arrayId = arrayType.getResourceId(0, 0); - TypedArray iconType = getResources().obtainTypedArray(arrayId); - for(int i = 0; i < drawerItemsList.size(); i++) { - drawerItemsIconsList.add(iconType.getResourceId(i, 0)); - drawerItemsVisibleList.add(true); - } - iconType.recycle(); - arrayType.recycle(); - - // Hide listings user doesn't want to see - if(!podcastsEnabled) { - drawerItemsVisibleList.set(3, false); - } - if(!bookmarksEnabled) { - drawerItemsVisibleList.set(4, false); - } - if(!sharedEnabled) { - drawerItemsVisibleList.set(5, false); - } - if(!chatEnabled) { - drawerItemsVisibleList.set(6, false); - } - if(!adminEnabled) { - drawerItemsVisibleList.set(7, false); - } - 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; - enabledItems[2] = sharedEnabled; - enabledItems[3] = chatEnabled; - enabledItems[4] = adminEnabled; - - String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE); - if(fragmentType != null && lastSelectedPosition == 0) { - for(int i = 0; i < drawerItemsDescriptions.length; i++) { - if(fragmentType.equals(drawerItemsDescriptions[i])) { - lastSelectedPosition = drawerAdapter.getAdapterPosition(i); - break; - } - } - } + if(!podcastsEnabled) { + setDrawerItemVisible(R.id.drawer_podcasts, false); + } + if(!bookmarksEnabled) { + setDrawerItemVisible(R.id.drawer_bookmarks, false); + } + if(!sharedEnabled) { + setDrawerItemVisible(R.id.drawer_shares, false); + } + if(!chatEnabled) { + setDrawerItemVisible(R.id.drawer_chat, false); + } + if(!adminEnabled) { + setDrawerItemVisible(R.id.drawer_admin, false); + } - if(drawerList.getChildAt(lastSelectedPosition + 1) == null) { - lastSelectedView = null; - drawerAdapter.setSelectedPosition(lastSelectedPosition); - } else { - lastSelectedView = (TextView) drawerList.getChildAt(lastSelectedPosition + 1).findViewById(R.id.drawer_name); - if(lastSelectedView != null) { - lastSelectedView.setTextAppearance(SubsonicActivity.this, R.style.DSub_TextViewStyle_Bold); - } + if(lastSelectedPosition != 0) { + MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition); + if(item != null) { + item.setChecked(true); } } + showingTabs = true; } + private void populateServers() { + drawerList.getMenu().clear(); - protected void drawerItemSelected(int position, View view) { - startFragmentActivity(drawerItemsDescriptions[position]); - - if(lastSelectedView != view) { - if(lastSelectedView != null) { - lastSelectedView.setTextAppearance(this, R.style.DSub_TextViewStyle); + int serverCount = Util.getServerCount(this); + int activeServer = Util.getActiveServer(this); + for(int i = 1; i <= serverCount; i++) { + MenuItem item = drawerList.getMenu().add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_BASE + i, MENU_ITEM_SERVER_BASE + i, Util.getServerName(this, i)); + if(activeServer == i) { + item.setChecked(true); } + } + drawerList.getMenu().setGroupCheckable(MENU_GROUP_SERVER, true, true); - lastSelectedView = (TextView) view.findViewById(R.id.drawer_name); - lastSelectedView.setTextAppearance(this, R.style.DSub_TextViewStyle_Bold); - lastSelectedPosition = position; + showingTabs = false; + } + private void setDrawerItemVisible(int id, boolean visible) { + MenuItem item = drawerList.getMenu().findItem(id); + if(item != null) { + item.setVisible(visible); } } + protected void drawerItemSelected(String fragmentType) { + startFragmentActivity(fragmentType); + } + public void startFragmentActivity(String fragmentType) { Intent intent = new Intent(); intent.setClass(SubsonicActivity.this, SubsonicFragmentActivity.class); @@ -559,6 +598,9 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte if(!"".equals(fragmentType)) { intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType); } + if(lastSelectedPosition != 0) { + intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition); + } startActivity(intent); finish(); } @@ -719,7 +761,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte } currentFragment.invalidate(); - populateDrawer(); + populateTabs(); } supportInvalidateOptionsMenu(); 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 c5391a88..db7559b3 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java @@ -112,9 +112,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity { getImageLoader().clearCache(); } else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) { getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Download"); - if(drawerAdapter != null) { - drawerAdapter.setDownloadVisible(true); - } + lastSelectedPosition = R.id.drawer_downloading; } setContentView(R.layout.abstract_fragment_activity); @@ -127,6 +125,37 @@ public class SubsonicFragmentActivity extends SubsonicActivity { if(fragmentType != null) { getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType); firstRun = true; + + switch(fragmentType) { + case "Home": + lastSelectedPosition = R.id.drawer_home; + break; + case "Artist": + lastSelectedPosition = R.id.drawer_library; + break; + case "Playlist": + lastSelectedPosition = R.id.drawer_playlists; + break; + case "Podcast": + lastSelectedPosition = R.id.drawer_podcasts; + break; + case "Bookmark": + lastSelectedPosition = R.id.drawer_bookmarks; + break; + case "Share": + lastSelectedPosition = R.id.drawer_shares; + break; + case "Chat": + lastSelectedPosition = R.id.drawer_chat; + break; + } + } else { + lastSelectedPosition = R.id.drawer_home; + } + + MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition); + if(item != null) { + item.setChecked(true); } } currentFragment = getNewFragment(fragmentType); @@ -198,7 +227,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity { drawerToggle.setDrawerIndicatorEnabled(false); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeAsUpIndicator(coverArtView.getDrawable()); } @Override @@ -394,9 +422,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity { replaceFragment(fragment, fragment.getSupportTag()); getIntent().removeExtra(Constants.INTENT_EXTRA_VIEW_ALBUM); - if("Artist".equals(getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE))) { - lastSelectedPosition = 1; - } } createAccount(); @@ -480,8 +505,8 @@ public class SubsonicFragmentActivity extends SubsonicActivity { } @Override - protected void drawerItemSelected(int position, View view) { - super.drawerItemSelected(position, view); + protected void drawerItemSelected(String fragmentType) { + super.drawerItemSelected(fragmentType); if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); @@ -577,20 +602,15 @@ public class SubsonicFragmentActivity extends SubsonicActivity { artistView.setText(R.string.main_artist); } - if(coverArtView.getHeight() > 0 ) { - 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()); - } - }); - } + if(coverArtView != null) { + int height = coverArtView.getHeight(); + if(height <= 0) { + int[] attrs = new int[] {R.attr.actionBarSize}; + TypedArray typedArray = this.obtainStyledAttributes(attrs); + height = typedArray.getDimensionPixelSize(0, 0); + typedArray.recycle(); } + getImageLoader().loadImage(coverArtView, song, false, height, false); } int[] attrs = new int[] {(state == PlayerState.STARTED) ? R.attr.media_button_pause : R.attr.media_button_start}; diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/DrawerAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/DrawerAdapter.java deleted file mode 100644 index b0a4a33d..00000000 --- a/app/src/main/java/github/daneren2005/dsub/adapter/DrawerAdapter.java +++ /dev/null @@ -1,126 +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.adapter; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.TextView; - -import java.util.List; - -import github.daneren2005.dsub.R; - -/** - * Created by Scott on 11/8/13. - */ -public class DrawerAdapter extends ArrayAdapter<String> { - private static String TAG = DrawerAdapter.class.getSimpleName(); - private Context context; - private List<String> items; - private List<Integer> icons; - private List<Boolean> visible; - private int selectedPosition = -1; - - public DrawerAdapter(Context context, List<String> items, List<Integer> icons, List<Boolean> visible) { - super(context, R.layout.drawer_list_item, items); - - this.context = context; - this.items = items; - this.icons = icons; - this.visible = visible; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - position = getActualPosition(position); - String item = items.get(position); - Integer icon = icons.get(position); - - if(convertView == null) { - convertView = LayoutInflater.from(context).inflate(R.layout.drawer_list_item, null); - } - - TextView textView = (TextView) convertView.findViewById(R.id.drawer_name); - textView.setText(item); - - if(selectedPosition == position) { - textView.setTextAppearance(context, R.style.DSub_TextViewStyle_Bold); - selectedPosition = -1; - } - - ImageView iconView = (ImageView) convertView.findViewById(R.id.drawer_icon); - iconView.setImageResource(icon); - - return convertView; - } - - @Override - public int getCount() { - int count = 0; - for(int i = 0; i < visible.size(); i++) { - if(visible.get(i)) { - count++; - } - } - - return count; - } - - public int getActualPosition(int position) { - for(int i = 0; i <= position; i++) { - if(!visible.get(i)) { - position++; - } - } - - return position; - } - public int getAdapterPosition(int position) { - if(!visible.get(position)) { - visible.set(position, true); - notifyDataSetChanged(); - } - - for(int i = position; i >= 0; i--) { - if(!visible.get(i)) { - position--; - } - } - - return position; - } - - public void setItemVisible(int position, boolean visible) { - if(this.visible.get(position) != visible) { - this.visible.set(position, visible); - notifyDataSetInvalidated(); - } - } - public void setDownloadVisible(boolean visible) { - setItemVisible(items.size() - 2, visible); - } - - public void setSelectedPosition(int position) { - selectedPosition = position; - } -} diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java new file mode 100644 index 00000000..e451bc19 --- /dev/null +++ b/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java @@ -0,0 +1,113 @@ +/* + 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 2015 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; + +import java.util.List; + +import github.daneren2005.dsub.R; +import github.daneren2005.dsub.domain.ServerInfo; +import github.daneren2005.dsub.util.Util; +import github.daneren2005.dsub.view.AlbumListCountView; +import github.daneren2005.dsub.view.BasicHeaderView; +import github.daneren2005.dsub.view.BasicListView; +import github.daneren2005.dsub.view.UpdateView; + +public class MainAdapter extends SectionAdapter<Integer> { + public static final int VIEW_TYPE_ALBUM_LIST = 1; + public static final int VIEW_TYPE_ALBUM_COUNT_LIST = 2; + + public MainAdapter(Context context, List<String> headers, List<List<Integer>> sections, OnItemClickedListener onItemClickedListener) { + super(context, headers, sections); + this.onItemClickedListener = onItemClickedListener; + } + + @Override + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + UpdateView updateView; + if(viewType == VIEW_TYPE_ALBUM_LIST) { + updateView = new BasicListView(context); + } else { + updateView = new AlbumListCountView(context); + } + + return new UpdateView.UpdateViewHolder(updateView); + } + + @Override + public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Integer item, int viewType) { + UpdateView updateView = holder.getUpdateView(); + + if(viewType == VIEW_TYPE_ALBUM_LIST) { + updateView.setObject(context.getResources().getString(item)); + } else { + // Hacky method to make sure updateBackground is called in background thread + updateView.setObject(item, null); + } + } + + @Override + public int getItemViewType(Integer item) { + if(item == R.string.main_albums_newest) { + return VIEW_TYPE_ALBUM_COUNT_LIST; + } else { + return VIEW_TYPE_ALBUM_LIST; + } + } + + @Override + public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) { + return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.album_list_header)); + } + @Override + public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header) { + UpdateView view = holder.getUpdateView(); + CheckBox checkBox = (CheckBox) view.findViewById(R.id.item_checkbox); + + String display; + if ("albums".equals(header)) { + display = context.getResources().getString(R.string.main_albums_title); + + if(!Util.isOffline(context) && ServerInfo.canAlbumListPerFolder(context)) { + checkBox.setVisibility(View.VISIBLE); + checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Util.setAlbumListsPerFolder(context, isChecked); + } + }); + checkBox.setChecked(Util.getAlbumListsPerFolder(context)); + } else { + checkBox.setVisibility(View.GONE); + } + } else if("videos".equals(header)) { + display = context.getResources().getString(R.string.main_videos); + checkBox.setVisibility(View.GONE); + } else { + display = header; + checkBox.setVisibility(View.GONE); + } + + if(view != null) { + view.setObject(display); + } + } +} diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java deleted file mode 100644 index a2db4cf0..00000000 --- a/app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java +++ /dev/null @@ -1,290 +0,0 @@ -/*** - Copyright (c) 2008-2009 CommonsWare, LLC - Portions (c) 2009 Google, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -package github.daneren2005.dsub.adapter; - -import android.database.DataSetObserver; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ListAdapter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Arrays; - -/** - * Adapter that merges multiple child adapters and views - * into a single contiguous whole. - * <p/> - * Adapters used as pieces within MergeAdapter must - * have view type IDs monotonically increasing from 0. Ideally, - * adapters also have distinct ranges for their row ids, as - * returned by getItemId(). - */ -public class MergeAdapter extends BaseAdapter { - - private final CascadeDataSetObserver observer = new CascadeDataSetObserver(); - private final ArrayList<ListAdapter> pieces = new ArrayList<ListAdapter>(); - - /** - * Stock constructor, simply chaining to the superclass. - */ - public MergeAdapter() { - super(); - } - - /** - * Adds a new adapter to the roster of things to appear - * in the aggregate list. - * - * @param adapter Source for row views for this section - */ - public void addAdapter(ListAdapter adapter) { - pieces.add(adapter); - adapter.registerDataSetObserver(observer); - } - - public void removeAdapter(ListAdapter adapter) { - adapter.unregisterDataSetObserver(observer); - pieces.remove(adapter); - } - - /** - * Adds a new View to the roster of things to appear - * in the aggregate list. - * - * @param view Single view to add - */ - public ListAdapter addView(View view) { - return addView(view, false); - } - - /** - * Adds a new View to the roster of things to appear - * in the aggregate list. - * - * @param view Single view to add - * @param enabled false if views are disabled, true if enabled - */ - public ListAdapter addView(View view, boolean enabled) { - return addViews(Arrays.asList(view), enabled); - } - - /** - * Adds a list of views to the roster of things to appear - * in the aggregate list. - * - * @param views List of views to add - */ - public ListAdapter addViews(List<View> views) { - return addViews(views, false); - } - - /** - * Adds a list of views to the roster of things to appear - * in the aggregate list. - * - * @param views List of views to add - * @param enabled false if views are disabled, true if enabled - */ - public ListAdapter addViews(List<View> views, boolean enabled) { - ListAdapter adapter = enabled ? new EnabledSackAdapter(views) : new SackOfViewsAdapter(views); - addAdapter(adapter); - return adapter; - } - - /** - * Get the data item associated with the specified - * position in the data set. - * - * @param position Position of the item whose data we want - */ - @Override - public Object getItem(int position) { - for (ListAdapter piece : pieces) { - int size = piece.getCount(); - - if (position < size) { - return (piece.getItem(position)); - } - - position -= size; - } - - return (null); - } - - /** - * How many items are in the data set represented by this - * Adapter. - */ - @Override - public int getCount() { - int total = 0; - - for (ListAdapter piece : pieces) { - total += piece.getCount(); - } - - return (total); - } - - /** - * Returns the number of types of Views that will be - * created by getView(). - */ - @Override - public int getViewTypeCount() { - int total = 0; - - for (ListAdapter piece : pieces) { - total += piece.getViewTypeCount(); - } - - return (Math.max(total, 1)); // needed for setListAdapter() before content add' - } - - /** - * Get the type of View that will be created by getView() - * for the specified item. - * - * @param position Position of the item whose data we want - */ - @Override - public int getItemViewType(int position) { - int typeOffset = 0; - int result = -1; - - for (ListAdapter piece : pieces) { - int size = piece.getCount(); - - if (position < size) { - result = typeOffset + piece.getItemViewType(position); - break; - } - - position -= size; - typeOffset += piece.getViewTypeCount(); - } - - return (result); - } - - /** - * Are all items in this ListAdapter enabled? If yes it - * means all items are selectable and clickable. - */ - @Override - public boolean areAllItemsEnabled() { - return (false); - } - - /** - * Returns true if the item at the specified position is - * not a separator. - * - * @param position Position of the item whose data we want - */ - @Override - public boolean isEnabled(int position) { - for (ListAdapter piece : pieces) { - int size = piece.getCount(); - - if (position < size) { - return (piece.isEnabled(position)); - } - - position -= size; - } - - return (false); - } - - /** - * Get a View that displays the data at the specified - * position in the data set. - * - * @param position Position of the item whose data we want - * @param convertView View to recycle, if not null - * @param parent ViewGroup containing the returned View - */ - @Override - public View getView(int position, View convertView, - ViewGroup parent) { - for (ListAdapter piece : pieces) { - int size = piece.getCount(); - - if (position < size) { - - return (piece.getView(position, convertView, parent)); - } - - position -= size; - } - - return (null); - } - - /** - * Get the row id associated with the specified position - * in the list. - * - * @param position Position of the item whose data we want - */ - @Override - public long getItemId(int position) { - for (ListAdapter piece : pieces) { - int size = piece.getCount(); - - if (position < size) { - return (piece.getItemId(position)); - } - - position -= size; - } - - return (-1); - } - - private static class EnabledSackAdapter extends SackOfViewsAdapter { - public EnabledSackAdapter(List<View> views) { - super(views); - } - - @Override - public boolean areAllItemsEnabled() { - return (true); - } - - @Override - public boolean isEnabled(int position) { - return (true); - } - } - - private class CascadeDataSetObserver extends DataSetObserver { - @Override - public void onChanged() { - notifyDataSetChanged(); - } - - @Override - public void onInvalidated() { - notifyDataSetInvalidated(); - } - } -} - diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java deleted file mode 100644 index e4744cc5..00000000 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java +++ /dev/null @@ -1,181 +0,0 @@ -/*** - Copyright (c) 2008-2009 CommonsWare, LLC - Portions (c) 2009 Google, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ -package github.daneren2005.dsub.adapter; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ListView; - -import java.util.ArrayList; -import java.util.List; - -/** - * Adapter that simply returns row views from a list. - * <p/> - * If you supply a size, you must implement newView(), to - * create a required view. The adapter will then cache these - * views. - * <p/> - * If you supply a list of views in the constructor, that - * list will be used directly. If any elements in the list - * are null, then newView() will be called just for those - * slots. - * <p/> - * Subclasses may also wish to override areAllItemsEnabled() - * (default: false) and isEnabled() (default: false), if some - * of their rows should be selectable. - * <p/> - * It is assumed each view is unique, and therefore will not - * get recycled. - * <p/> - * Note that this adapter is not designed for long lists. It - * is more for screens that should behave like a list. This - * is particularly useful if you combine this with other - * adapters (e.g., SectionedAdapter) that might have an - * arbitrary number of rows, so it all appears seamless. - */ -public class SackOfViewsAdapter extends BaseAdapter { - private List<View> views = null; - - /** - * Constructor creating an empty list of views, but with - * a specified count. Subclasses must override newView(). - */ - public SackOfViewsAdapter(int count) { - super(); - - views = new ArrayList<View>(count); - - for (int i = 0; i < count; i++) { - views.add(null); - } - } - - /** - * Constructor wrapping a supplied list of views. - * Subclasses must override newView() if any of the elements - * in the list are null. - */ - public SackOfViewsAdapter(List<View> views) { - for (View view : views) { - view.setLayoutParams(new ListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - } - this.views = views; - } - - /** - * Get the data item associated with the specified - * position in the data set. - * - * @param position Position of the item whose data we want - */ - @Override - public Object getItem(int position) { - return (views.get(position)); - } - - /** - * How many items are in the data set represented by this - * Adapter. - */ - @Override - public int getCount() { - return (views.size()); - } - - /** - * Returns the number of types of Views that will be - * created by getView(). - */ - @Override - public int getViewTypeCount() { - return (getCount()); - } - - /** - * Get the type of View that will be created by getView() - * for the specified item. - * - * @param position Position of the item whose data we want - */ - @Override - public int getItemViewType(int position) { - return (position); - } - - /** - * Are all items in this ListAdapter enabled? If yes it - * means all items are selectable and clickable. - */ - @Override - public boolean areAllItemsEnabled() { - return (false); - } - - /** - * Returns true if the item at the specified position is - * not a separator. - * - * @param position Position of the item whose data we want - */ - @Override - public boolean isEnabled(int position) { - return (false); - } - - /** - * Get a View that displays the data at the specified - * position in the data set. - * - * @param position Position of the item whose data we want - * @param convertView View to recycle, if not null - * @param parent ViewGroup containing the returned View - */ - @Override - public View getView(int position, View convertView, - ViewGroup parent) { - View result = views.get(position); - - if (result == null) { - result = newView(position, parent); - views.set(position, result); - } - - return (result); - } - - /** - * Get the row id associated with the specified position - * in the list. - * - * @param position Position of the item whose data we want - */ - @Override - public long getItemId(int position) { - return (position); - } - - /** - * Create a new View to go into the list at the specified - * position. - * - * @param position Position of the item whose data we want - * @param parent ViewGroup containing the returned View - */ - protected View newView(int position, ViewGroup parent) { - throw new RuntimeException("You must override newView()!"); - } -} diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java index 599870d7..f57012b5 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java @@ -77,6 +77,7 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH @Override public void onClick(View v) { T item = holder.getItem(); + updateView.onClick(); if (updateView.isCheckable()) { if (selected.contains(item)) { selected.remove(item); @@ -136,15 +137,17 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH } int subPosition = 0; + int subHeader = 0; for(List<T> section: sections) { - if(position == subPosition) { - int index = sections.indexOf(section); - onBindHeaderHolder(holder, headers.get(index)); + boolean validHeader = headers.get(subHeader) != null; + if(position == subPosition && validHeader) { + onBindHeaderHolder(holder, headers.get(subHeader)); return; } - if(position <= (subPosition + section.size())) { - T item = section.get(position - subPosition - 1); + int headerOffset = validHeader ? 1 : 0; + if(position < (subPosition + section.size() + headerOffset)) { + T item = section.get(position - subPosition - headerOffset); onBindViewHolder(holder, item, getItemViewType(item)); if(updateView.isCheckable()) { @@ -154,7 +157,11 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH return; } - subPosition += section.size() + 1; + subPosition += section.size(); + if(validHeader) { + subPosition += 1; + } + subHeader++; } } @@ -164,7 +171,12 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH return sections.get(0).size(); } - int count = headers.size(); + int count = 0; + for(String header: headers) { + if(header != null) { + count++; + } + } for(List<T> section: sections) { count += section.size(); } @@ -179,16 +191,23 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH } int subPosition = 0; + int subHeader = 0; for(List<T> section: sections) { - if(position == subPosition) { + boolean validHeader = headers.get(subHeader) != null; + if(position == subPosition && validHeader) { return VIEW_TYPE_HEADER; } - if(position <= (subPosition + section.size())) { - return getItemViewType(section.get(position - subPosition - 1)); + int headerOffset = validHeader ? 1 : 0; + if(position < (subPosition + section.size() + headerOffset)) { + return getItemViewType(section.get(position - subPosition - headerOffset)); } - subPosition += section.size() + 1; + subPosition += section.size(); + if(validHeader) { + subPosition += 1; + } + subHeader++; } return -1; 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 71c135aa..90a91383 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java @@ -9,28 +9,23 @@ 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.adapter.MainAdapter; +import github.daneren2005.dsub.adapter.SectionAdapter; 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.ProgressListener; 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; @@ -41,37 +36,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class MainFragment extends SubsonicFragment { +public class MainFragment extends SelectRecyclerFragment<Integer> { 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(); + public MainFragment() { + super(); + pullToRefresh = false; + serialize = false; } @Override @@ -116,140 +87,56 @@ public class MainFragment extends SubsonicFragment { } @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; - context.setActiveServer(activeServer); - return true; + public int getOptionsMenu() { + return 0; } @Override - protected void refresh(boolean refresh) { - createLayout(); - } + public SectionAdapter getAdapter(List objs) { + List<List<Integer>> sections = new ArrayList<>(); + List<String> headers = new ArrayList<>(); - 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); - } + List<Integer> offline = Arrays.asList(R.string.main_offline); + sections.add(offline); + headers.add(null); - 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); + List<Integer> albums = new ArrayList<>(); + albums.add(R.string.main_albums_newest); + albums.add(R.string.main_albums_random); if(ServerInfo.checkServerVersion(context, "1.8")) { - adapter.addView(albumsAlphabeticalButton, true); + albums.add(R.string.main_albums_alphabetical); } if(!Util.isTagBrowsing(context)) { - adapter.addView(albumsHighestButton, true); + albums.add(R.string.main_albums_highest); } - adapter.addViews(Arrays.asList(albumsStarredButton, albumsGenresButton, albumsYearButton, albumsRecentButton, albumsFrequentButton), true); + albums.add(R.string.main_albums_starred); + albums.add(R.string.main_albums_genres); + albums.add(R.string.main_albums_year); + albums.add(R.string.main_albums_recent); + albums.add(R.string.main_albums_highest); + + sections.add(albums); + headers.add("albums"); + if(ServerInfo.checkServerVersion(context, "1.8") && !Util.isTagBrowsing(context)) { - adapter.addView(videoTitle, false); - adapter.addView(videosButton, true); + List<Integer> videos = Arrays.asList(R.string.main_videos); + sections.add(videos); + headers.add("videos"); } } - 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); + return new MainAdapter(context, headers, sections, this); + } - if(!Util.isOffline(context)) { - getMostRecentCount(); - } + @Override + public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception { + return Arrays.asList(0); + } + + @Override + public int getTitleResource() { + return R.string.common_appname; } private void toggleOffline() { @@ -287,8 +174,8 @@ public class MainFragment extends SubsonicFragment { 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); + // TODO: Clear immediately so doesn't still show when pressing back + // setMostRecentCount(0); } SubsonicFragment fragment = new SelectDirectoryFragment(); @@ -487,81 +374,31 @@ public class MainFragment extends SubsonicFragment { }.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); + + @Override + public void onItemClicked(Integer item) { + if(item == R.string.main_offline) { + toggleOffline(); + } else if (item == R.string.main_albums_newest) { + showAlbumList("newest"); + } else if (item == R.string.main_albums_random) { + showAlbumList("random"); + } else if (item == R.string.main_albums_highest) { + showAlbumList("highest"); + } else if (item == R.string.main_albums_recent) { + showAlbumList("recent"); + } else if (item == R.string.main_albums_frequent) { + showAlbumList("frequent"); + } else if (item == R.string.main_albums_starred) { + showAlbumList("starred"); + } else if(item == R.string.main_albums_genres) { + showAlbumList("genres"); + } else if(item == R.string.main_albums_year) { + showAlbumList("years"); + } else if(item == R.string.main_albums_alphabetical) { + showAlbumList("alphabeticalByName"); + } else if(item == R.string.main_videos) { + showVideos(); } } } 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 c3d86d4b..a770fbb1 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java +++ b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java @@ -277,6 +277,11 @@ public class ImageLoader { } public SilentBackgroundTask<Void> loadAvatar(Context context, ImageView view, String username) { + if(username == null) { + view.setImageResource(R.drawable.ic_social_person); + return null; + } + Bitmap bitmap = cache.get(username); if (bitmap != null && !bitmap.isRecycled()) { Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap); diff --git a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java index d078d77e..c7b6986e 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java @@ -260,10 +260,9 @@ public final class Notifications { cancelPI); Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class); - notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true); notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - builder.setContentIntent(PendingIntent.getActivity(context, 1, notificationIntent, 0)); + builder.setContentIntent(PendingIntent.getActivity(context, 2, notificationIntent, 0)); final Notification notification = builder.build(); downloadShowing = true; 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 969e178e..0160ddd0 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.SettingsActivity; import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; @@ -257,7 +258,7 @@ public final class Util { } public static void applyTheme(Context context, String theme) { - if(context instanceof SubsonicFragmentActivity) { + if(context instanceof SubsonicFragmentActivity || context instanceof SettingsActivity) { if ("dark".equals(theme)) { context.setTheme(R.style.Theme_DSub_Dark_No_Actionbar); } else if ("black".equals(theme)) { diff --git a/app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java b/app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java new file mode 100644 index 00000000..81695f53 --- /dev/null +++ b/app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java @@ -0,0 +1,132 @@ +/* + 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 2015 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.view; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import java.util.ArrayList; + +import github.daneren2005.dsub.R; +import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.service.MusicService; +import github.daneren2005.dsub.service.MusicServiceFactory; +import github.daneren2005.dsub.util.Constants; +import github.daneren2005.dsub.util.FileUtil; +import github.daneren2005.dsub.util.Util; + +public class AlbumListCountView extends UpdateView { + private final String TAG = AlbumListCountView.class.getSimpleName(); + + private TextView titleView; + private TextView countView; + private int albumListString; + private int startCount; + private int count = 0; + + public AlbumListCountView(Context context) { + super(context, false); + this.context = context; + LayoutInflater.from(context).inflate(R.layout.basic_count_item, this, true); + + titleView = (TextView) findViewById(R.id.basic_count_name); + countView = (TextView) findViewById(R.id.basic_count_count); + } + + protected void setObjectImpl(Object obj1, Object obj2) { + this.albumListString = (Integer) obj1; + titleView.setText(albumListString); + + SharedPreferences prefs = Util.getPreferences(context); + startCount = prefs.getInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0); + count = startCount; + update(); + } + + @Override + protected void updateBackground() { + try { + 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 + 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) { + // 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(); + } + } catch(Exception e) { + Log.w(TAG, "Failed to refresh most recent count", e); + } + } + + @Override + protected void update() { + // Update count display with appropriate information + if(count <= 0) { + countView.setVisibility(View.GONE); + } else { + String displayName; + if(count < 10) { + displayName = "0" + count; + } else { + displayName = "" + count; + } + + countView.setText(displayName); + countView.setVisibility(View.VISIBLE); + } + } + + @Override + public void onClick() { + SharedPreferences.Editor editor = Util.getPreferences(context).edit(); + editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0); + editor.commit(); + + count = 0; + update(); + } +} diff --git a/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java b/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java index d8111692..b5dad2d1 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java +++ b/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java @@ -25,9 +25,12 @@ public class BasicHeaderView extends UpdateView { TextView nameView; public BasicHeaderView(Context context) { + this(context, R.layout.basic_header); + } + public BasicHeaderView(Context context, int layout) { super(context, false); - LayoutInflater.from(context).inflate(R.layout.basic_header, this, true); + LayoutInflater.from(context).inflate(layout, this, true); nameView = (TextView) findViewById(R.id.item_name); } diff --git a/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java b/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java index 62d1672d..44831c60 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java +++ b/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java @@ -288,6 +288,10 @@ public class UpdateView extends LinearLayout { return checkable; } + public void onClick() { + + } + public static class UpdateViewHolder<T> extends RecyclerView.ViewHolder { private UpdateView updateView; private View view; diff --git a/app/src/main/res/layout/abstract_activity.xml b/app/src/main/res/layout/abstract_activity.xml index be65e437..56db1439 100644 --- a/app/src/main/res/layout/abstract_activity.xml +++ b/app/src/main/res/layout/abstract_activity.xml @@ -1,21 +1,22 @@ <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:fitsSystemWindows="true"> + <!-- The main content view --> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent"/> + <!-- The navigation drawer --> - <ListView android:id="@+id/left_drawer" - android:layout_width="240dp" - android:layout_height="match_parent" - android:layout_gravity="start" - android:choiceMode="singleChoice" - android:divider="@android:color/transparent" - android:dividerHeight="0dp" - android:background="?android:windowBackground"/> + <android.support.design.widget.NavigationView + android:id="@+id/left_drawer" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="start"/> </android.support.v4.widget.DrawerLayout> diff --git a/app/src/main/res/layout/abstract_fragment_activity.xml b/app/src/main/res/layout/abstract_fragment_activity.xml index 29fbc3b1..74a94111 100644 --- a/app/src/main/res/layout/abstract_fragment_activity.xml +++ b/app/src/main/res/layout/abstract_fragment_activity.xml @@ -15,9 +15,10 @@ <android.support.v7.widget.Toolbar android:id="@+id/main_toolbar" - style="?attr/actionBarStyle" android:layout_height="?attr/actionBarSize" - android:layout_width="match_parent"/> + android:layout_width="match_parent" + android:background="?attr/colorPrimary" + android:elevation="4dp"/> <include layout="@layout/abstract_fragment_container"/> </FrameLayout> @@ -30,13 +31,14 @@ <FrameLayout android:id="@+id/slide_up_swipe_target" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:background="?attr/colorPrimary"> <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:elevation="4dp" android:visibility="gone"/> <LinearLayout @@ -44,7 +46,8 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" style="@style/BasicButton" - android:orientation="horizontal"> + android:orientation="horizontal" + android:elevation="4dp"> <github.daneren2005.dsub.view.RecyclingImageView android:id="@+id/album_art" diff --git a/app/src/main/res/layout/album_list_header.xml b/app/src/main/res/layout/album_list_header.xml new file mode 100644 index 00000000..58af3353 --- /dev/null +++ b/app/src/main/res/layout/album_list_header.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/item_name" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:background="@android:color/transparent" + android:textColor="@color/cyan" + android:textStyle="bold" + android:paddingLeft="6dp" + android:paddingRight="6dp" + android:paddingTop="8dp" + android:paddingBottom="8dp"/> + + <CheckBox + android:id="@+id/item_checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/main.albums_per_folder" + android:layout_marginRight="6dp" + android:layout_gravity="right"/> +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/album_list_item.xml b/app/src/main/res/layout/album_list_item.xml index 67c052eb..c43e52a8 100644 --- a/app/src/main/res/layout/album_list_item.xml +++ b/app/src/main/res/layout/album_list_item.xml @@ -3,7 +3,8 @@ android:id="@id/drag_handle" android:orientation="horizontal" android:layout_width="fill_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:background="?attr/selectableItemBackground"> <RelativeLayout android:layout_width="@dimen/AlbumArt.Small" diff --git a/app/src/main/res/layout/basic_count_item.xml b/app/src/main/res/layout/basic_count_item.xml index 08d276db..7f71c5a6 100644 --- a/app/src/main/res/layout/basic_count_item.xml +++ b/app/src/main/res/layout/basic_count_item.xml @@ -2,7 +2,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:background="@android:color/transparent" + android:background="?attr/selectableItemBackground" android:minHeight="50dip"> <TextView diff --git a/app/src/main/res/layout/download_activity.xml b/app/src/main/res/layout/download_activity.xml deleted file mode 100644 index 017e4013..00000000 --- a/app/src/main/res/layout/download_activity.xml +++ /dev/null @@ -1,4 +0,0 @@ -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/fragment_container" - android:layout_width="match_parent" - android:layout_height="match_parent" />
\ 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 index 00441b73..fe0a9f2d 100644 --- a/app/src/main/res/layout/drawer_header.xml +++ b/app/src/main/res/layout/drawer_header.xml @@ -3,34 +3,54 @@ android:layout_width="match_parent" android:layout_height="178dp" android:orientation="vertical" - android:weightSum="1"> + android:weightSum="1" + android:background="?attr/selectableItemBackground"> <LinearLayout android:layout_width="match_parent" android:layout_height="56dp" - android:orientation="vertical" + android:orientation="horizontal" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"> - <TextView - android:id="@+id/header_server_name" + <LinearLayout + android:orientation="vertical" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="16dp" - android:textColor="?android:textColorPrimary" - android:textSize="14sp" - android:textStyle="bold"/> + android:layout_height="wrap_content"> + + <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> + + <View + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="1"/> - <TextView - android:id="@+id/header_user_name" + <ImageView + android:id="@+id/header_select_image" + android:src="?attr/select_server" + android:layout_gravity="center_vertical" 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"/> + android:paddingRight="20dp"/> </LinearLayout> <de.hdodenhof.circleimageview.CircleImageView diff --git a/app/src/main/res/layout/drawer_list_item.xml b/app/src/main/res/layout/drawer_list_item.xml deleted file mode 100644 index 607b3658..00000000 --- a/app/src/main/res/layout/drawer_list_item.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingTop="8dip" - android:paddingBottom="9dip"> - - <ImageView - android:id="@+id/drawer_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left|center_vertical" - android:paddingTop="1dip" - android:paddingBottom="1dip" - android:paddingRight="8dip" - android:paddingLeft="10dip"/> - - <TextView - android:id="@+id/drawer_name" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:textColor="?android:textColorPrimary" - android:textAppearance="?android:attr/textAppearanceLarge" - style="DSub.TextViewStyle"/> -</LinearLayout> diff --git a/app/src/main/res/layout/main_buttons.xml b/app/src/main/res/layout/main_buttons.xml deleted file mode 100644 index 95a60409..00000000 --- a/app/src/main/res/layout/main_buttons.xml +++ /dev/null @@ -1,157 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="wrap_content"> - - <LinearLayout - android:id="@+id/main_select_server" - android:orientation="horizontal" - android:paddingTop="2dip" - android:paddingBottom="2dip" - android:paddingLeft="6dp" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeight"> - - <ImageView - android:src="?attr/select_server" - android:layout_gravity="center_vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content"/> - - <LinearLayout - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - - <TextView android:id="@+id/main.select_server_1" - android:text="@string/main.select_server" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="10dip" - android:layout_marginTop="6dip" - android:textAppearance="?android:attr/textAppearanceLarge"/> - - <TextView android:id="@+id/main.select_server_2" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="10dip" - android:textAppearance="?android:attr/textAppearanceSmall"/> - - </LinearLayout> - </LinearLayout> - - <TextView - android:id="@+id/main_offline" - android:text="@string/main.offline" - android:drawablePadding="12dip" - android:drawableLeft="?attr/offline_icon" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center_vertical" - android:paddingLeft="6dp" - android:paddingBottom="4dp" - android:minHeight="50dip"/> - - <LinearLayout - android:id="@+id/main_albums" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <TextView - android:text="@string/main.albums_title" - style="@style/MainAlbumButtonLabel" - android:layout_width="0dp" - android:layout_weight="1" - android:layout_height="fill_parent"/> - - <CheckBox - android:id="@+id/main_albums_per_folder" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/main.albums_per_folder" - android:layout_marginRight="6dp" - android:layout_gravity="right"/> - </LinearLayout> - - <TextView - android:id="@+id/main_video_section" - android:text="@string/main.videos" - style="@style/MainAlbumButtonLabel" - android:layout_width="0dp" - android:layout_weight="1" - android:layout_height="fill_parent"/> - - <LinearLayout - android:id="@+id/main_albums_newest" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:minHeight="46dip"> - - <TextView - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:text="@string/main.albums_newest" - style="@style/MainAlbumButton"/> - - <TextView - android:id="@+id/main_albums_recent_count" - android:layout_width="32dp" - android:layout_height="32dp" - android:layout_marginRight="12dp" - android:background="@drawable/ic_number_border" - android:focusable="false" - android:paddingRight="10dp" - android:layout_marginLeft="20px" - android:layout_marginBottom="4px" - android:text="99" - android:textAppearance="?android:attr/textAppearanceSmallPopupMenu" - android:textSize="11sp" - android:gravity="right|center_vertical" - android:layout_gravity="center_vertical" - android:visibility="gone"/> - </LinearLayout> - - <TextView - android:id="@+id/main_albums_recent" - android:text="@string/main.albums_recent" - style="@style/MainAlbumButton"/> - <TextView - android:id="@+id/main_albums_frequent" - android:text="@string/main.albums_frequent" - style="@style/MainAlbumButton"/> - <TextView - android:id="@+id/main_albums_highest" - android:text="@string/main.albums_highest" - style="@style/MainAlbumButton"/> - <TextView - android:id="@+id/main_albums_starred" - android:text="@string/main.albums_starred" - style="@style/MainAlbumButton"/> - <TextView - android:id="@+id/main_albums_genres" - android:text="@string/main.albums_genres" - style="@style/MainAlbumButton"/> - <TextView - android:id="@+id/main_albums_year" - android:text="@string/main.albums_year" - style="@style/MainAlbumButton"/> - <TextView - android:id="@+id/main_albums_random" - android:text="@string/main.albums_random" - style="@style/MainAlbumButton"/> - <TextView - android:id="@+id/main_albums_alphabetical" - android:text="@string/main.albums_alphabetical" - style="@style/MainAlbumButton"/> - - <TextView - android:id="@+id/main_videos" - android:text="@string/main.videos" - style="@style/MainAlbumButton"/> - -</LinearLayout> - diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml new file mode 100644 index 00000000..89355cb7 --- /dev/null +++ b/app/src/main/res/layout/settings_activity.xml @@ -0,0 +1,16 @@ +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <android.support.v7.widget.Toolbar + android:id="@+id/main_toolbar" + android:layout_height="?attr/actionBarSize" + android:layout_width="match_parent" + android:background="?attr/colorPrimary" + android:elevation="4dp"/> + + <FrameLayout + android:id="@+id/fragment_container" + android:layout_width="match_parent" + android:layout_height="match_parent" /> +</FrameLayout>
\ No newline at end of file diff --git a/app/src/main/res/menu/drawer_navigation.xml b/app/src/main/res/menu/drawer_navigation.xml new file mode 100644 index 00000000..88ecd920 --- /dev/null +++ b/app/src/main/res/menu/drawer_navigation.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <group android:checkableBehavior="single"> + <item + android:id="@+id/drawer_home" + android:icon="?attr/drawerHome" + android:title="@string/button_bar.home"/> + <item + android:id="@+id/drawer_library" + android:icon="?attr/drawerLibrary" + android:title="@string/button_bar.browse"/> + <item + android:id="@+id/drawer_playlists" + android:icon="?attr/drawerPlaylists" + android:title="@string/button_bar.playlists"/> + <item + android:id="@+id/drawer_podcasts" + android:icon="?attr/drawerPodcasts" + android:title="@string/button_bar.podcasts"/> + <item + android:id="@+id/drawer_bookmarks" + android:icon="?attr/drawerBookmarks" + android:title="@string/button_bar.bookmarks"/> + <item + android:id="@+id/drawer_shares" + android:icon="?attr/drawerShares" + android:title="@string/button_bar.shares"/> + <item + android:id="@+id/drawer_chat" + android:icon="?attr/drawerChat" + android:title="@string/button_bar.chat"/> + <item + android:id="@+id/drawer_admin" + android:icon="?attr/drawerAdmin" + android:title="@string/button_bar.admin"/> + <item + android:id="@+id/drawer_downloading" + android:icon="?attr/drawerDownloading" + android:title="@string/button_bar.downloading" + android:visible="false"/> + </group> + + <group + android:id="@+id/drawer_bottom" + android:checkableBehavior="single"> + + <item + android:id="@+id/drawer_settings" + android:title="@string/menu.settings"/> + </group> +</menu>
\ No newline at end of file diff --git a/app/src/main/res/values-v21/themes.xml b/app/src/main/res/values-v21/themes.xml new file mode 100644 index 00000000..acd117b5 --- /dev/null +++ b/app/src/main/res/values-v21/themes.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="Theme.DSub.Light" parent="Theme.DSub.Light.Base"> + <item name="android:windowTranslucentStatus">true</item> + </style> + + <style name="Theme.DSub.Dark" parent="Theme.DSub.Dark.Base"> + <item name="android:windowTranslucentStatus">true</item> + </style> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 37b15d12..d876ecdb 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -1,18 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string-array name="drawerItems"> - <item>@string/button_bar.home</item> - <item>@string/button_bar.browse</item> - <item>@string/button_bar.playlists</item> - <item>@string/button_bar.podcasts</item> - <item>@string/button_bar.bookmarks</item> - <item>@string/button_bar.shares</item> - <item>@string/button_bar.chat</item> - <item>@string/button_bar.admin</item> - <item>@string/button_bar.downloading</item> - <item>@string/menu.settings</item> - </string-array> - <string-array name="drawerItemsDescriptions"> <item>Home</item> <item>Artist</item> @@ -46,32 +33,6 @@ <item>Chat</item> </string-array> - <array name="drawerItemIconsLight"> - <item>@drawable/main_offline_light</item> - <item>@drawable/ic_menu_library_light</item> - <item>@drawable/ic_menu_playlist_light</item> - <item>@drawable/ic_menu_podcast_light</item> - <item>@drawable/ic_menu_bookmark_light</item> - <item>@drawable/ic_menu_share_light</item> - <item>@drawable/ic_menu_chat_light</item> - <item>@drawable/ic_menu_admin_light</item> - <item>@drawable/ic_menu_download_light</item> - <item>@drawable/ic_menu_settings_light</item> - </array> - - <array name="drawerItemIconsDark"> - <item>@drawable/main_offline_dark</item> - <item>@drawable/ic_menu_library_dark</item> - <item>@drawable/ic_menu_playlist_dark</item> - <item>@drawable/ic_menu_podcast_dark</item> - <item>@drawable/ic_menu_bookmark_dark</item> - <item>@drawable/ic_menu_share_dark</item> - <item>@drawable/ic_menu_chat_dark</item> - <item>@drawable/ic_menu_admin_dark</item> - <item>@drawable/ic_menu_download_dark</item> - <item>@drawable/ic_menu_settings_dark</item> - </array> - <string-array name="themeValues"> <item>light</item> <item>dark</item> diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 9667117c..3db670e6 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -27,6 +27,16 @@ <attr name="rating_good" format="reference"/> <attr name="radio" format="reference"/> <attr name="drawerItemsIcons" format="reference"/> + <attr name="drawerHome" format="reference"/> + <attr name="drawerLibrary" format="reference"/> + <attr name="drawerPlaylists" format="reference"/> + <attr name="drawerPodcasts" format="reference"/> + <attr name="drawerBookmarks" format="reference"/> + <attr name="drawerShares" format="reference"/> + <attr name="drawerChat" format="reference"/> + <attr name="drawerAdmin" format="reference"/> + <attr name="drawerDownloading" format="reference"/> + <attr name="drawerSettings" format="reference"/> <declare-styleable name="SeekBarPreference"> <attr name="min" format="integer"/> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 50d2d171..ecba7592 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,8 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="Theme.DSub.Light" parent="@style/Theme.AppCompat.Light"> - <item name="actionBarStyle">@style/Widget.DSub.ActionBarStyle.Light</item> - <item name="android:actionBarStyle">@style/Widget.DSub.ActionBarStyle.Light</item> + <style name="Theme.DSub.Light.Base" parent="@style/Theme.AppCompat.Light"> <item name="offline_icon">@drawable/main_offline_light</item> <item name="media_button_backward">@drawable/media_backward_light</item> <item name="media_button_forward">@drawable/media_forward_light</item> @@ -29,15 +27,24 @@ <item name="rating_bad">@drawable/ic_action_rating_bad_light</item> <item name="rating_good">@drawable/ic_action_rating_good_light</item> <item name="radio">@drawable/ic_menu_radio_light</item> - <item name="drawerItemsIcons">@array/drawerItemIconsLight</item> + <item name="drawerHome">@drawable/main_offline_light</item> + <item name="drawerLibrary">@drawable/ic_menu_library_light</item> + <item name="drawerPlaylists">@drawable/ic_menu_playlist_light</item> + <item name="drawerPodcasts">@drawable/ic_menu_podcast_light</item> + <item name="drawerBookmarks">@drawable/ic_menu_bookmark_light</item> + <item name="drawerShares">@drawable/ic_menu_share_light</item> + <item name="drawerChat">@drawable/ic_menu_chat_light</item> + <item name="drawerAdmin">@drawable/ic_menu_admin_light</item> + <item name="drawerDownloading">@drawable/ic_menu_download_light</item> + <item name="drawerSettings">@drawable/ic_menu_settings_light</item> <item name="android:textViewStyle">@style/DSub.TextViewStyle</item> <item name="android:buttonStyle">@style/DSub.ButtonStyle.Light</item> <item name="drawerArrowStyle">@style/DSub.DrawerArrow</item> + <item name="colorPrimary">@color/cyan</item> + <item name="colorPrimaryDark">@color/cyan</item> <item name="colorAccent">@color/cyan</item> </style> - <style name="Theme.DSub.Dark" parent="@style/Theme.AppCompat"> - <item name="actionBarStyle">@style/Widget.DSub.ActionBarStyle.Dark</item> - <item name="android:actionBarStyle">@style/Widget.DSub.ActionBarStyle.Dark</item> + <style name="Theme.DSub.Dark.Base" parent="@style/Theme.AppCompat"> <item name="offline_icon">@drawable/main_offline_dark</item> <item name="media_button_backward">@drawable/media_backward_dark</item> <item name="media_button_forward">@drawable/media_forward_dark</item> @@ -64,12 +71,27 @@ <item name="rating_bad">@drawable/ic_action_rating_bad_dark</item> <item name="rating_good">@drawable/ic_action_rating_good_dark</item> <item name="radio">@drawable/ic_menu_radio_dark</item> - <item name="drawerItemsIcons">@array/drawerItemIconsDark</item> + <item name="drawerHome">@drawable/main_offline_dark</item> + <item name="drawerLibrary">@drawable/ic_menu_library_dark</item> + <item name="drawerPlaylists">@drawable/ic_menu_playlist_dark</item> + <item name="drawerPodcasts">@drawable/ic_menu_podcast_dark</item> + <item name="drawerBookmarks">@drawable/ic_menu_bookmark_dark</item> + <item name="drawerShares">@drawable/ic_menu_share_dark</item> + <item name="drawerChat">@drawable/ic_menu_chat_dark</item> + <item name="drawerAdmin">@drawable/ic_menu_admin_dark</item> + <item name="drawerDownloading">@drawable/ic_menu_download_dark</item> + <item name="drawerSettings">@drawable/ic_menu_settings_dark</item> <item name="android:textViewStyle">@style/DSub.TextViewStyle</item> <item name="android:buttonStyle">@style/DSub.ButtonStyle.Dark</item> <item name="drawerArrowStyle">@style/DSub.DrawerArrow</item> + <item name="colorPrimary">@color/cyan</item> + <item name="colorPrimaryDark">@color/cyan</item> <item name="colorAccent">@color/cyan</item> </style> + <style name="Theme.DSub.Light" parent="Theme.DSub.Light.Base"> + </style> + <style name="Theme.DSub.Dark" parent="Theme.DSub.Dark.Base"> + </style> <style name="Theme.DSub.Black" parent="Theme.DSub.Dark"> <item name="android:windowBackground">@android:color/black</item> </style> @@ -93,20 +115,6 @@ <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> - <item name="android:background">@android:color/transparent</item> - <item name="backgroundStacked">@android:color/transparent</item> - <item name="android:backgroundStacked">@android:color/transparent</item> - </style> - - <style name="Widget.DSub.ActionBarStyle.Dark" parent="Widget.AppCompat.ActionBar.Solid"> - <item name="background">@android:color/transparent</item> - <item name="android:background">@android:color/transparent</item> - <item name="backgroundStacked">@android:color/transparent</item> - <item name="android:backgroundStacked">@android:color/transparent</item> - </style> <style name="DSub.TextViewStyle" parent="android:Widget.TextView"> </style> |